算法第四版:归并排序及其改进(java实现)
三项改进:
-
如果子数组较小(7左右),则采用速度更快的插入排序;
-
检测待归并的两个子数组是否已经有序,如果已经有序则直接复制进a[ ];
-
通过再递归中交换参数来避免每次归并时都要复制数组到辅助数组。
下面展示同样高亮的代码片
.
public class Merge {
private static final int CUTOFF = 7;
public static void sort(Comparable[] a){
// Comparable[] aux = new Comparable[a.length];
Comparable[] aux = a.clone(); //初始化aux,为了后面把它当原始数组a[]用
sort(a,aux,0,a.length-1);
}
private static void sort(Comparable[] a, Comparable[] aux,int lo, int hi){
int mid = lo + (hi -lo) / 2;
// if(hi <= lo)
// return;
if(hi <= lo + CUTOFF - 1){ //小数组使用插入排序
insertionSort(a, lo, hi);
return;
}
sort(aux,a,lo,mid);
sort(aux,a,mid+1,hi);
if(!less(aux[mid+1],aux[mid])){ //如果数组已经有序则直接复制,不再merge
System.arraycopy(aux, lo, a, lo, hi-lo+1);
return;
}
merge(a,aux,lo,mid,hi);
}
private static void insertionSort(Comparable[] a, int lo, int hi) {
for (int i = lo; i <= hi; i++) {
Comparable temp = a[i];
int j = i-1;
for(; j >= lo && less(temp,a[j]); j--){
a[j+1] = a[j];
}
a[j+1] = temp;
}
}
private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi){
int i = lo, j = mid+1;
/*for(int k = lo; k <= hi; k++){
aux[k] = a[k];
}
for(int k = lo; k<= hi; k++){
if(i>mid)
a[k] = aux[j++];
else if(j>hi)
a[k] = aux[i++];
else if(less(aux[j],aux[i]))
a[k] = aux[j++];
else
a[k] = aux[i++];
} */
//消除数组复制
for(int k = lo; k<= hi; k++){
if (i > mid) a[k] = aux[j++];
else if(j > hi) a[k] = aux[i++];
else if(less(aux[j],aux[i])) a[k] = aux[j++];
else a[k] = aux[i++];
}
}
private static boolean less(Comparable v, Comparable w) {
return v.compareTo(w) < 0;
}
private static void exch(Comparable[] a, int i, int j) {
Comparable t = a[i];
a[i] = a[j];
a[j] = t;
}
public static void show(Comparable[] a){
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
}
public static boolean isSorted(Comparable[] a){
for (int i = 1; i < a.length; i++) {
if(less(a[i], a[i-1]))
return false;
}
return true;
}
public static void main(String[] args){
Integer[] a = new Integer[]{5, 3, 2, 4, 1, 10, 7, 8, 6, 9};
sort(a);
show(a);
System.out.println();
}
}