归并排序详解(递归与非递归(迭代))

1.前言

归并排序基于比较的排序中,最好的三个之一(其余两个为:堆排序、快速排序
时间复杂度为 O(N*logN
空间复杂度为 O(N)

2.内容

递归

void Partition(vector <int>& c, int L, int M, int R)   //归并排序的合并过程
{
	//开辟一个额外数组,存储排序后的数组
	vector <int> ex(R - L + 1);   
	//左右指针
	int l = L;     
	int r = M + 1;
	int k = 0;    //额外数组
	//进行比较,并放入额外数组中
	while (l <= M && r <= R)   //左右指针不越界
	{
		ex[k++] = c[l] <= c[r] ? c[l++] : c[r++];    //先拷贝小的(若相等,先拷贝左边的)
	}
	//拷贝剩下的元素
	while (l <= M)
	{
		ex[k++] = c[l++];
	}
	while (r <= R)
	{
		ex[k++] = c[r++];
	}
	//重新放进原数组中
	int i = 0;
	for (const auto& e : ex)
		c[L + i++] = e;
}
void Guibingdg(vector <int>& b, int L, int R)  //递归版本
{
	if (L >= R)
		return;
	else
	{
		int M = L + ((R-L) >> 1);   //中间位置
		Guibingdg(b, L, M);   //左有序
		Guibingdg(b, M + 1, R); //右有序
		Partition(b, L, M, R);   //合并
	}
}

int main()
{
	srand((unsigned int)time(0));
	int n;
	n=rand()%10+5; //数组大小在 5~14
	vector<int>a(n);    //创建动态数组对象a
	for (int i = 0; i < n; i++)
		a[i] = rand()%10000-5000;       //随机-5000~4999
	for (const auto& e : a)   //排序前先输出,做对比
		cout << e << " ";
	cout << endl;
	Guibingdg(a, 0, n - 1);   //递归版本的归并排序
	for (const auto& e : a)   //范围for语句,遍历输出
		cout << e << " ";
	return 0;
}

非递归(迭代版本)

void Guibingfdg(vector<int>& b,int len)  //非递归版本(迭代  分而治之)
{
	vector <int> c(len);    //申请额外空间
	
	for (int segment = 1; segment < len; segment *= 2)   //划分部分表示每一步的步长(注意不要多加;)
	{
		for (int begin = 0; begin < len; begin +=segment* 2)
		{
			int L = begin, M = min(begin + segment, len), R = min(begin + segment * 2, len);   //定义L  M  R,划分范围
			int k = L;
			int p1 = L, end1 = M;
			int p2 = M, end2 = R;
			while (p1 < end1 && p2 < end2)   //不越界  (不加等号是因为后面的分治会考虑进去)
			{                                //同时符合最后一步 ==len时
				c[k++] = b[p1] < b[p2] ? b[p1++] : b[p2++];   //将小的先拷贝
			}
			//拷贝剩余元素
			while (p1 < end1)
				c[k++] = b[p1++];
			while (p2 < end2)
				c[k++] = b[p2++];
		}
		//将排序好的c中元素重新拷贝回b中
		for (int i = 0; i < len; i++)
			b[i] = c[i];
	}
}

int main()
{
	srand((unsigned int)time(0));
	int n;
	n=rand()%10+5; //数组大小在 5~14
	vector<int>a(n);    //创建动态数组对象a
	for (int i = 0; i < n; i++)
		a[i] = rand()%10000-5000;       //随机-5000~4999
	for (const auto& e : a)   //排序前先输出,做对比
		cout << e << " ";
	cout << endl;
	Guibingfdg(a, n);        //迭代版本的
	for (const auto& e : a)   //范围for语句,遍历输出
		cout << e << " ";
	return 0;
}

3.总结

归并排序利用了分而治之 的思想,加深理解思想

(在这里引用菜鸟教程上的图来解释)
在这里插入图片描述在这里插入图片描述

4.更新日志

2022.5.15 整理上传

欢迎评论留言、指正~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值