算法排序-归并排序

107 阅读2分钟

归并排序

归并排序,是把一个大问题分解成多个子小问题的重要例子。一个无序的队列,可以分为若干个 更小规模的无序队列进行排序后。

如何拆分为更小子问题

简单做法就是对半一分为二,直到无法分为止。

 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)

稳定性

不稳定,相同值存在交换位置可能性