当前位置: 首页 > news >正文

归并排序递归与非递归实现

这篇文章笔者带领读者系统学习一下归并排序。源码仍然在github上:z-yi-han/Fundamentals-of-Data-Struct: 这是新人用来记录自己的数据结构学习的过程

归并排序的定义

首先,读者要知道什么是归并排序,其实在之前的文章中,我们写过一道链表相关的算法题,是把两个链表合成的一道题,写那道题的时候,笔者教了读者分而治之的思想,所以归并排序就是这种分而治之的思想,给定一组数据,然后将其分开,然后把分开的每一段都变成有序即可。

递归实现归并排序

当然,主要部分在于封装的那个函数,因为tmp数组不好出现在主函数中,因此在子函数中进行功能的实现,下面给读者看一下子函数代码:

首先,我们先来过一下归并排序的思路,先正面想,给定的数据分成两份,如果这两份都是有序的,那么就分别用一个指针,比大小,然后再存储进一个第三方数组中,前后两个数组中小的先放进去,然后不断往后走,这就是单趟的逻辑。但是现在的问题是无法保证前后数组都是有序的,因此笔者用到了递归,也就是通过不断地分组,直到只有一个元素,而一个元素那必定是有序的,然后返回上一个栈帧,有两个元素,两个元素再比较即可,有序之后再往上走,就是四个元素,在往上前四个后四个全部有序,归并一下8个就会有序,依次类推即可,相信读者能感受出来,笔者刚才说的话其实就是归并排序,类似于二叉树的后序遍历,先子树再结点。然后就是最重要的归并过程了,首先分割区间直接mid即可,然后前后两段开始从头比较,小的放入tmp中,当比较完之后,剩下的部分就直接放入tmp就行。这就是用递归思想解决归并排序,在二叉树的学习之后,其实很好理解了。

非递归实现归并排序

上面的内容其实对于已经学完二叉树的读者来说相信并不难理解,接下来笔者带领读者学习用非递归法实现归并排序,这种方法对于笔者和读者来说都是不小的挑战,希望读者跟着笔者的思路认真思考。

首先,我们的目标是模拟实现递归,在之前的文章中,我们用栈来实现了递归思路进而完成了非递归实现快速排序,然而在这种情况下,真的可以用栈来模拟递归吗?这就要回到归并排序的过程了,首先归并排序是非常规则的一分为二,不断分治进而使其有序,如果我们用栈来模拟实现,没进入一次递归,出来的时候还需要一个栈来存数据,因此很麻烦,回想一下之前写的栈模拟递归实现,快排每次划分后的区间是不对称的,因为区间取决于基准,而这个基准是不确定的,因此那棵树相当不规则,而快排就是先处理一个子区间,另一个子区间留着递归,因此快排用栈更自然。总结来说:归并排序子区间规模有规律所以用循环,快排子区间规模无规律所以用栈保存剩余区间。

经过上述论述,相信读者就已经知道了,我们要用循环来模拟实现归并排序。下面我们就来改造一下原来的代码,模拟非递归实现归并排序:

首先,我们先思考循环归并的过程,其实很简答:刚开始11归并,因为最基本的有序就是一个元素,注意11归并的结果是2个元素有序,然后就22归并,以此类推即可,因此每次循环的过程都需要两个子区间,现在规定每次的长度是gap,gap分别是1,2,4,8...,其实代码已经可以出来了:

注意控制gap,gap就是每组的长度,比如11归并,gap就是1,22归并gap就是2,以gap为长度时,每次i加上gap即可 。主体代码我们已经写明白了 ,但是 有一个很严重的问题——数组会出现越界情况:这是因为我们归并的时候是按照11,22,44,88....的,因此一旦是奇数或者不是2的倍数那就会导致数组直接越界:

因此我们要想办法避免那种错误,其实这种错误一共有两类,一是右边的区间都越界,第二种是begin2未越界,end2越界了,修正的方式其实并不难,前者既然后边区间都越界 ,那么干脆不用就好了,后者只需要修正一下即可:

最后我们测试一下:

OK,本篇文章到此结束了,希望读者多支持。


文章转载自:

http://BVeNK4G3.kfbth.cn
http://kQF7ePRb.kfbth.cn
http://dsQlkg71.kfbth.cn
http://9XuWPoAv.kfbth.cn
http://258QIPoE.kfbth.cn
http://uEzDKjuy.kfbth.cn
http://3pXYBTct.kfbth.cn
http://55FLbZ0S.kfbth.cn
http://lyO4otma.kfbth.cn
http://UdlBBaee.kfbth.cn
http://i2aFnQYL.kfbth.cn
http://PrSPfFJL.kfbth.cn
http://Es5nSyMD.kfbth.cn
http://RulEgvGd.kfbth.cn
http://9xRXaJKb.kfbth.cn
http://VmRwKlPT.kfbth.cn
http://vLWC0BCI.kfbth.cn
http://4jihh2XY.kfbth.cn
http://V4ULaRVT.kfbth.cn
http://V8IduVs3.kfbth.cn
http://vW5pp4fm.kfbth.cn
http://OJmP84bA.kfbth.cn
http://OrOqBD6a.kfbth.cn
http://m4oHcoe1.kfbth.cn
http://McJ9IpiK.kfbth.cn
http://P7y2x4Cj.kfbth.cn
http://pcS4KMR7.kfbth.cn
http://Rk9jP68S.kfbth.cn
http://RWyMnssC.kfbth.cn
http://LxyAsUKs.kfbth.cn
http://www.dtcms.com/a/383819.html

相关文章:

  • 第9课:工作流编排与任务调度
  • 淘客app的接口性能测试:基于JMeter的高并发场景模拟与优化
  • C++ 继承:从概念到实战的全方位指南
  • Python中全局Import和局部Import的区别及应用场景对比
  • S16 赛季预告
  • 【硬件-笔试面试题-95】硬件/电子工程师,笔试面试题(知识点:RC电路中的时间常数)
  • synchronized锁升级的过程(从无锁到偏向锁,再到轻量级锁,最后到重量级锁的一个过程)
  • Altium Designer(AD)自定义PCB外观颜色
  • Flink快速上手使用
  • 安卓学习 之 选项菜单(OptionMenu)
  • CKA04--storageclass
  • Dask read_csv未指定数据类型报错
  • 【代码随想录算法训练营——Day11】栈与队列——150.逆波兰表达式求值、239.滑动窗口最大值、347.前K个高频元素
  • TruthfulQA:衡量语言模型真实性的基准
  • 继承与多态
  • Python爬虫实战:研究Pandas,构建新浪网股票数据采集和分析系统
  • 【从零开始】14. 数据评分与筛选
  • 正则表达式与文本三剑客(grep、sed、awk)基础与实践
  • JavaWeb--day5--请求响应分层解耦
  • 去卷积:用魔法打败魔法,让图像清晰
  • Java开发者LLM实战——LangChain4j最新版教学知识库实战
  • 算法 --- 哈希表
  • 【科研绘图系列】R语言绘制全球海洋温度对浮游生物分裂率影响的数据可视化分析
  • 141.环形链表
  • C++ 最短路SPFA
  • 一文读懂 Java 注解运行原理
  • Dify开发中系统变量(system)和用户变量(user)的区别
  • 扩散模型之(五)基于概率流ODE方法
  • 【代码模板】Linux内核模块带指针的函数如何返回错误码?(ERR_PTR(-ENOMEM)、IS_ERR(ent)、PTR_ERR(ent))
  • 查询 mysql中 所有的 非空记录字段