归并排序(C语言)

目录

1.归并排序图解

2.归并排序(递归版)

3.归并排序(非递归版)


1.归并排序图解

归并排序的核心思想是让左右两边有序的部分进行合并比较排序,具体什么意思呢?分两点:

1.分:左右两边要有序,如何做到左右两边有序呢?看上面的图,当我们将一个数组进行分离,一直分,知道左右两边进行对比的数只有一个,这种情况下肯定有序。

2.治:这个过程就是将左右两边数进行排序,然后排好后再进行重复操作,就将整个数组置为有序了。

我们用代码来加深整个过程的理解。

2.归并排序(递归版)

我们先来讲这个递归版本的代码思想:

我这里传的四个参数分别是:a--数组,begin--头下标,end--尾下标,tmp用来拷贝的数组。

从图中我们不难发现分的过程是一个除以2倍的关系,所以我们用mid来记录接下来递归的左边尾下标和右边头下标,递归终止条件就是头下标大于等于尾下标的时候,接下来我们进行的操作就是定义一下左边的头尾下标和右边的头尾下标,还有一个i用作tmp的下标,接下来就开始比对了,我们进行升序排序,所以我们把小的往tmp里放,循环的结束条件就是左右两边随便一边走完就停止,接下来再把没输完的全部输进去就好,不要忘记我们的tmp充当的是临时拷贝的角色,我们要改动的是数组a,所以我们使用库函数memcpy来将tmp里的数拷贝到a中,这样就模拟了治的过程,也就是说每一趟递归我们a里的值跟上面图片治部分的每一行是一样的。

我们来看看结果:

归并是一种时间复杂度为O(NlogN)的排序算法,而且它的稳定性也比较高。

我们再来感受一下不用递归,归并怎么来写。

3.归并排序(非递归版)

//归并排序 非递归实现
void MergeSortNrec(int* a, int begin, int end, int* tmp)
{int gap = 1;while (gap < end+1){for (int i = 0; i < (end - begin + 1); i += 2*gap){int begin1 = i, end1 = i + gap-1;int begin2 = i + gap, end2 = i + gap * 2-1;int j = begin1;if (end1 >= end+1|| begin2 >= end+1){break;}if (end2 >= end+1){end2 = end;}while (begin1 <= end1 && begin2 <= end2){if (a[begin1] <= a[begin2]){tmp[j++] = a[begin1++];}else{tmp[j++] = a[begin2++];}}while (begin1 <= end1){tmp[j++] = a[begin1++];}while (begin2 <= end2){tmp[j++] = a[begin2++];}memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));}gap *= 2;}
}

非递归版我们采用的逻辑还是一样的,只不过实现形式有很大区别,递归中我们是分治,用递归达到分的目的,这里我们没有递归,怎么办呢,我们可以用循环来实现,这里我就不卖关子了,我们的总体思路是直接到分的最后一步,也就是一个跟一个比的情款,然后再往回去走。

所以,上面代码中的gap的作用就是控制对比元素的个数,一开始一个跟一个对比,每一趟新的循环gap阔两倍,然后治的过程,代码跟我们递归版的是相差无几的,但是这里的end1,begin2,end2要注意有可能会发生越界的情况,所以我们要对他们进行判断,当end1和begin2中的任意一个出现越界情况的话,我们就终止循环,因为光是左边的就已经到尾了,就没必要比右边了(右边压根没数据了);如果是end2越界,说明这个数组长度不是gap的整数倍了,我们就将end2重置为尾下标就行了,保证了不会出现越界的行为。

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

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

相关文章

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用相机日志跟踪功能(C++)

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用相机日志跟踪功能&#xff08;C&#xff09; Baumer工业相机Baumer工业相机NEOAPI SDK和短曝光功能的技术背景Baumer工业相机通过NEOAPI SDK使用相机日志跟踪功能1.引用合适的类文件2.通过NEOAPI SDK使用相机日志跟踪功能3.通…

如何用Docker部署Nacos服务并结合内网穿透实现公网访问管理界面?

文章目录 1. Docker 运行Nacos2. 本地访问Nacos3. Linux安装Cpolar4. 配置Nacos UI界面公网地址5. 远程访问 Nacos UI界面6. 固定Nacos UI界面公网地址7. 固定地址访问Plik Nacos是阿里开放的一款中间件,也是一款服务注册中心&#xff0c;它主要提供三种功能&#xff1a;持久化…

区间预测 | Matlab实现GRU-Adaboost-ABKDE的集成门控循环单元自适应带宽核密度估计多变量回归区间预测

区间预测 | Matlab实现GRU-Adaboost-ABKDE的集成门控循环单元自适应带宽核密度估计多变量回归区间预测 目录 区间预测 | Matlab实现GRU-Adaboost-ABKDE的集成门控循环单元自适应带宽核密度估计多变量回归区间预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实…

Java 基础知识-反射

大家好我是苏麟 , 今天聊聊反射 . 反射 ​专业的解释&#xff1a; 反射允许对封装类的字段&#xff0c;方法和构造函数的信息进行编程访问 是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法 ​ 对于任意一个对象&#xff0c;都能够调…

学习JavaEE的日子 day13补 深入类加载机制及底层

深入类加载机制 初识类加载过程 使用某个类时&#xff0c;如果该类的class文件没有加载到内存时&#xff0c;则系统会通过以下三个步骤来对该类进行初始化 1.类的加载&#xff08;Load&#xff09; → 2.类的连接&#xff08;Link&#xff09; → 3.类的初始化&#xff08;In…

《WebKit 技术内幕》之三(3): WebKit 架构和模块

