(C++)归并排序的递归与非递归实现

本文详细介绍了归并排序的两种实现方式:递归和非递归。递归版本通过双指针技巧降低复杂度,并利用递归对序列进行排序;非递归版本则通过逐步增加待合并子序列的长度来实现排序过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

递归实现

merge函数利用的是双指针技巧降低复杂度。

mergeSort函数使用了递归,当中先对左右序列各调用一次mergeSort,再对整个序列调用merge。就按照最浅层的归并的思想去理解,不要大脑走到哪就step in。

另外mergeSort进入递归有个left<right的判定容易漏写。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

const int maxn = 10;
const int INF = 1000000000;//INF:下确界  
const LL SUP = (1LL<<63)-1;//SUP:上确界 
const double eps = 1e-5;

LL Map[128];

void merge(int A[],int L1,int R1,int L2,int R2){
	
	int i=L1,j=L2;
	int temp[maxn];
	int index = 0;
	
	while(i<=R1&&j<=R2){//是≤不是< 
		if(A[i]<=A[j]){
			temp[index++] = A[i++];
		}else{
			temp[index++] = A[j++];
		}
	}
	
	while(i<=R1)temp[index++] = A[i++];//这个while很容易写成if 
	while(j<=R2)temp[index++] = A[j++];
	
	
	for(int i=0;i<index;i++){
		A[L1+i] = temp[i];
	}
	
}

void mergeSort(int A[],int l,int r){//递归实现的归并排序 
	if(l<r){
		int mid = (l+r)/2;
		mergeSort(A,l,mid);
		mergeSort(A,mid+1,r);
		merge(A,l,mid,mid+1,r); 
	}
	
} 



int main(){
	
	int A[maxn] = {66,12,33,57,64,27,39,66,78,66};
	
	mergeSort(A,0,maxn-1);

	for(int i=0;i<maxn;i++){
		printf("%d ",A[i]);
	}
	
	return 0;
}

非递归实现

基础的归并函数merge是一样的,但感觉非递归道理容易想明白但是实现起来细节多。注意两个for和一个if的<n不能写成<=n(如果传入的n是数组的长度而非最后一个元素的下标)

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

const int maxn = 10;
const int INF = 1000000000;//INF:下确界  
const LL SUP = (1LL<<63)-1;//SUP:上确界 
const double eps = 1e-5;

LL Map[128];

void merge(int A[],int L1,int R1,int L2,int R2){
	
	int i=L1,j=L2;
	int temp[maxn];
	int index = 0;
	
	while(i<=R1&&j<=R2){//是≤不是< 
		if(A[i]<=A[j]){
			temp[index++] = A[i++];
		}else{
			temp[index++] = A[j++];
		}
	}
	
	while(i<=R1)temp[index++] = A[i++];//这个while很容易写成if 
	while(j<=R2)temp[index++] = A[j++];
	
	
	for(int i=0;i<index;i++){
		A[L1+i] = temp[i];
	}
	
}

void mergeSort(int A[],int n){//非递归实现的归并排序 
	//step为组内元素个数(每归并一次乘二)
	for(int step=2;step/2<n;step*=2){
		//每step个元素一组,组内左一半step/2和右一半step/2的元素合并,注意有很多个这样的组
		for(int i=0;i<n;i+=step){
			int mid = i+step/2-1;//step/2为左子区间元素个数
			if(mid+1<n){//右子区间存在元素则合并 
				merge(A,i,mid,mid+1,min(i+step-1,n));
			}
		} 
	} 
	
} 



int main(){
	
	int A[maxn] = {66,12,33,57,64,27,39,66,78,66};
	
	mergeSort(A,maxn);

	for(int i=0;i<maxn;i++){
		printf("%d ",A[i]);
	}
	
	return 0;
}

 如果时间限制允许,且只要求打印出每一趟归并排序的结果,可以不调用merge()而是采用sort

void mergeSort(int A[],int len){
	for(int step = 2;step/2<len;step*=2){
		for(int i=0;i<len;i+=step){
			sort(A+i,A+min(i+step,len));
		}
		for(int i=0;i<maxn;i++){
			printf("%d ",A[i]);
		}
		printf("\n");
	}
}

但是这样就不是真正意义上的归并了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CSU迦叶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值