【排序算法】C语言实现归并排序,包括递归和迭代两个版本

news2024/12/22 19:25:53

请添加图片描述

文章目录

  • 🚀前言
  • 🚀归并排序介绍及其思想
  • 🚀递归实现
  • 🚀迭代实现

🚀前言

大家好啊!阿辉接着更新排序算法,今天要讲的是归并排序,这里阿辉将讲到归并排序的递归实现迭代实现,话不多说,开始咱们今天的学习吧!!!!

🚀归并排序介绍及其思想

归并排序这是阿辉讲的第一个时间复杂度O(nlogn)的排序算法,额外空间复杂度是O(n),归并排序可以做到稳定性。

思想
归并排序的思想就是分治分治的思想是将一个大问题分解成若干个小问题,然后分别解决这些小问题,最后将这些小问题的解合并起来得到原问题的解

由分治的思想很容易,想到用递归来实现归并排序,我们接着看👇

🚀递归实现

关于归并排序的递归方法主要由三个大的逻辑组成:

  • 分解:将待排序的数组分成两个子数组
  • 解决:对每个子数组进行排序
  • 合并:将排序好的子数组合并成一个有序的数组

这里我们使用递归很轻松就能把主逻辑写好,大家都知道写递归必须要有限制条件否则会造成死递归,对于归并排序的限制条件很简单,对于数组只有一个元素时自然就是有序的,直接返回即可

主逻辑:
merge函数相当于黑盒,作用就是把两个有序数组合成一个大的有序数组

void MergeSort(int a[], int l, int r) {// C/C++归并排序递归版本,主逻辑
	if (r == l) {//递归限制条件
		return;
	}
	int m = l + ((r - l) >> 1);//数组中位置下标
	MergeSort(a, l, m);//左部分排序
	MergeSort(a, m + 1, r);//右部分排序
	merge(a, l, m, r);//两部分有序数组合并
}

整个归并排序最重要的部分也就是有序数组合并的部分:
请添加图片描述

merge函数实现,还是不太懂的可以看一下下面的代码,有详细的注释
C语言版本:

void merge(int a[], int l, int m, int r) {
	int* help = (int*)malloc((r - l + 1) * 4);//申请辅助空间
	int i = 0;//作为help指针的偏移量,存储两有序数组排好序的大数组
	int first = l;//作为左部分数组的起始下标
	int second = m + 1;//作为右部分数组的起始下标
	while (first <= m && second <= r) {//哪一方下标越界就说明不用继续比较了
		//三目运算代码更简洁,谁小谁在前先赋值给help,后置++,
		// 赋值后i向后偏移一个位置,second或first也向后偏移一个位置
		help[i++] = a[first] <= a[second] ? a[first++] : a[second++];
	}
	//下面虽然两个while循环但是只会进去一个
	//还没存进help数组的继续存
	while (first <= m) {
		help[i++] = a[first++];
	}
	while (second <= r) {
		help[i++] = a[second++];
	}
	//最后把help管理的值,还原到原数组a中
	for (i = 0; i < r - l + 1; i++) {
		a[l + i] = help[i];
	}
	free(help);//释放申请的堆空间
	help = NULL;//野指针系上绳子
}

C++版本:
也就是用了STL的容器更方便

 void merge(vector<int>& arr, int l, int mid, int r) {//合并有序数组
	vector<int> help(r - l + 1, 0);//用一个额外的数组装排好的数
	int first = l;
	int second = mid + 1;
	int i = 0;
	//合并过程
	while (first <= mid && second <= r) {
		help[i++] = arr[first] <= arr[second] ? arr[first++] : arr[second++];
	}
	while (first <= mid) {
		help[i++] = arr[first++];
	}
	while (second <= r) {
		help[i++] = arr[second++];
	}
	//将help数组拷贝到原数组
	for (int i = 0; i < r - l + 1; i++) {
		arr[l + i] = help[i];
	}
}

🚀迭代实现

归并排序的迭代实现就是把主逻辑从递归改为迭代了,有序合并部分并没有改变还是上面实现的merge函数
其实就是从递归的条件返回那一步往后推:
这里我们引入一个概念步长,用来表示左部分和右部分的数组长度,步长从1开始,然后每次倍增,就相当于递归的回溯过程
上图:
步长为左右部分长度,左右部分进行merge操作,没有右部分的跳过
请添加图片描述
主逻辑:

