归并排序,其主要思想是通过递归来分解原有数组,通过使分解后的数组有序,然后合并数组从而达到排序的结果。因此我们不难写出整个归并排序的过程。
public static void mergeSort(int a[],int left,int right,int p[]){
if(left >= right){
return;
}else{
int mid = (right + left) >> 1;
mergeSort(a,left,mid,p);
mergeSort(a,mid+1,right,p);
mergeArray(a,left,mid,right,p);
}
}
这里定义了一个临时数组P,作用是将其临时比较后的数组存放到该数组中。通过mergeSort方法,来使原数组进行分解,这里进行递归调用。从而使分解后的两个数组里面最后只剩下一个元素。比较两个数组中的这个元素,谁大就将其先存放到临时数组P中,如果比较完毕后,其中一个数组已经为空,另外一个数组还有数据,那么将其元素直接复制到临时数组中。
分解完毕后,就要进行合并了。我们定义了mergeArray函数来进行合并。
public static void mergeArray(int a[],int first,int mid,int last,int temp[]){
int i = first, j = mid + 1;
int m = mid, n = last;
int k = 0;
while (i <= m && j <= n)
{
if (a[i] <= a[j])
temp[k++] = a[i++];
else
temp[k++] = a[j++];
}
while (i <= m)
temp[k++] = a[i++];
while (j <= n)
temp[k++] = a[j++];
for (i = 0; i < k; i++)
a[first + i] = temp[i];
}
在合并两个数组的过程中,使用while循环,这个while语句值得思考,两个数组,用其中一个数组的元素和另外一个进行循环比较,将较小的值存放到temp数组中,然后再比较下一个。其中一个数组比较完毕后,另一个数组中剩余的数据直接复制到临时数组中。
看看完整的代码。
package com.bplead.sort;
public class MergeSort {
public static void mergeSort(int a[],int left,int right,int p[]){
if(left >= right){
return;
}else{
int mid = (right + left) >> 1;
mergeSort(a,left,mid,p);
mergeSort(a,mid+1,right,p);
mergeArray(a,left,mid,right,p);
}
}
public static void mergeArray(int a[],int first,int mid,int last,int temp[]){
int i = first, j = mid + 1;
int m = mid, n = last;
int k = 0;
while (i <= m && j <= n)
{
if (a[i] <= a[j])
temp[k++] = a[i++];
else
temp[k++] = a[j++];
}
while (i <= m)
temp[k++] = a[i++];
while (j <= n)
temp[k++] = a[j++];
for (i = 0; i < k; i++)
a[first + i] = temp[i];
prt(temp);
}
private static void prt(int a[]){
for(int i=0;i<a.length;i++)
System.out.print(a[i] + " ");
System.out.println();
}
public static void main(String[] args) {
int a[] = {21,42,36,35,11,23,10,98,22,8,76,43,29,66,64,1};
int p[] = new int[a.length];
mergeSort(a,0,a.length-1,p);
prt(p);
}
}
运行的结果如下:
21 42 0 0 0 0 0 0 0 0 0 0 0 0 0 0
35 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0
21 35 36 42 0 0 0 0 0 0 0 0 0 0 0 0
11 23 36 42 0 0 0 0 0 0 0 0 0 0 0 0
10 98 36 42 0 0 0 0 0 0 0 0 0 0 0 0
10 11 23 98 0 0 0 0 0 0 0 0 0 0 0 0
10 11 21 23 35 36 42 98 0 0 0 0 0 0 0 0
8 22 21 23 35 36 42 98 0 0 0 0 0 0 0 0
43 76 21 23 35 36 42 98 0 0 0 0 0 0 0 0
8 22 43 76 35 36 42 98 0 0 0 0 0 0 0 0
29 66 43 76 35 36 42 98 0 0 0 0 0 0 0 0
1 64 43 76 35 36 42 98 0 0 0 0 0 0 0 0
1 29 64 66 35 36 42 98 0 0 0 0 0 0 0 0
1 8 22 29 43 64 66 76 0 0 0 0 0 0 0 0
1 8 10 11 21 22 23 29 35 36 42 43 64 66 76 98
1 8 10 11 21 22 23 29 35 36 42 43 64 66 76 98
我这里有一个问题一直没想明白。就是在mergeArray中,为什么需要将临时数组中的值复制到原数组中。也就是
for (i = 0; i < k; i++)
a[first + i] = temp[i];
这一段代码的作用是什么,当我注释掉这段代码后,排序失败。请路过的高手指示一下。多谢。