归并排序详解
归并排序详解
yedalong
·
2024-09-26 13:35:56
·
算法·理论
什么是归并排序
归并排序是由冯・诺伊曼发明的,是建立在归并操作之上的一种高效的排序方式。它的速度仅次于快速排序,时间复杂度 O(n \log n),空间复杂度 O(n),是稳定的排序算法。归并排序的运用领域非常广泛,最常见的就是解决逆序对的问题。可以说,归并排序是非常优秀的。
归并排序的思路
下面将由我带大家跑一遍归并排序。\
假设一开始有个无序数组:5 4 6 9 8,
我们的目的是将这个数组从小到大排序。\
我们将它分成两个部分\
\
继续细分下去,直到全为单个数字(单个数字也是一个有序数列)\
分完后,就要开始合并了\
合并过程是最重要的,规则如下:\
对于两个有序的序列合并,因为是有序的,所以我们只需比较两个序列的第一个元素,取最小值放到一个数组里维护,再将这数删除,直到这个数组维护完两个区间,再将这个有序的数组在原封不动的复制到这两个区间上。\
对于这个数列排序过程如下:\
\
最后就排好序啦!
归并排序的模板
#include
using namespace std;
int n,arr[10005];
void merge(int l,int mid,int r){//合并操作,重点
queue
int left=l;//此变量用于存左半区的第一个数的下标
int right=mid+1;//此变量用于存右半区的第一个数的下标
while(left<=mid&&right<=r){//如果左半区和右半区的数都还没取完
if(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< return 0; } 例题 怎没样?学废会了吗?赶紧实战一下吧!\ P1908 逆序对\ P1774 最接近神的人\ B3874 [GESP202309 六级] 小杨的握手问题\ P1309 [NOIP 2011 普及组] 瑞士轮