void MergeSort(int a[], int l, int r) {
	int len = 1;//步长
	while (len <= r) {
		l = 0;
		while (l <= r) {
			int m = l + len - 1;//计算左部分的最后一个位置
			if (m >= r) {//此时说明没有右部分,可以跳出循环进行下一轮了
				break;
			}
			//m + len是右部分的最后一个位置与r做比较防止越界,拿到一个正确的merge右边界
			int n = r <= m + len ? r : m + len;
			merge(a, l, m, n);
			l = n + 1;
		}
		if (len > r / 2) {//假如数组很长len×2可能溢出,防止溢出变成负数死循环
			break;
		}
	}
}

merge函数和前面的一样,阿辉就不水了


请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1408464.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI服务器行业分析:预计2023年全球市场规模将达211亿美元

AI服务器需求暴增&#xff0c;机构指出&#xff0c;AI时代浪潮汹涌&#xff0c;海量数据催生庞大的算力需求&#xff0c;带动AI服务器需求量与日俱增&#xff0c;用于服务器内、外部数据传输等接口芯片也随之攀升。 ChatGPT大火后&#xff0c;各大科技企业纷纷发力AI大模型&…

Vue的生命周期方法

beforeCreate 在实例初始化之后&#xff0c;数据观测&#xff08;data observe&#xff09;和 event/watcher 事件配置之前被调用。在当前阶段 data、methods、computed 以及 watch 上的数据和方法都不能被访问。 created 实例已经创建完成之后被调用。在这一步&#xff0c;实…

坚持刷题 |对称二叉树

文章目录 题目考察点代码实现实现总结扩展用迭代的方式判断是否为对称二叉树递归和迭代的对比可能的扩展提问 坚持刷题&#xff0c;老年痴呆追不上我&#xff0c;今天真的好累&#xff0c;就不难为自己了&#xff0c;刷个简单级别的吧&#xff1a;对称二叉树 题目 101.对称二叉…

大数据开发之SparkSQL

第 1 章&#xff1a;spark sql概述 1.1 什么是spark sql 1、spark sql是spark用于结构化数据处理的spark模块 1&#xff09;半结构化数据&#xff08;日志数据&#xff09; 2&#xff09;结构化数据&#xff08;数据库数据&#xff09; 1.2 为什么要有sparksql hive on s…

如何开发一款独立游戏?

如何开发一款独立游戏&#xff1f; 2023年&#xff0c;Steam平台共发行了14533款游戏&#xff0c;我们可以清晰地看到独立游戏市场的蓬勃发展和不断增长的活力。我们从SteamDB数据统计网站获悉&#xff0c;2023年Steam平台的游戏发行数量比2022年的12562款增加了1971款&#xf…

理想汽车大模型算法工程师面试,被问的瑟瑟发抖。。。。

最近我们技术群的一位小伙伴&#xff0c;分享了他面试理想汽车大模型算法工程师的经历与经验。 今天整理后分享给大家&#xff0c;如果你对这块感兴趣&#xff0c;可以文末加入我们的技术&面试讨论群 一面&#xff08;1.5h&#xff0c;感觉有点难&#xff09; 自我介绍&…

推荐收藏!48道数据分析师高频面试题汇总!

大家好&#xff0c;最近很多小伙伴私信我&#xff0c;讲一下数据分析的面试题&#xff0c;今天给大家整理了48道数据分析师面试时被频繁问到的题目&#xff0c;找数据分析岗位的同学一定要码住认真看。 想了解最新的面试动态、最新高频考点、技术交流的同学&#xff0c;可以文…

Windows和Linux访问不了GitHub的解决方法

一、Windows访问不了GitHub 问题描述 使用Windows访问GitHub时&#xff0c;出现如下情况&#xff0c;显示无法访问。 解决方案&#xff1a; 打开域名查询网站&#xff1a;https://tool.chinaz.com/dns 输入GitHub的域名&#xff0c;点击立即检测。 出现如下页面&#xff0c…

RK3399平台开发系列讲解(USB篇)BusHound 工具使用介绍

🚀返回专栏总目录 文章目录 一、BusHound简介二、BusHound的下载三、BusHound设备窗口四、BUSHound发送命令窗口沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 BusHound软件是由美国perisoft公司研制的一种专用于PC机各种总线数据包监视和控制的开发工具软件,其名…

