归并排序详解
什么是归并排序
归并排序是由冯・诺伊曼发明的,是建立在归并操作之上的一种高效的排序方式。它的速度仅次于快速排序,时间复杂度
归并排序的思路
下面将由我带大家跑一遍归并排序。\
假设一开始有个无序数组:
归并排序的模板
#include <bits/stdc++.h>
using namespace std;
int n,arr[10005];
void merge(int l,int mid,int r){//合并操作,重点
queue<int> q;//此队列用于维护 l 到 r 区间内的有序数列,可以用数组代替
int left=l;//此变量用于存左半区的第一个数的下标
int right=mid+1;//此变量用于存右半区的第一个数的下标
while(left<=mid&&right<=r){//如果左半区和右半区的数都还没取完
if(arr[left]<arr[right]) q.push(arr[left++]);//如果左半区的第一个数比右半区的第一个数更小,将左半区的第一个数放入队列维护
else q.push(arr[right++]);////如果右半区的第一个数比左半区的第一个数更小,将右半区的第一个数放入队列维护
}
while(left<=mid) q.push(arr[left++]);//将左半区剩余数直接取空
while(right<=r) q.push(arr[right++]);//将右半区剩余数直接取空
for(int i = l;i<=r;i++) arr[i]=q.front(),q.pop();//将维护好的有序队列复制到 l 到 r 区间内的数组里
}
void Merge_sort(int left,int right){//归并排序函数主体
if(left!=right){//如果不为一个数,递归分治
int mid=(left+right)/2;//将 left 到 right 区间分成两半
Merge_sort(left,mid);//左半区
Merge_sort(mid+1,right);//右半区
merge(left,mid,right);//合并
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i = 1;i<=n;i++) cin>>arr[i];//输入
Merge_sort(1,n);//归并
for(int i = 1;i<=n;i++) cout<<arr[i]<<' ';//输出
return 0;
}
例题
怎没样?学废会了吗?赶紧实战一下吧!\
P1908 逆序对\
P1774 最接近神的人\
B3874 [GESP202309 六级] 小杨的握手问题\
P1309 [NOIP 2011 普及组] 瑞士轮