该算法思路如下:
1、新开辟一个辅助数组,方便归并时使用,由于归并时需要辅助空间,又防止在每次归并时都开辟一个新数组,所以提前申请一个同样大小空间的数组
2、将整个数组二分,分别递归排序前半部分与后半部分,之后将两部分归并
以上步骤二是分治法的典型思路
当我们的排序不断递归下去时,直到被拆分的数组中只有一个元素时,这时候数组便是有序的,之后和另一个相邻元素归并,。。直到前半部分有序,后半部分同样递归与归并,之后前半部分与后半部分归并,形成整个有序的一个数组。
归并的思路确实是相当精妙的。。。
以下为java版本的实现
public class merge_sort {
//贵宾用的辅助数组
private static int[] aux;
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] intarry={0,12,1,90,2,11,9,4,6,13,5,3,33};
aux = new int[intarry.length];
mergesort(intarry,0,intarry.length-1);
for(int i:intarry){
System.out.print(i);
System.out.print(",");
}
}
public static void mergesort(int[] intarry,int low,int high){
if(high==low) return;
int mid=low+(high-low)/2;
mergesort(intarry,low,mid);
mergesort(intarry,mid+1,high);
merge(intarry,low,mid,high);
}
/***
* 原地归并
* @param intarrya 数组
* @param low 归并头节点
* @param mid 归并的分割点
* @param high 归并的尾节点
*
*/
public static void merge(int[] intarry,int low,int mid,int high){
int i=low;
int j=mid+1;
for(int k=low;k<=high;k++){
aux[k]=intarry[k];
}
for(int k=low;k<=high;k++){
if(i>mid){
intarry[k] = aux[j++];
}else if(j>high){
intarry[k] = aux[i++];
}else if(aux[i]<aux[j]){
intarry[k]=aux[i++];
}else{
intarry[k]=aux[j++];
}
}
}
}
其实归并的实现还有一种自底向上的实现与自顶向下的区别如下
自顶向下:
乱序5,4,2,1,6,3>>4,5,2,1,6,3>>4,5,1,2,6,3>>1,2,4,5,6,3>>1,2,4,5,3,6>>1,2,3,4,5,6
自底向上
乱序5,4,2,1,6,3>>4,5,2,1,6,3>>4,5,1,2,6,3>>4,5,1,2,3,6>>1,2,4,5,3,6>>1,2,3,4,5,6