归并排序即是将两个有序的数组归并成一个更大的有序数组。如[1,3,5] 与 [2,4,6]归并为[1,2,3,4,5,6]。
或[1,3,5, 2,4,6]归并成[1,2,3,4,5,6]。
一种实现方法是将两个有序数组中的元素按大小排列进第三个数组中。实现代码如下:
public static void merge(int[] a, int lo, int mid, int hi) { int[] aux = new int[a.length]; // Copy elements from a[] to aux[] for(int i=lo; i<=hi; i++) { aux[i] = a[i]; } int i = lo; int j = mid + 1; for(int k=lo; k<=hi; k++) { if(i>mid) // The first array done a[k] = aux[j++]; else if(j>hi) // The second array done a[k] = aux[i++]; else if(aux[i] < aux[j]) a[k] = aux[i++]; else a[k] = aux[j++]; } }
自顶向下的归并排序
将数组a[lo...hi]分成两个子数组a[lo...mid]与a[mid+1...hi],两个子数组分别排序后进行归并。
子数组又可以继续向下分成两个子数组,直到每个子数组只有一个元素,对只有一个元素的两个子数组可以归并排序。
实现代码如下:
public static void topToDown(int[] a, int lo, int hi) { if (hi<=lo) return; int mid = lo + (hi-lo)/2; topToDown(a, lo, mid); topToDown(a, mid+1, hi); merge(a, lo, mid, hi); } public static void topToDown(int[] a) { topToDown(a, 0, a.length - 1); }
对于a[0...15]分析如下:
对于包含4个元素的数组a(a[0],a[1],a[2],a[3] )执行顺序如下:
sort(a,0,3)
sort(a,0,1)
sort(a,0,0) 此时不满足(hi>=lo)返回到sort(a,0,1)函数中,执行下一句
执行sort(a,1,1)不满足(hi>=lo)返回到sort(a,0,1)函数中
执行merge(a,0,0,1),sort(a,0,1)函数执行结束,返回到函数sort(a,0,3)中
sort(a,2,3)
sort(a,2,2)此时不满足(hi>=lo)返回到sort(a,2,3)函数中,执行下一句
sort(a,3,3)不满足(hi>=lo)返回到sort(a,2,3)函数中,执行下一句
执行merge(a,2,2,3),sort(a,2,3)函数执行结束,返回到函数sort(a,0,3)中
执行merge(a,0,1,3); sort(a,0,3)执行结束。
算法复杂度:
自底向上的归并排序
先归并子数组,再对子数组进行归并。
实现代码如下:
public static void downToTop(int[] a) { int N = a.length; for (int size=1; size<N; size+=size) { for (int lo=0; lo<N-size; lo+=size+size) { merge(a, lo, lo+size-1, Math.min(lo+size+size-1, N-1)); } } }
实例如下:
算法复杂度