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

归并排序的原理及其多种方法的实现

✨✨✨学习的道路很枯燥,希望我们能并肩走下来!

目录

前言

一、归并排序的基本思想

二、代码实现

1.递归实现

2.非递归实现

三、 归并排序的特性总结


前言

本篇详细介绍了归并排序,让使用者对归并排序有进一步认识,而不是仅仅停留在表面,更好的模拟,为了更好的使用. 文章可能出现错误,如有请在评论区指正,让我们一起交流,共同进步!

一、归并排序的基本思想

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有 序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

归并排序核心步骤:

 

动图分析: 

 

二、代码实现

1.递归实现

MergeSort_A(int* a, int* temp, int begin, int end)
{if (begin == end)return;int mid = (begin + end) / 2;   //取中MergeSort_A(a, temp, begin, mid);  //递归MergeSort_A(a, temp, mid+1, end);int begin1 = begin, end1 = mid;int begin2 = mid + 1, end2 = end;int i = begin;while (begin1 <= end1 && begin2 <= end2)  //结束条件为其中一方停止{if (a[begin1] <= a[begin2])  //依次比较,取小的尾插到temp数组中{temp[i++] = a[begin1++];}else{temp[i++] = a[begin2++];}}while (begin1 <= end1){temp[i++] = a[begin1++];}while (begin2 <= end2){temp[i++] = a[begin2++];}memcpy(a + begin, temp + begin, sizeof(int) * (end - begin + 1));  //覆盖到原数组
}void MergeSort(int* a, int n)
{int temp = (int*)malloc(sizeof(int) * n);  //创建存放数组temp,用于交换排序if (temp == NULL){perror("malloc fail");return;}MergeSort_A(a,temp, 0, n - 1);free(temp);temp = NULL;
}

2.非递归实现

void MergeSortNonR(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");return;}int gap = 1;  //begin(包括1,2,后end同)与end之间的元素个数while (gap < n){for (int j = 0; j < n; j += 2*gap){int begin1 = j, end1 = begin1 + gap - 1;int begin2 = begin1 + gap, end2 = begin2 + gap - 1;int i = j;if (end1 >= n || begin2 >= n) //越界问题处理break;if (end2 >= n)end2 = n - 1;while(begin1 <= end1 && begin2 <= end2){if (a[begin1] <= a[begin2]){tmp[i++] = a[begin1++];}else{tmp[i++] = a[begin2++];}}while (begin1 <= end1){tmp[i++] = a[begin1++];}while (begin2 <= end2){tmp[i++] = a[begin2++];}memcpy(a + j, tmp + j, sizeof(int) * (end2 - j + 1));}gap *= 2;}free(tmp);tmp = NULL;
}

越界问题处理:

 

三、 归并排序的特性总结

1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。

2. 时间复杂度:O(N*logN)

3. 空间复杂度:O(N)

4. 稳定性:稳定


总结

✨✨✨各位读友,本篇分享到内容是否更好的让你理解了数据在内存中的存储,如果对你有帮助给个👍赞鼓励一下吧!!
🎉🎉🎉世上没有绝望的处境,只有对处境绝望的人。
感谢每一位一起走到这的伙伴,我们可以一起交流进步!!!一起加油吧!!!。

相关文章:

  • Rust 函数体内能定义数据类型或者做其他什么事情吗?
  • Rust 语言的 HashMap
  • 代码随想录算法训练营DAY7| C++哈希表Part.2|LeetCode:454.四数相加II、383.赎金信、15. 三数之和、18.四数之和
  • XSS学习(cookie远程登录演示)
  • AXI4-Stream Interconnect IP核(1)——原理
  • MySQL数据库 - 复杂查询(一)
  • 二叉树|701.二叉搜索树中的插入操作
  • Springboot项目之mybatis-plus多容器分布式部署id重复问题之源码解析
  • 【生成对抗网络GAN】一篇文章讲透~
  • 《无名之辈》天涯镖局攻略:高效拉镖窍门!
  • Codeup_1132:问题 A: 最长公共子序列
  • 大话设计模式之模板方法模式
  • 云原生最佳实践系列 4:基于 MSE 和 SAE 的微服务部署与压测
  • 你的 Python 代码需要解释一下了!
  • ideaSSM 人才引进管理系统bootstrap开发mysql数据库web结构java编程计算机网页源码maven项目
  • 分享的文章《人生如棋》
  • $translatePartialLoader加载失败及解决方式
  • ➹使用webpack配置多页面应用(MPA)
  • C++回声服务器_9-epoll边缘触发模式版本服务器
  • centos安装java运行环境jdk+tomcat
  • emacs初体验
  • javascript面向对象之创建对象
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • Swift 中的尾递归和蹦床
  • vue 个人积累(使用工具,组件)
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • 创建一种深思熟虑的文化
  • 多线程 start 和 run 方法到底有什么区别?
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • 优秀架构师必须掌握的架构思维
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • 仓管云——企业云erp功能有哪些?
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • ​MySQL主从复制一致性检测
  • ​学习一下,什么是预包装食品?​
  • #控制台大学课堂点名问题_课堂随机点名
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • $refs 、$nextTic、动态组件、name的使用
  • (02)vite环境变量配置
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (ZT)薛涌:谈贫说富
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (三) prometheus + grafana + alertmanager 配置Redis监控
  • (原)本想说脏话,奈何已放下
  • (转)C语言家族扩展收藏 (转)C语言家族扩展
  • (转)四层和七层负载均衡的区别
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .Net Core和.Net Standard直观理解
  • .NET DevOps 接入指南 | 1. GitLab 安装
  • .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法
  • .NET 中什么样的类是可使用 await 异步等待的?
  • .NET项目中存在多个web.config文件时的加载顺序