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

迭代归并:归并排序非递归实现解析


在这里插入图片描述

🎬 鸽芷咕:个人主页

 🔥 个人专栏: 《数据结构&算法》《粉丝福利》

⛺️生活的理想,就是为了理想的生活!

📋 前言

归并排序的思想上我们已经全部介绍完了,但是同时也面临和快速排序一样的问题那就是递归消耗的栈帧空间太大了,所以对此我们必须掌握非递归的排序思想。

文章目录

  • 📋 前言
  • 一、非递归实现的思想
  • 二、非递归实现的过程
    • 2.1 非递归实现的调整
    • 2.2 调整思路讲解
    • 2.3 归并非递归完整代码
  • 三、归并排序的总结
  • 📝文章结语:

一、非递归实现的思想

归并实现的思想无非就是先将 每个数都递归 分割为一个小区间然后再进行排序,之后递归 回溯 上一个区间 这时 上一个区间都排好了所以可以在进行排序就这样循环上去。

在这里插入图片描述

在这里插入图片描述

既然要用非递归那么我们是不是可以这样想 直接吧每个区间定义为 1 进行归并然后再来进行循环到上一组归并排序:
-在这里插入图片描述
这样就可以利用循环来吧归并排序非递归化了

二、非递归实现的过程

好了具体思想那么我们懂了,既然要进行从最小区间 1 开始那么我们肯定需要需要定义 一个 gap = 1 开始循环

  • 然后每次 gap * = 2; 来进行调整我们的归并区间的间距进行归并
  • 而排序的时候则又需要一个循环了来进行进行对每个区间进行归并排序
  • int i = 0; i < n; i += (gap*2)
  • 为什么每次 i += (gap*2)因为 每次当这个区间排完了之后就需要跳到下一个区间开始

🍸 代码演示:

// 归并排序非递归实现
void MergeSortNonR(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc file");exit(-1);}int gap = 1;while (gap < n){for (int i = 0; i < n; i += (gap*2)){int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + (2 * gap) - 1;int index = i;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[index++] = a[begin1++];}else{tmp[index++] = a[begin2++];}}while (begin1 <= end1){tmp[index++] = a[begin1++];}while (begin2 <= end2){tmp[index++] = a[begin2++];}memcpy(a + i, tmp + i, sizeof(int) * (2*gap));}printf("\n");gap *= 2;}free(tmp);
}

2.1 非递归实现的调整

以上就是非递归实现的代码了,但你真的以为非递归就这样结束了?哈哈哈其实没有我们前面举例的是2的倍数来进行排序的但是当我们排序10之类的不是2的倍数就会出现越界的情况:

🔥 注:是上面我们每次 第二个区间都是 i + (2 * gap) - 1 但是当不是2的整数倍来实现的话不就越界了

2.2 调整思路讲解

在这里插入图片描述
哦豁大家是不是看到了当第二次排序的时候 begin2end2 都越界了,第三次归并的时候甚至 end2 都 越界了

这其实非常简单既然第二个区间都越界的话那么是不是就不需要进行归并了,你想啊连第二个区间都不存在的话第一个区间和谁归并?

  • 而只有 end2 越界的话咱们修正一下不就好了,只让它归并一个数
    在这里插入图片描述

🔥 注:这里还要注意memcpy 的时候的copy大小。

以前我们进行 copy 的时候都是 2倍的gap 但是当才不是整数倍的时候就需要调整了
在这里插入图片描述

i 每次都是要归并的区间开头, 而 end2 倍修正了之后就是区间尾了他们一相减就好了
🔥 注:相减了之后要加1,因为是闭区间。(3-0)虽然是相减了但是我们实际复制的是4个数

在这里插入图片描述

2.3 归并非递归完整代码


// 归并排序非递归实现
void MergeSortNonR(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc file");exit(-1);}int gap = 1;while (gap < n){for (int i = 0; i < n; i += (gap*2)){int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + (2 * gap) - 1;if (begin2 >= n)break;if (end2 >= n)end2 = n-1;printf("[%d,%d][%d,%d] ", begin1, end1, begin2, end2);int index = i;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[index++] = a[begin1++];}else{tmp[index++] = a[begin2++];}}while (begin1 <= end1){tmp[index++] = a[begin1++];}while (begin2 <= end2){tmp[index++] = a[begin2++];}memcpy(a + i, tmp + i, sizeof(int) * (end2-i+1));}printf("\n");gap *= 2;}free(tmp);
}

三、归并排序的总结

  1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
  2. 时间复杂度:O(N*logN)
  3. 空间复杂度:O(N)
  4. 稳定性:稳定

📝文章结语:

看到这里了还不给博主扣个:
⛳️ 点赞🍹收藏 ⭐️ 关注

💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
拜托拜托这个真的很重要!
你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。
在这里插入图片描述

相关文章:

  • 一起玩儿物联网人工智能小车(ESP32)——21. ESP32的LED PWM控制器说明
  • List常见方法和遍历操作
  • Linux Shell 017-文本行合并工具paste
  • Spring Boot IO官方文档中文版
  • 雨课堂作业整理
  • 几代WiFi有什么差异,它们有什么区别
  • Python---多进程---多线程
  • <JavaEE> TCP 的通信机制(四) -- 流量控制 和 拥塞控制
  • Python 中的运算符介绍(1)
  • 第二节 linux操作系统安装与配置
  • 进阶学习——Linux系统磁盘管理与文件系统
  • 4、内存泄漏检测(多线程)
  • 【网络安全 | Misc】miss_01 太湖杯
  • OSPF的DR与BDR-新版(16)
  • MariaDB单机多实例的配置方法
  • 收藏网友的 源程序下载网
  • 《Java8实战》-第四章读书笔记(引入流Stream)
  • 【mysql】环境安装、服务启动、密码设置
  • java中的hashCode
  • leetcode46 Permutation 排列组合
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • vue 配置sass、scss全局变量
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • 不用申请服务号就可以开发微信支付/支付宝/QQ钱包支付!附:直接可用的代码+demo...
  • 分享几个不错的工具
  • 聊聊flink的TableFactory
  • 前端之React实战:创建跨平台的项目架构
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 我建了一个叫Hello World的项目
  • 责任链模式的两种实现
  • 正则学习笔记
  • mysql面试题分组并合并列
  • ​ArcGIS Pro 如何批量删除字段
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • ​业务双活的数据切换思路设计(下)
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • # 透过事物看本质的能力怎么培养?
  • #1015 : KMP算法
  • #pragma 指令
  • #QT(TCP网络编程-服务端)
  • (22)C#传智:复习,多态虚方法抽象类接口,静态类,String与StringBuilder,集合泛型List与Dictionary,文件类,结构与类的区别
  • (C语言)逆序输出字符串
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (一)appium-desktop定位元素原理
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (转载)Google Chrome调试JS
  • .bat批处理(十一):替换字符串中包含百分号%的子串
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .NET/C# 编译期间能确定的相同字符串,在运行期间是相同的实例
  • .NET成年了,然后呢?
  • .NET高级面试指南专题十一【 设计模式介绍,为什么要用设计模式】