归并排序算法

mac2024-06-22  43

归并排序算法

虽然c++的STL中有sort算法,但是这个算法可以有效求出逆序对的问题 时间复杂度上与sort函数和快速排序算法相差无几

归并排序拓展:处理逆序对*

归并排序

这个算法采用的是分而治之的思想,顾名思义就是把一个数组分开来处理,然后再合并唯一。

时间复杂度:归并排序比快速排序稳定,因此它的时间复杂度为 O(nlogn),不管在什么情况下都是这种情况。

归并排序的大致过程:

这里需要注意,当返回时处理的区间已经是在区间内有序的。 先把递归的把数组分成左右两个小区间(以mid为中),一直分,直到当区间里的元素只有一个时返回,设置两个指针i,j。 (l)指向左区间最左边的第一个元素,j(mid+1)指向右区间最左边的第一个元素,开一个临时数组(temp); 然后比较这两个指针所指向的元素,小的数就放入临时数组(temp),并且指针向后移动,依次操作。 当i超过mid或者j超过r的时候证明左区间或右区间以及没有元素,退出操作,因为上面的操作是当左区间或右区间中一个区间没有元素时退出。 所以我们需要判断哪个区间还有数,并且放入临时数组(temp) 最后再把temp数组赋值给a数组就完成了当前这个区间的排序,再返回上一层递归。

这个图是将区间递归分

上代码:

#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> Pall; namespace IO{ inline LL read(){ LL o=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){o=o*10+c-'0';c=getchar();} return o*f; } }using namespace IO; const int N=1e5+7,INF=0x3f3f3f3f; int a[N]; void merge_sort(int l,int r){ if(l>=r)return ;//如果区间中只有一个元素时,就返回 int mid=l+r>>1;//确定中间点(区间分界点) merge_sort(l,mid),merge_sort(mid+1,r);//左边递归处理,右边递归处理 int i=l,j=mid+1,temp[r-l+1],cnt=0;//i指针指向左区间的最左边的元素,j指针指向右区间最右边的元素,temp是临时数组 while(i<=mid&&j<=r){//如果左区间还有元素并且右区间还有元素,就需要进行比较 if(a[i]<=a[j])temp[cnt++]=a[i++];//如果i指向的元素比j指向的元素小或相等,就把i指向的元素放入临时数组,并且移动i到下一个元素 else temp[cnt++]=a[j++];//如果j指向的元素比j指向的元素大,就把j指向的元素放入临时数组,并且移动j到下一个元素 } while(i<=mid)temp[cnt++]=a[i++];//如果左区间还有元素,就把剩下的元素放入临时数组。如果没有就不会执行 while(j<=r)temp[cnt++]=a[j++];//如果右区间还有元素,就把剩下的元素放入临时数组。如果没有就不会执行 for(i=l,j=0;i<=r;i++,j++)a[i]=temp[j];//最后i指向的是这个大区间的最左边(左区间+右区间),j指向的是temp的首元素。 //把temp中的排好的的元素赋值到a数组中(l,r)这个区间,因为这个递归层就是处理(l,r)区间的排序。 } int main(){ int n; cin>>n; for(int i=0;i<n;i++){ cin>>a[i]; } merge_sort(0,n-1);//归并排序 for(int i=0;i<n;i++){ cout<<a[i]<<" "; } return 0; }
最新回复(0)