c++归并排序

因为在重学时遇到了这道题,求逆序对,然后想到了这道题,求逆序对,然后就准备复习一下好久之前曾经学过的归并排序…

众所周知,归并排序是一个排序算法,且他是通过分治的思想去完成排序的过程的,虽然我们似乎是有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;
}

至此,归并排序就结束了,当然求逆序对还有更加NB装逼的方法,你可以使用树状数组,甚至是线段树的方法进行求值,但是我现在还没复习到(唉,明明之前是会的,现在却…),就不献丑了,之后补坑.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值