时间复杂度O(nlogn)

两个一组排序

四个一组排序

······

直到只剩下一组,2n>数组长度

  1. 递归实现

    反复将当前区间[left,right]分为两半,

    对两个子区间[left,mid]和[mid+1,right]分别递归进行归并排序,

    然后将两个已经有序的子区间,合并,排序,返回

    void 合并并排序(int *A,int L1,int R1,int L2,int R2){
    
            int i=L1,j=L2;
    
            int temp[maxn],index=0;//temp为临时数组用于存放当前两个子分区的排序结果,index为下标
    
            while(i<=R1&&j<=R2){//谁大把谁放进temp
    
                if(A[i]<=A[j]) temp[index++]=A[i++];
    
                else temp[index++]=A[j++];
    
            }
    
            //之前循环退出时,并未处理所有元素,分别试探看哪个还有剩余,也都放进去
    
            while(i<=R1) temp[index++]=A[i++];
    
            while(j<=R2) temp[index++]=A[j++];
    
            //把temp中的临时,放入原来数组
    
            for(int i=0;i<index;i++){
    
                A[L1+i]=temp[i];
    
            }
    
    }
    
    void mergeSort(int A[],int left,int right){
    
        if(left>=right) return;//返回条件,只剩一个元素
    
        int mid=(left+right)/2;
    
        mergeSort(A,left,mid);
    
        mergeSort(A.mid+1,left);
    
        合并并排序(A,left,mid,mid+1,right);
    
    }
    
  2. 非递归实现

步长值初始为2

步长值增加

将数组中每步长值个元素分为一组,进行内部排序

​ 把左step/2个元素,与右step/2个元素合并,

​ 而,如果元素个数不超过step/2,则不操作。

void mergeSort(int A[]){

    for(int step=2;step/2<=n;step*=2){//多种步长

        for(int i=1;i<=n;i+=step){//每种步长,如果只要显示排序产生的结果,此处可以直接用sort

            int mid=i+step/2-1;//将每组分为两份,i从1开始,所以-1

            if(mid+1<=n){

                合并和排序(A,i,mid,mid+1,min(i+step-1,n));//min处理最后一种情况

            }

        }

    }

}