归并排序,其主要思想是通过递归来分解原有数组,通过使分解后的数组有序,然后合并数组从而达到排序的结果。因此我们不难写出整个归并排序的过程。
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];
这一段代码的作用是什么,当我注释掉这段代码后,排序失败。请路过的高手指示一下。多谢。