深入浅出排序算法之归并排序

目录

1. 归并排序的原理

1.1 二路归并排序执行流程

2. 代码分析

2.1 代码设计

3. 性能分析

4. 非递归版本


1. 归并排序的原理

“归并”一词的中文含义就是合并、并入的意思,而在数据结构中的定义是将两个或者两个以上的有序表组合成一个新的有序表。

归并排序(Merging Sort)就是利用归并的思想实现的排序方法。它的原理是假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[n/2](\left \lfloor x \right \rfloor表示不小于x的最小整数)个长度为2或1的有序子序列;再两两归并,……,如此重复,直至得到一个长度为n的有序序列为止,这种排序方法成为2路归并排序。

1.1 二路归并排序执行流程

原始序列:49   38   65   97   76   13   27

(1)将原始序列看成7个只含有一个关键字的子序列,显然这些子序列都是有序的。

子序列1:49;子序列2:38;子序列3:65;子序列4:97;子序列5:76;子序列6:13;子序列7:27

(2)两两归并,形成若干有序二元组,即49和38归并成{38   49},65和97归并成{65   97},76和13归并成{13   76},27没有归并对象,保持原样{27}。第一趟二路归并排序结束,结果如下:

{38   49},{65   97},{13   76},{27}

(3)再将这个序列看成若干二元组子序列

子序列1:38   49;子序列2:65   97;子序列3:13   76;子序列4:27;

最后一个子序列长度可能是1,也可能是2。

(4)继续两两归并,形成若干有序四元组(同样,最后的子序列中不一定有4个关键字),即{38   49}和{65   97}归并形成{38   49   65   97},{13   76}和{27}归并形成{13   27   76}。第二趟二路归并排序结束,结果如下:

{38   49   65   97},{13   27   76}

(5)最后只有两个子序列了,再进行一次归并,就可完成整个二路归并排序,结果如下:

13   27   38   49   65   76   97

  

2. 代码分析

大家先看看有没有思路!

 3,2,1 开始我的表演哈哈哈!

 请看图解:

2.1 代码设计

根据图解我们要怎么设计方法呢?

我打算把分解功能写成一个方法,合并功能写成一个方法。具体实现如下: 

    public static void mergeSort1(int[] array){mergeSortDivide(array,0, array.length - 1);}//分解private static void mergeSortDivide(int[] array,int left,int right){//终止条件:left > rightwhile(left >= right){return;}int mid = (left+right)/2;//递归左子序列mergeSortDivide(array,left,mid);//递归右子序列mergeSortDivide(array,mid+1,right);//合并merge(array,left,right,mid);}//合并private static void merge(int[] array,int start,int end,int mid){//左子序列从start开始int s1 = start;//右子序列从mid+1开始int s2 = mid + 1;//新建一个数组,作为复制数组int[] tmp = new int[end - start + 1];//k表示中间数组的元素下标int k = 0;//开始比较while(s1 <= mid && s2 <= end){if(array[s1] <= array[s2]){//将小的值赋值给tmp[k]//小伙伴们这可以思考一下:为什么不能先写array[s2] <= array[s1]?//等下看我下面的解析!tmp[k++] = array[s1++];} else{//array[s2] <= array[s1]的情况tmp[k++] = array[s2++];}}//有剩余的数组//左子序列while(s1 <= mid){tmp[k++] = array[s1++];}//右子序列while(s2 <= end){tmp[k++] = array[s2++];}//将tmp数组的值赋值给array数组for(int i = 0;i<tmp.length;i++){array[i+start] = tmp[i];}}

回答问题:为什么不能先写array[s2] <= array[s1]?

答:归并排序是稳定的。如果先写array[s2] <= array[s1],那么在s2开始的元素与s1开始的元素相等的话,例如:1<=1,那么本该在后面的1就会移到前面,导致这段代码实现的归并排序不稳定了!

3. 性能分析

时间复杂度空间复杂度
O(n*log(n))O(n)

4. 非递归版本

