• 【书上讲解】归并排序的非递归写法


    描述

    【题解】

    让区间的长度L为1,2,4,...2^(n-1) 然后对每个位置i开始的长度为L的区间归并有序,用归并排序的方法就好,然后i跳转到i+L 复杂度仍然是log2(n)*n级别的,注意写的时候的一些细节。 比如一定要让最后L>=n的情况进行过一次,不然无法保证整个序列是有序的

    【代码】

    /*
        归并排序非递归写法
    */
    #include <cstdio>
    const int N = 1e5;
    
    int a[N+10],b[N+10];
    int n;
    
    //把a这个数组在l1..r2这个区间分成两段[l1,r1]和[l2,r2];然后进行合并
    void _Merge(int a[],int b[],int l1,int r1,int l2,int r2){
        int i = l1,j = l2,k = l1;
        while (i<=r1 && j<= r2){
            if (a[i]<=a[j])
                b[k++]=a[i++];
            else
                b[k++] = a[j++];
        }
        while (i<=r1) b[k++] = a[i++];
        while (j<=r2) b[k++] = a[j++];
    }
    
    void _merge(int a[],int b[],int L){
        int i = 1;
        while (i+L-1<n){//把i..i+L-1这个区间合并
            _Merge(a,b,i,i+L/2-1,i+L/2,i+L-1);
            i = i+L;
        }
        //i+L-1>=n
        if (i+L/2-1<=n){
            _Merge(a,b,i,i+L/2-1,i+L/2,n);
        }else{
            _Merge(a,b,i,n,n+1,n);
        }
    }
    
    int main(){
        //freopen("D:\rush.txt","r",stdin);
        scanf("%d",&n);
        for (int i = 1;i <= n;i++) scanf("%d",&a[i]);
        int L = 1;
        while (L<=n){
            L*=2;
            _merge(a,b,L);//把a长度为L的合并起来然后放到b数组中去
            L*=2;//要确保L>n的时候,那个长度合并过
            _merge(b,a,L);//把b长度为L的合并起来然后放到a数组中去
        }
        for (int i = 1;i <= n;i++) printf("%d ",a[i]);
        return 0;
    }
    
    
  • 相关阅读:
    Kvm --01 虚拟化基础概念
    Git--09 创建Maven项目
    Git--08 Jenkins
    Git--07 Gitlab备份与恢复
    Git --06 Git-gui安装
    Git --05 Gitlab使用
    Git--04 Github使用
    socket 释放全过程
    动态规划习题总结
    linux heap堆分配
  • 原文地址:https://www.cnblogs.com/AWCXV/p/11620700.html
Copyright © 2020-2023  润新知