因为在重学时遇到了这道题,求逆序对,然后想到了这道题,求逆序对,然后就准备复习一下好久之前曾经学过的归并排序…
众所周知,归并排序是一个排序算法,且他是通过分治的思想去完成排序的过程的,虽然我们似乎是有c++中的sort
可以既快又简单的完成排序的这一操作,但是当我们遇到了上面的这两道题目的时候,此时sort函数就碰到了问题,所以归并函数还是值得我们好好掌握的
下面简单聊一聊归并函数的实现过程(下面是从小到大排序):
比如我们有这样的一组数据:
4 2 4 5 1
然后我们可以先将其分成两个部分(即使用分治的思想):
4 2 4 5 1
然后再将两个部分在分成两个部分
4 2 4 51
然后单个的我们就不需要排序了,当然5,1这一组最后的边界也是成为两个单个的数字,
然后返回到上一层,
这一次我们看向5,1 这一组,因为单个不用比较,所以我们要比较两个数字的时候,此时我们直接比较5,1,发现可以需要调换,此时我们就变成了1,5
然后就是
2,4 4 1,5
此时我们再比较 2,4 与 4这两组,将其比较大小完成2,4,4这样的有序序列
然后一直往上地推回去即可
总而言之就是分治的思想
接下来是代码的部分(从大到小排序)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <string.h>
#include <stack>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define root 1,n,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
ll x=0,w=1;char ch=getchar();
for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x*w;
}
#define maxn 1000000
int a[100000];
int n;
int fuzhu[100000];
void qsort(int l,int r) {
if(l>=r) return ;
/*这个边界条件一定不要忘记了,忘记了会导致死循环,边界的意义就是只剩下一个数字的时候,此时就不需要在
分了*/
int mid=(l+r)>>1;//因为是分治的思想,所以肯定是有一个mid的吧
//题外话,这里的 >> 符号是移位符,也就是将二进制往右移移位,也就是相当于除以2
qsort(l,mid);qsort(mid+1,r);
//二分分治
int k=l;int i=l,j=mid+1;
//k相当于此时这个组合的位置
//就比如2,5,4 与 5,6这两个组合,现在要将他们合并成同一个组合,k就相当于新的组合的指针
while(i<=mid&&j<=r) {
if(a[i]>a[j]) {//将两个组合中的较大的值放入新的组合的前列
fuzhu[k++]=a[i++];
}else {
fuzhu[k++]=a[j++];
}
}
while(i<=mid) {//如果还有剩余的话当然就直接放入就好了,此时就不需要再比了
fuzhu[k++]=a[i++];
}
while(j<=r) {
fuzhu[k++]=a[j++];
}
for(int i=l;i<=r;i++) {//然后把新的组合在放入我们原来的a数组之中,因为fuzhi就只是一个中间数组
a[i]=fuzhu[i];
}
}
int main() {
n=read();
for(int i=1;i<=n;i++) a[i]=read();
qsort(1,n);
for(int i=1;i<=n;i++) cout<<a[i]<<" ";
cout<<endl;
return 0;
}