归并排序
所谓归并排序是指将两个或两个以上有序的数列(或有序表),合并成一个仍然有序的数列(或有序表)。这样的排序方法经常用于多个有序的数据文件归并成一个有序的数据文件。归并排序的算法比较简单。
1. 基本思想
归并排序是用分治思想,分治模式在每一层递归上有三个步骤:
- 分解(Divide):将n个元素分成2个含n/2个元素的子序列(n为奇数时,有一个序列会多一)。
- 解决(Conquer):用合并排序法对两个子序列递归的排序。
-
合并(Combine):合并两个已排序的子序列已得到排序结果。
2. 实现逻辑
2.1 工作原理
① 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
② 设定两个指针,最初位置分别为两个已经排序序列的起始位置
③ 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
④ 重复步骤③直到某一指针到达序列尾
⑤ 将另一序列剩下的所有元素直接复制到合并序列尾
2.2 递归实现
① 将序列每相邻两个数字进行归并操作,形成floor(n/2)个序列,排序后每个序列包含两个元素
② 将上述序列再次归并,形成floor(n/4)个序列,每个序列包含四个元素
③ 重复步骤②,直到所有元素排序完毕
4. 复杂度分析
平均时间复杂度:O(nlogn)
最佳时间复杂度:O(n)
最差时间复杂度:O(nlogn)
空间复杂度:O(n)
排序方式:In-place
稳定性:稳定
#include<cstdio> const int maxn=500010; int a[maxn],c[maxn]; int n; long long ans=0; void msort(int l,int r){ if(l==r) return ; int mid=(l+r)/2; msort(l,mid);//分解 msort(mid+1,r); int i=l,j=mid+1,k=l; while(i<=mid&&j<=r){//合并 if(a[i]>a[j]) { // ans+=mid-i+1; c[k++]=a[j++]; } else c[k++]=a[i++]; } while(i<=mid) c[k++]=a[i++]; while(j<=r) c[k++]=a[j++]; for(int i=l;i<=r;i++) a[i]=c[i]; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); msort(1,n); for(int i=1;i<=n;i++) printf("%d",a[i]); //printf("%lld\n",ans);//逆序对数 return 0; }