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

匿名 (未验证) 提交于 2019-12-03 00:13:02

描述

【题解】


让区间的长度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; }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!