思想:将一个数组一分为二,二分为四,依此将其不断分裂,除最后一行的数组,都一个数组都有两个子数组组成。将两个子数组排序并归并成一个大的数组就是归并排序。
原地归并:
public static void merge(Comparable[] a,int lo,int mid,int hi)//在左边和右边有序的情况下排序
{//将lo到hi进行排序
int i=lo,j=mid+1;
for(int k=lo;k<=hi;k++)
auk[k]=a[k];//将lo到hi这段复制到auk中
for(int k=lo;k<=hi;k++)
if(less(auk[j],auk[i]))如果右边的小于左边的,右边进数组
a[k]=auk[j++];
else if(less(auk[i]<auk[j])左边小于右边,左边进数组
a[k]=auk[i++];
else if(j>hi)右边的排完了,只排左边
a[k]=a[i++];
else a[k]=a[j++];
}
自顶向下归并
public class Merge
{
private static Comparable[] auk;
public static void sort(Comparable[]a)
{
aux=new Comparable[a.length];//为数组auk开辟空间
sort(a,0,a.leng.th-1);}
private static void sort(Comparable[]a,int lo,int hi)//对hi,到lo进行排序
{int mid=hi/2+lo/2;
sort(a,lo,mid);将左边排序
sort(a,mid+1,hi);将右边排序
merge(a,lo,mid,hi);
}
自低向上排序
设置尺寸sz=1;
每次使两个由sz大小组成的小数组有序,直至排完
令sz=2*sz,重复以上步骤。
重复sz=2*sz,直至所有小数组变成了一个大的有序数组
public class MergeBU
{
private static Comparable []aux;//归并所需的辅助数组
int N=a.length;
auk=new Comparable[N];
for(int sz=1;sz<N;sz=2*sz)
for(int lo=0;lo<N-sz;lo+=2*sz)
merge(a,lo,lo+sz-1,Main.min(lo+sz*2-1,N-1));//这个Main.min是因为可能数组不是偶数,即可能最大的两个子数组的大小可能相差1
}
呼……
打了一个半小时,终于完了,嘻嘻!