归并排序

合并函数

2-路归并排序的核心在于如何将两个有序序列合并为一个有序序列。

void merge(vector<int>& a,int L1,int R1,int L2,int R2) {
	int i=L1,j=L2;
	//定义一个足够大的临时容器
	int size=(R1-L1+5)*2;
	vector<int> tmp(size);
	int index=0;
	//把两组中较小的插入
	while(i<=R1&&j<=R2) {
		if(a[i]<a[j]) tmp[index++]=a[i++];
		else tmp[index++]=a[j++];
	}
	//把末尾的插入
	while(i<=R1) tmp[index++]=a[i++];
	while(j<=R2) tmp[index++]=a[j++];
	//把临时容器中的值赋值回原容器
	for(i=0; i<index; i++) {
		a[L1+i]=tmp[i];
	}
}

递归实现

递归实现写法简单,只需要注意左边界一定要小于右边界即可。

void mergeSort(vector<int>& a,int left,int right) {
	if(left<right) {
		int mid = (left+right)/2;
		mergeSort(a,left,mid);
		mergeSort(a,mid+1,right);
		merge(a,left,mid,mid+1,right);
	}
}

非递归实现

如果希望输出归并排序每一趟的结果,就只能使用非递归的写法。
主要思想:令step为2的幂次,每次把容器中step个元素作为一组,进行内部合并;每次令step乘以2,重复操作,直到step/2超过元素总数,说明已经完成了汇总。

void mergeSort_non(vector<int>& a) {
	//step超过容器大小后,还需要再执行一趟总的归并
	for(int step=2; step/2<a.size(); step*=2) {
		for(int i=0; i<a.size(); i+=step) {
			//左区间元素个数为step/2
			//拿第一组记忆mid的写法:一组两个元素,左右区间各一个元素,所以L1为0,R1为0,L2为1,R2为1
			//所以mid最开始应该为0,需要-1
			int mid=i+step/2-1;
			int n=a.size()-1;
			merge(a,i,mid,mid+1,min(i+step-1,n)) ;
		}
		//输出每一趟的结果
		for(auto i:a) {
			cout<<i<<" ";
		}
		cout<<endl;
	}
}

时间允许的时候可以使用sort函数代替merge函数,注意sort函数对迭代器的写法,末位是尾后一位元素,所以不用-1。

void mergeSort_non_recur(vector<int>& a){
	//step超过容器大小后,还没有进行总的归并,因此需要比较的是step/2和size的大小 
	for(int step=2;step/2<a.size();step*=2){
		for(int i=0;i<a.size();i+=step){
			//注意右边界是容器大小和该组右边界较小的,不要越界 
			sort(a.begin()+i,min(a.begin()+i+step,a.end()));
		}
		//输出每一趟的结果 
		for(auto i:a){
			cout<<i<<" ";
		}
		cout<<endl;
	}	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值