归并排序
归并排序,是把一个大问题分解成多个子小问题的重要例子。一个无序的队列,可以分为若干个 更小规模的无序队列进行排序后。
如何拆分为更小子问题
简单做法就是对半一分为二,直到无法分为止。
public void partition(int[] data,int left,int right){
if(left>=right){
return;
}
int mid=(right-left)/2+leftIndex;
partition(data,left,mid);//左一半
partition(data,mid+1,right);//右一半
mergeSort(data,left,mid,right);//排序
}
何为归并?
想象一下两个有序的队列,你如何将其归并成一个队列呢?为了更好描述排序合并规则,分别称为左队列,和右队列,以及总队列。 左队列和右队列依次比较,较小队列拿出一个元素放入到总队列中,同时下个元素和较大的那个元素比较。
public void mergeSort(int[] data,int left,int mid,int right){
int[] total=new int[right-left+1];//总队列
int tIndex=0;
int lIndex=left;
int rIndex=mid+1;
while(tIndex<total.length){
if(lIndex>mid){//左对列排净了
total[tIndex++]=data[rIndex++];
} else if(rIndex>right){右对列排净了
total[tIndex++]=data[lIndex++];
} else if(data[lIndex]<data[rIndex]){//左<右,取左
total[tIndex++]=data[lIndex++];
} else {
total[tIndex++]=data[rIndex++];
}
}
System.arrayCopy(total,0,data,left,total.length);//复制到data中
}
时间复杂度
我们仅仅考虑比较次数,f(N)=f(N/2)+f(N/2)+N,并令N=2^n,则可以很轻松得出
f(2^n)=f(2^(n-1))+f(2^(n-1))+2^n
f(2^n)=f(2^(n-2))+f(2^(n-2))+2^n+2^n
f(2^n)=f(2^(n-3))+f(2^(n-3))+2^n+2^n+2^n
那么不难看出有n个2^n相加,求得n=ln(2^n),所以f(2^n)=2^nln(2^n),将N=2^n,就可以推出f(N)=Nln(N)
稳定性
不稳定,相同值存在交换位置可能性