3 Webkit2 3.1 Webkit2 架构及模块 相比于狭义的WebKit&#xff0c;WebKit2是一套全新的结构和接口&#xff0c;而并不是一个简单的升级版。Webkit2 的思想同 Chrominum 类似&#xff0c;就是将渲染过程放在单独的进程中来完成&#xff0c;独立于用户界面。 webKit2中…

华为路由设备DHCPV6配置

组网需求 如果大量的企业用户IPv6地址都是手动配置&#xff0c;那么网络管理员工作量大&#xff0c;而且可管理性很差。管理员希望实现公司用户IPv6地址和网络配置参数的自动获取&#xff0c;便于统一管理&#xff0c;实现IPv6的层次布局。 图1 DHCPv6服务器组网图 配置思路 …

重置aws上的ssh默认登录端口

aws上的ec2机器&#xff0c;默认ssh的登录都是22&#xff0c;为了防止被黑&#xff0c;记录下修改该默认端口的方法 修改/etc/ssh/sshd_config文件,将Port 22注释去掉在上面的文件中&#xff0c;加入一行&#xff0c;你想要增加的端口号&#xff0c;格式和22一致注意&#xff1…

Hotspot源码解析-第二十章-基础类型的数组类型对象的创建与分配

20.2 基础类型的数组类型创建 该函数的入口在init.cpp->init_globals()&#xff0c;然后再调用universe.cpp->universe2_init()函数&#xff0c;实际执行的函数是Universe::genesis&#xff0c;所以从这开始源码的解析。解析前先了解一下Klass的概念&#xff0c;大家思考…

软件测试面试200问(含答案)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1、B/S架构和C/S架构区别 B/S 只需要有操作系统和浏览器就行&a…

阿里云云原生助力安永创新驱动力实践探索

云原生正在成为新质生产力变革的核心要素和企业创新的数字基础设施。2023 年 12 月 1 日&#xff0c;由中国信通院举办的“2023 云原生产业大会”在北京召开。在大会“阿里云云原生”专场&#xff0c;安永科技咨询合伙人王祺分享了对云原生市场的总览及趋势洞见&#xff0c;及安…

自动驾驶轨迹规划之碰撞检测(三)

欢迎大家关注我的B站&#xff1a; 偷吃薯片的Zheng同学的个人空间-偷吃薯片的Zheng同学个人主页-哔哩哔哩视频 (bilibili.com) 目录 1.基于圆覆盖 2.BVH 3.MATLAB自动驾驶工具箱 4 ROS内置的模型 自动驾驶轨迹规划之碰撞检测&#xff08;一&#xff09;-CSDN博客 自动驾…

ubuntu qt 运行命令行

文章目录 1.C实现2.python实现 1.C实现 下面是封装好的C头文件&#xff0c;直接调用run_cmd_fun()即可。 #ifndef GET_CMD_H #define GET_CMD_H#endif // GET_CMD_H #include <iostream> #include<QString> using namespace std;//system("gnome-terminal -…

【JavaEE进阶】 关于应用分层

文章目录 &#x1f38b;序言&#x1f343;什么是应⽤分层&#x1f38d;为什么需要应⽤分层&#x1f340;如何分层(三层架构)&#x1f384;MVC和三层架构的区别和联系&#x1f333;什么是高内聚低耦合⭕总结 &#x1f38b;序言 在我们进行项目开发时我们如果一股脑将所有代码都…

嵌入式软件分层的思想

文章目录 一、分层的目的二、分层逻辑图三、分层的架构图四、分层的优缺点五、举例六、 优化 一、分层的目的 “高内聚&#xff0c;低耦合的思想”&#xff0c;表示在设计和开发软件系统时&#xff0c;应该使模块之间的关系更加紧密&#xff0c;同时避免模块之间的依赖性过于紧…

【JavaEE】文件操作: File 类的用法和 InputStream, OutputStream 的用法

目录 1. File 概述 1.1 File的属性 1.2 File的构造方法 1.3 File的方法 2.读文件 2.1 InputStream 概述 2.2 FileInputStream 概述 2.3 正确打开和关闭文件的方式 2.4 不同方式读取文件代码示例 2.4 另一种方法:利用 Scanner 进行字符读取 3.写文件 3.1 OutputStre…

如何在苹果手机上进行文件管理

摘要 苹果手机没有像安卓系统那样内置文件管理器&#xff0c;但是可以通过使用克魔开发助手来实现强大的文件管理功能。本文介绍了如何使用克魔开发助手在电脑上管理和传输苹果手机的文件。 引言 很多朋友都在使用苹果手机&#xff0c;但是当需要查看手机中的文件时&#xf…

version-polling一款用于实时检测 web 应用更新的 JavaScript 库

为了解决后端部署之后&#xff0c;如何通知用户系统有新版本&#xff0c;并引导用户刷新页面以加载最新资源的问题。 实现原理 1.使用 Web Worker API 在浏览器后台轮询请求页面&#xff0c;不会影响主线程运行。 2.命中协商缓存&#xff0c;对比本地和服务器请求响应头etag字…

取消lodash.throttle中的默认执行完最后一次函数

我的场景: 我有一个列表,我考虑用户连续点击删除的情况&#xff0c;如果用户连续点击&#xff0c;可能会导致数据库中的数据被删除了&#xff0c;但是我还需要刷新数据列表才能反应到页面上&#xff0c;可是这时候用户又点击了同一条数据的删除按钮多次&#xff0c;导致发起了…

第二讲_HarmonyOS应用创建和运行

HarmonyOS应用创建和运行 1. 创建一个HarmonyOS应用2. 运行新项目2.1 创建本地模拟器2.2 启动本地模拟器2.3 在本地模拟器运行项目 1. 创建一个HarmonyOS应用 打开DevEco Studio&#xff0c;在欢迎页单击Create Project&#xff0c;创建一个新工程。 选择创建Application应用。…