排序算法之——归并排序

归并排序

  • 1. 基本思想
  • 2. 数据的分解
  • 3. 数据的合并
  • 4.归并排序的实现
    • 4.1 递归实现
      • 4.1.1 一个易错点
      • 4.1.2 运行结果
    • 4.2 非递归实现
      • 4.2.1 图示思路
      • 4.2.2 代码实现
      • 4.2.3 一个易错点
      • 4.2.4 修改后的代码
      • 4.2.5 运行结果
  • 6. 时间复杂度
  • 7. 空间复杂度
  • 8. 稳定性
  • 9. 动图演示

1. 基本思想

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

2. 数据的分解

数据的分解采用递归分解,形式上和一棵完全二叉树相似。
在这里插入图片描述

3. 数据的合并

数据的合并过程不仅仅是将短数据合成长的,否则这仅仅是原来分解数据的逆过程。数据的合并过程中牵扯到对两组数据的排序再合并。为了实现这一目的,采用了双指针法。下面以图1.1中的在这里插入图片描述
两组数据为例进行说明;
在这里插入图片描述

4.归并排序的实现

4.1 递归实现

/*** 归并排序* 时间复杂度:O(n*logn)* 空间复杂度:O(n)* 稳定性:稳定* @param array*/public static void mergeSort(int[] array){//为了使参数只有一个,保持统一性,调用了mergeFunc()方法mergeFunc(array,0, array.length-1);}public static void mergeFunc(int[] array,int left,int right){if(left >= right){return;}int mid = left + (right - left) / 2;mergeFunc(array,left,mid); //分解左边mergeFunc(array,mid+1,right);//分解右边//开始合并merge(array,left,mid,right);}public static void merge(int[] array,int left,int mid,int right){int s1 = left;int e1 = mid;int s2 = mid+1;int e2 = right;int[] tmpArray = new int[right - left + 1];int k = 0;//1.保证两个数组都有数据while(s1 <= e1 && s2 <= e2){if(array[s1] < array[s2]){tmpArray[k] = array[s1];k++;s1++;}else{tmpArray[k] = array[s2];k++;s2++;}}//2.其中一个数组已经拷贝完,将另一个数组剩下的部分拷贝回临时数组while(s1 <= e1){tmpArray[k] = array[s1];k++;s1++;}while(s2 <= e2){tmpArray[k] = array[s2];k++;s2++;}//3.将临时数组中的数据拷贝回原数组中for(int i = 0;i < k;i++){array[left + i] = tmpArray[i];//这一步array[]的下标要注意}}

4.1.1 一个易错点

在将临时数组tmpArray[]中的数据放回原数组array[]的过程中,要特别注意下标问题。如图:
在这里插入图片描述
黄线框里的代码不能写成array[i] = tmpArray[i]。以一张图说明:
在这里插入图片描述

4.1.2 运行结果

在这里插入图片描述

4.2 非递归实现

4.2.1 图示思路

在这里插入图片描述

4.2.2 代码实现

/*** 并排序(非递归实现)* @param array*/
public static void mergeSortNotRecursion(int[] array){//为了使参数只有一个,保持统一性,调用了mergeFunc()方法int gapNumber = 1; //gapNumber表示每组数据的个数//最外层控制组数while(gapNumber < array.length){for(int i = 0;i < array.length;i += gapNumber){//i每次走gapNumber个距离int left = i;int mid = left + gapNumber - 1;int right = mid + gapNumber;merge(array,left,mid,right);}gapNumber *= 2;}}public static void merge(int[] array,int left,int mid,int right){int s1 = left;int e1 = mid;int s2 = mid+1;int e2 = right;int[] tmpArray = new int[right - left + 1];int k = 0;//1.保证两个数组都有数据while(s1 <= e1 && s2 <= e2){if(array[s1] < array[s2]){tmpArray[k] = array[s1];k++;s1++;}else{tmpArray[k] = array[s2];k++;s2++;}}//2.其中一个数组已经拷贝完,将另一个数组剩下的部分拷贝回临时数组while(s1 <= e1){tmpArray[k] = array[s1];k++;s1++;}while(s2 <= e2){tmpArray[k] = array[s2];k++;s2++;}//3.将临时数组中的数据拷贝回原数组中for(int i = 0;i < k;i++){array[left + i] = tmpArray[i];//这一步array[]的下标要注意}}

4.2.3 一个易错点

在这里插入图片描述

4.2.4 修改后的代码

while(gapNumber < array.length){for(int i = 0;i < array.length;i += gapNumber){//i每次走gapNumber个距离int left = i;int mid = left + gapNumber - 1;if(mid >= array.length){mid = array.length - 1;}int right = mid + gapNumber;if(right >= array.length){right = array.length - 1;}merge(array,left,mid,right);}gapNumber *= 2;}

4.2.5 运行结果

在这里插入图片描述

6. 时间复杂度

整个归并排序的过程相当于一棵完全二叉树的创建过程。假设待排序的数据的容量为n,则完全二叉树的高度为log2(n+1)(向上取整),每一层遍历n个数据,最终用时nlog2(n+1),故最终的时间复杂度为O(nlog2(n))。

7. 空间复杂度

由于每次归并两组数据的过程中都借用了临时数组tmpArray[],且tmpArray[]的长度至少要等于两组数据的元素个数之和,故最终的空间复杂度为O(n)。

8. 稳定性

归并排序是一种稳定排序。

9. 动图演示

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

了解CSS Flex:解析实例、用法和案例研究

Flex布局 01-标准流 标准流也叫文档流&#xff0c;指的是标签在页面中默认的排布规则&#xff0c;例如&#xff1a;块元素独占一行&#xff0c;行内元素可以一行显示多个。 02-浮动 基本使用 作用&#xff1a;让块元素水平排列。 属性名&#xff1a;float 属性值 left&…

发电机中为什么电磁控制阀如此省油?

为什么电磁控制阀如此省油? 1。细油浸电磁运动的设计。 推杆浸没在系统中的油中&#xff0c;具有缓冲效果。即使在高压和高频开关的情况下&#xff0c;它仍然可以保持沉默。 油浸滑动芯完全消除了运动部件之间的摩擦和滑动柱的摩擦&#xff0c;以及由此引起的油泄漏&#xff…

《授她以柄》口碑暴跌,短剧售后学的错误示范

2024年的春节档&#xff0c;短剧刷足了存在感&#xff0c;不只是多部短剧出圈霸屏&#xff0c;售后的幺蛾子也不少。 继《我在八零年代当后妈》在抖音刷屏后&#xff0c;腾讯短剧《授她以柄》强势登顶德塔文、Vlinkage等多个榜单&#xff0c;分账票房破500万&#xff0c;成为了…

面试必问!JVM 不得不说的知识点(三)

一、 JVM指令集: 1. 了解Java虚拟机的指令集是什么?举例说明一些常见的指令及其作用。 Java虚拟机的指令集是一组用于执行Java程序的低级操作码。这些指令直接在Java虚拟机上执行,可以认为是Java程序的二进制表示形式。以下是一些常见的Java虚拟机指令及其作用的例子: ic…

供水管网监测远程管理解决方案

供水管网监测远程管理解决方案 供水管网作为城市基础设施的重要组成部分&#xff0c;其运行状况直接影响到居民的饮用水安全和城市的水资源利用。然而&#xff0c;传统供水管网管理存在管理效率低、漏损率高、故障排查困难等问题。随着物联网技术的不断发展&#xff0c;利用物…

桥接模式:解耦抽象与实现,实现灵活多变的扩展结构

文章目录 一、引言二、应用场景与技术背景三、模式定义与实现四、实例详解五、优缺点分析总结&#xff1a; 一、引言 ​ 桥接模式是一种结构型设计模式&#xff0c;它将抽象部分与它的实现部分分离&#xff0c;使它们可以独立变化。这种模式通过创建一个抽象层和实现层的结构&…

io进程线程第七天

1.使用消息队列完成两个进程之间的通信 程序A代码&#xff1a; #include <myhead.h> struct msgbuf {long mtype;char mtext[1024]; }; //定义一个宏&#xff0c;表示消息正文内容的大小 #define MSGSIZE sizeof(struct msgbuf)-sizeof(long)int main(int argc, const c…

目标检测-Transformer-ViT和DETR

文章目录 前言一、ViT应用和结论结构及创新点 二、DETR应用和结论结构及创新点 总结 前言 随着Transformer爆火以来&#xff0c;NLP领域迎来了大模型时代&#xff0c;成为AI目前最先进和火爆的领域&#xff0c;介于Transformer的先进性&#xff0c;基于Transformer架构的CV模型…

Devvortex

目标靶机 攻击机IP地址为10.10.16.2 信息收集 # nmap -sT --min-rate 10000 -p- 10.10.11.242 -oN port.nmap Starting Nmap 7.94 ( https://nmap.org ) at 2024-02-21 10:32 CST Warning: 10.10.11.242 giving up on port because retransmission cap hit (10). Nma…

第三方支付机构最新“POS”机刷卡费用公式

多家支付机构发布了最新的刷卡费用公示。 《非银行支付机构监督管理条例》(简称《条例》)由国务院发布&#xff0c;明确规定非银行支付机构须按照相关价格法律、行政法规的规定&#xff0c;合理确定并公开支付业务的收费项目和收费标准&#xff0c;以明码标价。 支付行业在春节…

Shell的运行原理以及Linux当中的权限问题

本专栏内容为&#xff1a;Linux学习专栏&#xff0c;分为系统和网络两部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握Linux。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;Liunx从入门到精通 &#x1f69a;代码仓库&#xff1a;小…

k8s(2)

目录 一.二进制部署k8s 常见的K8S安装部署方式&#xff1a; k8s部署 二进制与高可用的区别 二.部署k8s 初始化操作&#xff1a; 每台node安装docker&#xff1a; 在 master01 节点上操作; 准备cfssl证书生成工具:&#xff1a; 执行脚本文件&#xff1a; 拉入etcd压缩包…

国产大模型,不会开启“烧钱游戏”

最近&#xff0c;OpenAI的Sora又在科技圈投入一枚深水炸弹。全球对于大模型的关注&#xff0c;又一次达到高峰。 聚焦到国内&#xff0c;百度、科大讯飞、商汤、华为等大型企业&#xff0c;以及海量的创业小公司都在布局大模型。以往每一次风口吹来的时候&#xff0c;资本总会…

springboot网站开发02-接入持久层框架mybatisPlus

springboot网站开发02-接入持久层框架mybatisPlus&#xff01;经过上一小节内容分享&#xff0c;我们的项目嵌套模式框架搭建好了&#xff0c;下面就是开始编辑具体的业务代码了&#xff0c;我们使用到了持久层框架是mybatisPlus插件。下面是一些具体的植入框架的操作步骤。 第…

C# cass10 宗地初始化-根据 “预编号” “权利人”图层对应信息 批量添加到宗地图层

运行环境Visual Studio 2022 c# cad2016 cass10 根据 “预编号” “权利人”图层对应信息 批量添加到宗地图层 一、主要步骤 zdimport 方法&#xff1a;这个方法用于导入宗地信息。首先通过调用 AutoCAD API 获取当前活动文档、数据库和编辑器对象。然后根据 CreatePalette.Se…

[OpenAI]继ChatGPT后发布的Sora模型原理与体验通道

前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff1a;https://www.captainbed.cn/z ChatGPT体验地址 文章目录 前言OpenAI体验通道Spacetime Latent Patches 潜变量时空碎片, 建构视觉语言系统…

day11_内部类代码块枚举课后练习 - 参考答案

文章目录 day11_课后练习代码阅读题第1题第2题第3题第4题第5题第6题第7题第8题第9题第10题第11题第12题 代码编程题第13题 day11_课后练习 代码阅读题 第1题 知识点&#xff1a;实例初始化 案例&#xff1a;判断运行结果 package com.atguigu.test01;class HelloA{public …

稳定运行矿山鸿蒙系统——飞凌嵌入式的这2款核心板获得「矿鸿资质证书」

飞凌嵌入式FETMX6ULL-S核心板和FETA40i-C核心板近期通过了“矿鸿兼容性测试认证”&#xff0c;这两款嵌入式核心板与矿鸿OS的结合将进一步推动煤矿行业的智能化进程。 矿鸿&#xff08;MineHarmony&#xff09;操作系统是由国家能源集团基于鸿蒙系统推出的一款专为煤矿行业设计…

网页403错误(Spring Security报异常 Encoded password does not look like BCrypt)

这个错误通常表现为"403 Forbidden"或"HTTP Status 403"&#xff0c;它指的是访问资源被服务器理解但拒绝授权。换句话说&#xff0c;服务器可以理解你请求看到的页面&#xff0c;但它拒绝给你权限。 也就是说很可能测试给定的参数有问题&#xff0c;后端…

C++力扣题目 392--判断子序列 115--不同的子序列 583--两个字符串的删除操作 72--编辑操作

392.判断子序列 力扣题目链接(opens new window) 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相对位置形成的新字符串。&#xff08;例如&#xff0c;&quo…