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

Posted awcxv

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了书上讲解归并排序的非递归写法相关的知识,希望对你有一定的参考价值。

描述

【题解】


让区间的长度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;

以上是关于书上讲解归并排序的非递归写法的主要内容,如果未能解决你的问题,请参考以下文章

高速排序 归并排序的非递归版本号 备忘

归并排序 的非递归算法

c_cpp 归并排序的非递归实现,慢于标准库

都2020年了,听说你还不会归并排序?手把手教你手写归并排序算法

手把手教你写归并排序算法 (Java代码)

[ 数据结构 -- 手撕排序算法第六篇 ] 归并排序(下)-- 非递归方法实现