2024年学鸿蒙开发有前途吗?

随着科技的不断发展和智能设备的普及&#xff0c;鸿蒙系统作为华为自主研发的操作系统&#xff0c;正逐渐受到市场的关注。2024年&#xff0c;学鸿蒙开发是否有前途&#xff0c;成为了很多开发者和学生关心的问题。本文将从多个角度分析鸿蒙系统的发展前景&#xff0c;以及学习…

JavaScript入门分享

文章目录 一、JavaScript简介二、第一个JavaScript案例三、在浏览器中执行JavaScript代码四、JavaScript的输出方法五、JavaScript的语法六、JavaScript的数据类型七、JavaScript的定义变量/函数八、热门文章 一、JavaScript简介 JavaScript是一种高级编程语言&#xff0c;用于…

esxi配置NTP自动对时与手动对时

目录 背景解法配置NTP服务器立即与NTP服务器同步时间 附&#xff1a;几个常用的NTP服务器列表 背景 VMware ESXi 6.7运行了一段时间后偶然发现系统时间与标准时间有5分钟左右的差异&#xff0c;于是研究了下如何自动对时以及用命令行立即对时。 解法 配置NTP服务器 首先在管…

手把手教你使用MDK仿真调试

当今的嵌入式系统开发领域中&#xff0c;高效的调试工具对于工程师来说至关重要。它们能够极大地减少开发周期中的错误追踪时间&#xff0c;并加速产品的上市时间。MDK作为业界领先的嵌入式开发工具之一&#xff0c;其内置的调试功能被广大开发者所赞誉。这些功能不仅提供了对代…

PostgreSQL 是不是大小写敏感

如果你踩过 MySQL 的大坑的话就知道&#xff1a;MySQL 在 Windows 下不区分大小写&#xff0c;但在 Linux 下默认是区分大小写。 如果你稍加不注意就会出现在本机开发的程序运行一切正常&#xff0c;发布到服务器行就出现表名找不到的问题。 这是我们前一个项目遇到的巨大问题…

Python中函数的参数有哪些?

目录 ①必选参数 ②默认参数 ③可变参数 ④关键字参数 ⑤命名关键字参数 学习python函数部分的时候&#xff0c;发现除了正常定义的必选参数外&#xff0c;还使用默认参数、可变参数、关键字参数和命名关键字参数&#xff0c;在这里理清楚这些参数具体是怎么回事吧&#x…

nvm 配置淘宝镜像失效,以及安装node后 npm-v 无效

win11 nvm版本 1.1.4 和1.1.7和1.1.12&#xff08;目前最新版本24年 一月二十三日&#xff09; 以上nvm版本都会出现一下问题&#xff0c; 从https://github.com/coreybutler/nvm-windows/releases 下载nvm安装包如下图 傻瓜式安装后&#xff0c;不用去配置环境变量&#…

动态IP代理与静态IP代理:详细区别与比较全析

动态代理IP和静态代理IP在跨境业务中具有非常广泛的实用性&#xff0c;但仍然有非常多小白选手并不清楚什么场景适合用哪一类IP&#xff0c;哪一中代理IP类型更适合你&#xff1f;其实他们各有其优点和缺点&#xff0c;为了使您的网络营销、社媒推广、跨境电商运营、网络抓取尽…

C#用DateTime.DaysInMonth(Int32, Int32) 获取指定月的天数

目录 一、DateTime.DaysInMonth(Int32, Int32) 方法 二、实例 1.实例1 2.实例2 3.方法3 一、DateTime.DaysInMonth(Int32, Int32) 方法 返回指定年和月中的天数。 public static int DaysInMonth (int year, int month);参数 year Int32 年。month Int32 月&#…

「JavaSE」抽象类接口2

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;快来卷Java啦 &#x1f387;欢迎点赞收藏加关注哦&#xff01; 抽象类&接口2 &#x1f349;接口间的继承&#x1f349;接口的应用&#x1f349;总结 &#x1f349;接口间的继承 和类的继承…

Java--异常处理

文章目录 主要内容一.练习11.源代码代码如下&#xff08;示例&#xff09;: 2.结果 二.练习21.源代码代码如下&#xff08;示例&#xff09;: 2.结果 三.练习31.源代码代码如下&#xff08;示例&#xff09;: 2.结果 总结 主要内容 一.练习1 编写程序&#xff0c;定义一个 cir…