今天月考完,突然想到排序这个东西,一直用的都是STL的sort和简单的冒泡排序
归并排序…只记得一个大体思路,好像从来都没有代码实现过
所以心血来潮重新看了一下(:3_ヽ)_ 神tm这都高二下学期了
归并排序的思想就是分治,把整个数组从中间分开分成两个小数组,两个小数组排序,最后再合并成一个大数组,这样一直划分,直到划分出来了两个的长度均为1时,就可以开始向回合并了
合并的时候两个子数组间两两逐个比较即可(因为子数组已经是有序的了),并入原数组之后就将并入的元素在临时空间中删去,一直删到最后。
合并子数组时间复杂度是O(n),合并次数是O(log n)<典型的二分复杂度,底数当然是2>
总的时间复杂度就是他们的乘积O(n log n)啦
不得不说书上的代码实现等各方面真是胜我百倍。。。
归并排序的用处,主要应该是求逆序对吧。。。
譬如
洛谷的 P1908
下面是我的题解:
求逆序对,只需跑一边归并排序
每次归并排序的时候,如果是先加入了右半个子数组的元素,可知此时存在逆序对,逆序对的个数为左半个子数组剩下的元素的数目,答案加上这个数即可
代码如下
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define For(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
int a[100010],n,temp[100010],ans;
void merge(int l,int r)
{
int l1=l,r1=(l+r)>>1,l2=((l+r)>>1)+1,r2=r,i=l;
while(l1<=r1&&l2<=r2)
{
if(a[l1]<=a[l2])
temp[i++]=a[l1++];
else
{
temp[i++]=a[l2++];
ans+=r1-l1+1;
}
}
while(l1<=r1)
temp[i++]=a[l1++];
while(l2<=r2)
temp[i++]=a[l2++];
For(i,l,r)
a[i]=temp[i];
}
void msort(int l,int r)
{
if(l<r)
{
msort(l,(l+r)>>1);
msort(((l+r)>>1)+1,r);
merge(l,r);
}
}
int main()
{
cin>>n;
For(i,1,n)
cin>>a[i];
msort(1,n);
//For(i,1,n)
// cout<<a[i]<<' ';
cout<<ans;
return 0;
}
快排模板题
洛谷P1177
也是可以直接用归并排序过的233
参考资料:https://blog.youkuaiyun.com/chencangui/article/details/44680113/