上面的版本是递归版本,接下来是非递归版本。

    private static void merge(int[] array,int start,int end,int mid) {int s1 = start;//int e1 = mid;int s2 = mid+1;//int e2 = end;int[] tmp = new int[end-start+1];int k = 0;//tmp数组的下标while (s1 <= mid && s2 <= end) {if(array[s1] <= array[s2]) {tmp[k++] = array[s1++];}else {tmp[k++] = array[s2++];}}while (s1 <= mid) {tmp[k++] = array[s1++];}while (s2 <= end) {tmp[k++] = array[s2++];}for (int i = 0; i < tmp.length; i++) {array[i+start] = tmp[i];}}public static void mergeSort(int[] array) {int gap = 1;while (gap < array.length) {// i += gap * 2 当前gap组的时候,去排序下一组for (int i = 0; i < array.length; i += gap * 2) {int left = i;int mid = left+gap-1;//有可能会越界if(mid >= array.length) {mid = array.length-1;}int right = mid+gap;//有可能会越界if(right>= array.length) {right = array.length-1;}merge(array,left,right,mid);}//当前为2组有序  下次变成4组有序gap *= 2;}}

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

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

相关文章

Python-pptx教程之一从零开始生成PPT文件

简介 python-pptx是一个用于创建、读取和更新PowerPoint&#xff08;.pptx&#xff09;文件的python库。 典型的用途是根据动态内容&#xff08;如数据库查询、分析数据等&#xff09;&#xff0c;将这些内容自动化生成PowerPoint演示文稿&#xff0c;将数据可视化&#xff0c…

【IDEA配置】IDEA配置

参考视频&#xff1a;【idea必知必会】优化设置 告别卡顿 1. 显示内存 右击底下空白区域&#xff0c;出现memory indicator内存指示器&#xff0c;点击勾选即可显示。有的是在Settings->Appearance->Window Options里&#xff0c;如图所示&#xff1a; 2. 内存设置 …

虚拟世界游戏定制开发:创造独一无二的虚拟体验

在游戏开发领域&#xff0c;虚拟世界游戏定制开发是一项引人注目的任务&#xff0c;旨在满足客户独特的需求和愿景&#xff0c;创造一个完全个性化的虚拟世界游戏。这种类型的游戏开发需要专业的技能、深刻的游戏开发知识和密切的与客户合作&#xff0c;以确保游戏满足客户的期…

CI2454 2.4g无线MCU芯片应用

Ci2454集成MCU芯片 | Ci2454是一款集成无线收发器和 8 位 RISC&#xff08;精简指令集&#xff09;MCU 的SOC芯片。 #Ci2454芯片 集成MCU芯片# 中国芯片# 无线收发器特性&#xff1a; 工作在 2.4GHz ISM 频段 调制方式&#xff1a;GFSK/FSK 数据速率&#xff1a;2Mbps/1Mbps…

数据库基础(一)【MySQL】

文章目录 安装 MySQL修改密码连接和退出数据库服务器使用 systemctl 管理服务器进程配置数据库从文件角度看待数据库查看连接情况 安装 MySQL 这是在 Linux 中安装 MySQL 的教程&#xff1a;Linux 下 MySQL 安装。本系列测试用的 MySQL 版本是 5.7&#xff0c;机器是 centOS7.…

LabVIEW中将枚举与条件结构一起使用

LabVIEW中将枚举与条件结构一起使用 枚举是一个具有相应数值的字符串标签型列表。在LabVIEW&#xff08;U8 &#xff0c; U16-默认值和U32&#xff09;中以无符号整数形式应用。 例如&#xff0c;可以有一个枚举保存四个季节&#xff0c;在这种情况下&#xff0c;每个字符串都…

Go之流程控制大全: 细节、示例与最佳实践

引言 在计算机编程中&#xff0c;流程控制是核心的组成部分&#xff0c;它决定了程序应该如何根据给定的情况执行或决策。以下是Go语言所支持的流程控制结构的简要概览&#xff1a; 流程控制类型代码if-else条件分支if condition { } else { }for循环for initialization; con…

GoLong的学习之路(一)语法之变量与常量

目录 GoLang变量批量声明变量的初始化类型推导短变量声明匿名变量 常量iota&#xff08;特殊&#xff09;&#xff08;需要重点记忆&#xff09; GoLang go的诞生为了解决在21世纪多核和网络化环境越来越复杂的变成问题而发明的Go语言。 go语言是从Ken Thomepson发明的B语言和…

分享个包含各省、市、区的编码数据的在线静态资源脚本

在翻《SpringBootVue3》——十三尼克陈作者的大型前后端分离项目实战里面&#xff0c;在看到地址管理的部分时&#xff0c;发现了该作者记录有一个静态的地址资源脚本 这里做个记录&#xff0c;打点 一、引入js <script src"https://s.yezgea02.com/1641120061385/td…

2024王道考研计算机组成原理——指令系统

零、本章概要 指令寻址&#xff1a;解决的是PC"1"的问题 数据寻址&#xff1a;使用寄存器/内存/结合 基址寻址&#xff1a;用于多道程序的并发执行 直接寻址&#xff1a;call 0x12345678 变址寻址&#xff1a;esi edi用于循环&#xff0c;因为使用直接寻址需要一堆…

超市商品管理系统 JAVA语言设计实现

目录 一、系统介绍 二、系统下载 三、系统截图 一、系统介绍 基于VueSpringBootMySQL的超市商品管理系统&#xff0c;超市区域模块、超市货架模块、商品类型模块、商品档案模块&#xff0c;分为用户网页端和管理后台&#xff0c;基于角色的访问控制&#xff0c;可将权限精确…

【Java】<泛型>,在编译阶段约束操作的数据结构,并进行检查。

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ JAVA泛型 泛型介绍&#xff1a; ①泛型&#…

HTML+CSS+JS+Django 实现前后端分离的科学计算器、利率计算器(附全部代码在gitcode链接)

&#x1f9ee;前后端分离计算器 &#x1f4da;git仓库链接和代码规范链接&#x1f4bc;PSP表格&#x1f387;成品展示&#x1f3c6;&#x1f3c6;科学计算器&#xff1a;1. 默认界面与页面切换2. 四则运算、取余、括号3. 清零Clear 回退Back4. 错误提示 Error5. 读取历史记录Hi…

2023年中职组“网络安全”赛项云南省竞赛任务书

2023年中职组“网络安全”赛项 云南省竞赛任务书 一、竞赛时间 总计&#xff1a;360分钟 竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 A模块 A-1 登录安全加固 180分钟 200分 A-2 本地安全策略配置 A-3 流量完整性保护 A-4 事件监控 A-5 服务加固…

VSCode 自动格式化

1.打开应用商店&#xff0c;搜索 prettier code formatter &#xff0c;选择第一个&#xff0c;点击安装。 2.安装完成后&#xff0c;点击文件&#xff0c;选择首选项&#xff0c;选择设置。 3.在搜索框内输入 save &#xff0c;勾选在保存时格式化文件。 4.随便打开一个文件&a…

Access denied for user ‘root‘@‘localhost‘ (using password:YES) 解决方案(禅道相关)

如果是忘记Mysql密码或更改权限后访问不了的问题请直接跳转以下链接&#xff1a; MySQL登录时出现Access denied for user ‘root‘‘localhost‘ (using password: YES)无法打开的解决方法 关于这个问题&#xff0c;网上查到的解决方法基本都是因为忘记Mysql密码或者用户权限问…

【Java 进阶篇】Java XML解析:从入门到精通

XML&#xff08;可扩展标记语言&#xff09;是一种常用的数据格式&#xff0c;用于存储和交换数据。在Java中&#xff0c;XML解析是一项重要的任务&#xff0c;它允许您从XML文档中提取和操作数据。本篇博客将从基础开始&#xff0c;详细介绍如何在Java中解析XML文档&#xff0…

前端AJAX入门到实战,学习前端框架前必会的(ajax+node.js+webpack+git)(二)

阳光总在风雨后&#xff0c;请相信有彩虹。 案例 - 图书管理 bootstrap弹框 需求&#xff0c;点击添加按钮&#xff0c;没有离开当前页面&#xff0c;在当前页面弹出弹框&#xff08;弹窗&#xff09; 先学着实现一个简单的弹框&#xff0c;如下图右下角 bootstrap有两种方式…

20231024后端研发面经整理

1.如何在单链表O(1)删除节点&#xff1f; 狸猫换太子 2.redis中的key如何找到对应的内存位置&#xff1f; 哈希碰撞的话用链表存 3.线性探测哈希法的插入&#xff0c;查找和删除 插入&#xff1a;一个个挨着后面找&#xff0c;知道有空位 查找&#xff1a;一个个挨着后面找…

gin 框架出现runtime error: index out of range [0] with length 0

之前是这样的&#xff1a; category : c.Request.Form["type"][0] 加上这一句就变成了 fmt.Println(c.Request.FormFile("type")) category : c.Request.Form["type"][0]