【数据结构与算法】十大经典排序算法-归并排序
🌟个人博客:www.hellocode.top
🏰Java知识导航:Java-Navigate
🔥CSDN:HelloCode.
🌞知乎:HelloCode
🌴掘金:HelloCode
⚡如有问题,欢迎指正,一起学习~~
当谈到高效的排序算法时,归并排序是一个备受推崇的选择。归并排序是一种分治算法,它将一个大问题分解成若干个小问题,然后逐个解决这些小问题,并将它们合并成一个整体的解。
基本思想

这里采用五分钟学算法大佬的图解,十分清晰
- 分解阶段: 将待排序数组分成两个相等或近似相等的子数组,不断将问题规模缩小。
- 解决阶段: 递归地对两个子数组进行排序,直到子数组的长度为1(即已有序)。
- 合并阶段: 将排好序的子数组合并成一个有序的数组,这是归并排序的核心操作。
三个阶段,涉及到递归就比较难理解(个人感觉),最好配合动画好好理解理解。主要就是分解和归并(将大问题分解为小问题,再通过归并过程合并并排序)
代码实现
每次随便写数组挺麻烦的,后续就都使用我写的工具类来生成随机数组了~
归并排序相对难理解一些,主要涉及到分解和归并,将待排序数组一个个拆分,直到拆分为1个1组(无需排序),接下来就是自底向上逐个合并,在合并的同时进行排序操作,最终合并好的就是有序的数组了
/*** @author HelloCode* @blog https://www.hellocode.top* @date 2023年08月15日 19:33*/
public class MergeSort {public static void main(String[] args) {// 生成容量为15的由100以内随机数构成的int数组(用到了自己写的一个工具类)int[] arr = ArrayUtil.randomIntArray(15, 100);System.out.println("原数组:" + Arrays.toString(arr));mergeSort(arr);System.out.println("排序后:" + Arrays.toString(arr));}private static void mergeSort(int[] arr) {if (arr == null || arr.length <= 1) {return; // 数组为空或只有一个元素,无需排序}// 创建临时数组(避免多次创建)int[] temp = new int[arr.length];// 递归入口sort(arr, temp, 0, arr.length - 1);}// 拆分private static void sort(int[] arr, int[] temp, int left, int right) {// 递归出口if (left >= right) {return;}// 记录中间值(左边数组的末尾,+1为右边数组的起始)int mid = left + ((right - left) >> 1);// 开始拆分sort(arr, temp, left, mid);sort(arr, temp, mid + 1, right);// 归并merge(arr, temp, left, mid, right);}// 归并(排序)private static void merge(int[] arr, int[] temp, int left, int mid, int right) {// 记录临时数组索引int p = left;// 左半边起始索引int i = left;// 右半边起始索引int j = mid + 1;// 开始归并// 两边都还有的情况while(i <= mid && j <= right){if(arr[i] <= arr[j]){temp[p++] = arr[i++];}else{temp[p++] = arr[j++];}}// 左边还有剩余的情况(直接加到临时数组末尾)while(i <= mid){temp[p++] = arr[i++];}// 右边还有剩余的情况(直接加到临时数组末尾)while(j <= right){temp[p++] = arr[j++];}// 将临时数组拷贝回原数组for(int k = left; k <= right; k++){arr[k] = temp[k];}}
}
测试:
原数组:[83, 49, 19, 75, 26, 64, 59, 60, 11, 97, 36, 41, 17, 31, 69]
排序后:[11, 17, 19, 26, 31, 36, 41, 49, 59, 60, 64, 69, 75, 83, 97]
生成随机数组的工具类:
/*** @author HelloCode* @blog https://www.hellocode.top* @date 2023年08月13日 20:01*/
public class ArrayUtil {private static final Random RANDOM = new Random();public static int[] randomIntArray(int capacity,int max){// 创建capacity大小的数组(1~max)int[] res = new int[capacity];for(int i = 0; i < capacity; i++){res[i] = RANDOM.nextInt(max) + 1;}return res;}
}
优化
归并排序本身是一个稳定且效率较高的排序算法,但还是有一些优化方法可以进一步提升性能:
- 插入排序优化: 对于小规模子数组,使用插入排序可以提高性能。当子数组长度小于一定阈值时,切换到插入排序可以减少递归调用开销。
- 自底向上归并: 在归并阶段,可以使用自底向上的方法,避免递归调用,从而减少栈空间的使用。
- 优化合并操作: 在合并阶段,如果左子数组的最大元素小于右子数组的最小元素,可以直接跳过合并操作,因为两个子数组已经有序。
总结
优点
- 归并排序稳定且适用于各种数据类型。
- 具有稳定的时间复杂度O(n log n),适用于大规模数据排序。
- 分治思想使其易于理解和实现,同时也为优化提供了空间。
缺点
- 归并排序需要额外的存储空间来存储临时数组,空间复杂度较高。
- 在小规模数据排序时,性能稍逊于快速排序。
复杂度
- 时间复杂度:平均情况、最好情况和最坏情况下的时间复杂度均为O(n log n)。
- 空间复杂度:空间复杂度为O(n),需要额外的存储空间来存储临时数组。
使用场景
- 归并排序适用于需要稳定排序的场景,对性能有一定要求。
- 特别适合用于外部排序,如在磁盘上对大文件进行排序。
通过分治思想,归并排序将排序问题分解为小问题,并通过合并操作将它们逐步解决,从而实现高效且稳定的排序。这使得归并排序成为计算机科学中重要的算法之一。
相关文章:
【数据结构与算法】十大经典排序算法-归并排序
🌟个人博客:www.hellocode.top 🏰Java知识导航:Java-Navigate 🔥CSDN:HelloCode. 🌞知乎:HelloCode 🌴掘金:HelloCode ⚡如有问题,欢迎指正&#…...
基于深度学习创建-表情符号--附源码
表情符号深度学习概述 如今,我们使用多种表情符号或头像来表达我们的心情或感受。它们充当人类的非语言线索。它们成为情感识别、在线聊天、品牌情感、产品评论等的关键部分。针对表情符号驱动的故事讲述的数据科学研究不断增加。 从图像中检测人类情绪非常流行,这可能是由…...
.netcore grpc的proto文件字段详解
一、.proto文件字段概述 grpc的接口传输参数都是根据.proto文件约定的字段格式进行传输的grpc提供了多种类型字段;主要包括标量值类型(基础类型)、日期时间、可为null类型、字节、列表、字典、Any类型(任意类型)、One…...
带你了解建堆的时间复杂度
目录 用向上调整建堆的时间复杂度 1.向上调整建堆的时间复杂度O(N*logN) 2.数学论证 3.相关代码 用向下调整建堆的时间复杂度 1.建堆的时间复杂度为O(N) 2.数学论证 3.相关代码 完结撒花✿✿ヽ(▽)ノ✿✿ 博主建议:面试的时候可能会被面试官问到建堆时间复杂度的证明过…...
人工智能原理(6)
目录 一、机器学习概述 1、学习和机器学习 2、学习系统 3、机器学习发展简史 4、机器学习分类 二、归纳学习 1、归纳学习的基本概念 2、变型空间学习 3、归纳偏置 三、决策树 1、决策树组成 2、决策树的构造算法CLS 3、ID3 4、决策树的偏置 四、基于实例的学习…...
单片机模块化编程文件创建流程
一、在工程文件夹下创建一个新的文件夹,命名为“ModulesCodesFiles”,译为“模块化代码文件”,用于存放所有模块化代码文件。 二、在“ModulesCodesFiles”文件夹下为每个模块创建一个新的文件夹,命名为模块的名称,例…...
docker image
docker image 1. 由来 docker image是Docker容器管理工具中的一个命令,用于管理和操作Docker镜像。 2. 常见五种示例命令和说明 以下是docker image的常见示例命令及其说明: 示例一:列出所有镜像 docker image ls描述:使用d…...
力扣75——单调栈
总结leetcode75中的单调栈算法题解题思路。 上一篇:力扣75——区间集合 力扣75——单调栈 1 每日温度2 股票价格跨度1 - 2 解题总结 1 每日温度 题目: 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer &…...
Webpack和Parcel详解
构建工具和打包器是在开发过程中帮助组织、优化和打包项目的工具。它们可以处理依赖管理、资源优化、代码转换等任务,从而使开发流程更高效。以下是关于构建工具和打包器的一些指导: **Webpack:** Webpack 是一个功能强大的模块打包器&#…...
linux系统服务学习(六)FTP服务学习
文章目录 FTP、NFS、SAMBA系统服务一、FTP服务概述1、FTP服务介绍2、FTP服务的客户端工具3、FTP的两种运行模式(了解)☆ 主动模式☆ 被动模式 4、搭建FTP服务(重要)5、FTP的配置文件详解(重要) 二、FTP任务…...
7.原 型
7.1原型 【例如】 另外- this指向: 构造函数和原型对象中的this都指向实例化的对象 7.2 constructor属性 每个原型对象里面都有个constructor属性( constructor构造函数) 作用:该属性指向该原型对象的构造函数 使用场景: 如果有多个对象的方法&#…...
【图像分类】理论篇(2)经典卷积神经网络 Lenet~Resenet
目录 1、卷积运算 2、经典卷积神经网络 2.1 Lenet 网络构架 代码实现 2.2 Alexnet 网络构架 代码实现 2.3 VGG VGG16网络构架 代码实现 2.4 ResNet ResNet50网络构架 代码实现 1、卷积运算 在二维卷积运算中,卷积窗口从输入张量的左上角开始ÿ…...
C++系列-内存模型
内存模型 内存模型四个区代码区全局区栈区堆区内存开辟和释放在堆区开辟数组 内存模型四个区 不同区域存放的数据生命周期是不同的,更为灵活。 代码区:存放函数体的二进制代码,操作系统管理。全局区:存放全局变量,常…...
[管理与领导-30]:IT基层管理者 - 人的管理 - 向上管理,管理好你的上司,职业发展事半功倍。什么样的上司不值得跟随?
目录 前言: 一、什么是向上管理 二、为什么要向上管理 三、如何进行向上管理 四、向上管理的注意事项 五、向上管理的忌讳 六、向上管理常犯的错 七、如何帮助上司解决他关心的问题 7.1 如何帮助上司解决他关心的问题 7.2 如何帮助上司降低压力 八、什么…...
Java进阶篇--迭代器模式
目录 同步迭代器(Synchronous Iterator): Iterator 接口 常用方法: 注意: 扩展小知识: 异步迭代器(Asynchronous Iterator): 常用的方法 注意: 总结:…...
【CAM】CAM(Class Activation Mapping)——可视化CNN的特征定位
文章目录 一、CAM(Class Activation Mapping)二、CAM技术实现2.1 网络修改2.2 微调2.2 特征提取 三、总结Reference 完整代码见Github :https://github.com/capsule2077/CAM-Visualization ,如果有用可以点个Star,谢谢! 一、CAM(C…...
Maven教程_编程入门自学教程_菜鸟教程-免费教程分享
教程简介 Maven 是一款基于 Java 平台的项目管理和整合工具,它将项目的开发和管理过程抽象成一个项目对象模型(POM)。开发人员只需要做一些简单的配置,Maven 就可以自动完成项目的编译、测试、打包、发布以及部署等工作。Maven 是…...
Gof23设计模式之模板方法模式
1.定义 定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。 2.结构 模板方法(Template Method)模式包含以下主要角色: 抽象类࿰…...
springBoot 配置文件 spring.resources.add-mappings 参数的作用
在Spring Boot应用中,spring.resources.add-mappings参数用于控制是否将特定路径的资源文件添加到URL路径映射中。 默认情况下,该参数的值为true,即会自动将静态资源(例如CSS、JavaScript、图片等)的URL路径添加到Spr…...
《Java极简设计模式》第03章:工厂方法模式(FactoryMethod)
作者:冰河 星球:http://m6z.cn/6aeFbs 博客:https://binghe.gitcode.host 文章汇总:https://binghe.gitcode.host/md/all/all.html 源码地址:https://github.com/binghe001/java-simple-design-patterns/tree/master/j…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
