归并排序的递归以及迭代两种实现和优化

本文主要探讨归并排序的递归以及迭代两种实现和优化

归并排序MergeSort
是一种经典而高效的排序算法,是一种采用分而治之(devide and conquer)方法的一个典型应用。
假使要得到一个有序完全有序序列,可以使构成其的两个子序列有序,然后在将它们合并;若使子序列有序,则应使子序列间断有序。这样的方法叫做二路归并。

具体的算法思想和复杂度可以参考:这一篇

本文着重介绍归并排序的两种实现,一种是递归实现,另外一种是迭代实现。
首先介绍其递归实现,有一点值得留心,就是对于排序区间是开区间还是闭区间:

    template <typename T>
    void merge(T arr[], int lo, int mi, int hi){
//        cout<<"merging ["<<lo<<","<<mi<<"] + ["<<"["<<mi+1<<","<<hi<<"]"<<endl;
        //合并的过程,开辟额外的存储空间
        //[lo,mi), [mi,hi) 合并
//        T C[lc];
//        for (int i = 0; i <lc ; ++i) {
//            C[i]=arr[mi+1+i];
//        }

//        T* A=arr+lo;
//        int lb=mi-lo;
//        T* B=new T[lb];
//        for (int i = 0; i < lb;  B[i]=A[i++]);//前半段子向量
//
//        int lc=hi-mi;//向量的后半段
//        T* C=arr+mi;
//        for (int i=0, j=0, k=0; (j<lb)||(k<lc); ){
//            //cout<<"i="<<i<<"j="<<j<<" k="<<k<<endl;
//            if ( ( j < lb ) && ( ! ( k < lc ) || ( B[j] <= C[k] ) ))
//                A[i++]=B[j++];//前半段比较小
//            if ( (k<lc) &&( !( j<lb )|| ( C[k]<B[j] )))
//                A[i++]=C[k++];//后半段比较小
//        }
//
//        delete[] B;

        //闭区间
        T* A=arr+lo;
        int lb=mi-lo+1;//+1
        T* B=new T[lb];
        for (int i = 0; i < lb;  B[i]=A[i++]);//前半段子向量

        int lc=hi-mi;//向量的后半段 [mi+1, hi]
        T* C=arr+mi+1;//+1
        for (int i=0, j=0, k=0; (j<lb)||(k<lc); ){
            //cout<<"i="<<i<<"j="<<j<<" k="<<k<<endl;
            if ( ( j < lb ) && ( ! ( k < lc ) || ( B[j] <= C[k] ) ))
                A[i++]=B[j++];//前半段比较小
            if ( (k<lc) &&( !( j<lb )|| ( C[k]<B[j] )))
                A[i++]=C[k++];//后半段比较小
        }

        delete[] B;
    }

    template <typename T>
    void __mergeSort(T arr[], int lo, int hi){//[lo,hi]排序
        //assert(lo<=hi);
//        if (hi-lo<2)//开区间
//            return;
        if (lo>=hi)//闭区间
            return;
//        {cout<<"rerurn"<<endl; return;}
        int mi=(lo+hi)/2;
//        cout<<"l sorting ["<<lo<<" , "<<mi<<"]"<<endl;
        __mergeSort(arr, lo, mi);
//        cout<<"1. finish ["<<lo<<" , "<<mi<<"]"<<endl;
       // cout<<"lo1="<<lo<<" mi1="<<mi<<endl;
       // __mergeSort(arr, mi, hi);
//        cout<<"r sorting ["<<mi+1<<" , "<<hi<<"]"<<endl;
        __mergeSort(arr, mi+1, hi);//闭区间
//        cout<<"2. finish ["<<mi+1<<" , "<<hi<<"]"<<endl;
       // cout<<"mi+1="<<mi+1<<" hi="<<hi<<endl;
        if (arr[mi]  > arr[mi+1])//这一步优化,只有当前后无序才进行合并
        merge(arr, lo, mi, hi);
//        cout<<"merge finished"<<endl;
    }


    // 归并排序
    // 时间复杂度O(nlogn)
    template <typename T>
    void mergeSort(T arr[], int n){
       // __mergeSort(arr,  0, n);//[0,n)开区间
        __mergeSort(arr,  0, n-1);//[0,n-1]闭区间
    }

另外一种为非递归实现


//时间复杂度O(NLOGN)
//空间复杂度O()
//对于arr[lo,hi)进行排序
//template <typename T>
//void mergeSort(T arr[], int lo, int hi){
//    //非递归实现
//}
template <typename T>
void __merge(T arr[], int l, int mi, int r, T aux[]){
    //合并arr[l,mi] [mi+1, hi]
    for (int i=l; i<=r; i++)
        aux[i]=arr[i];
    int i=l,j=mi+1;//i 表示前半段,j表示后半段
    for (int k=l; k<=r;k++){//k表示需要进行覆盖的整个串

        if (i>mi){//表示前半段已经赋值完了
            arr[k]=aux[j];j++;
        }
        else if(j>r){//表示后半段赋值完了
            arr[k]=aux[i];i++;
        }
        else if (aux[i]<aux[j]){//谁小谁赋值
            arr[k]=aux[i];i++;
        }
        else {
            arr[k]=aux[j];j++;
        }
    }
}

//对于arr[0.n)进行归并排序
void mergeSort(int arr[], int n){
    //非递归实现
    assert(n>0);
    int* aux=new int[n];
    for (int i=0;i<n;++i){
        aux[i]=arr[i];
    }

    for (int sz=1; sz<n;sz+=sz){
        for (int i=0; i<n ;i+=sz+sz){
            //arr[i, i+sz) [i+sz, i+sz+sz) 合并
            __merge( arr, i, i+sz-1, min(n-1,i+sz+sz-1), aux);
        }
    }

    delete[] aux;
    return ;
}

未完……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值