【十大排序算法】归并排序

归并排序,如同秋日落叶,分散而细碎,
然而风吹叶动,自然而有序,
彼此相遇,轻轻合拢,
最终成就,秩序之谧。

文章目录

  • 一、归并排序
  • 二、发展历史
  • 三、处理流程
  • 四、算法实现
  • 五、算法特性
  • 六、小结
  • 推荐阅读

一、归并排序

归并排序是一种基于分治思想的排序算法,它将一个待排序的数组分为两个子数组,然后对每个子数组递归地应用归并排序,直到子数组长度为 1。然后,将两个有序的子数组合并成一个有序的数组。这一过程重复进行,直到所有子数组合并成为一个有序的数组。

具体来说,归并排序的步骤如下:

  1. 分割: 将待排序数组分为两个子数组,通常是平均分割。
  2. 递归排序: 对两个子数组分别递归地应用归并排序,直到子数组长度为 1。
  3. 合并: 将两个有序的子数组合并成一个有序的数组。合并过程中,比较两个子数组的第一个元素,将较小(或较大)的元素添加到结果数组中,并将对应子数组的指针向后移动。
  4. 重复: 重复以上步骤,直到所有子数组合并成为一个有序的数组。

二、发展历史

归并排序是一种经典的排序算法,其发展历史可以追溯到 20 20 20 世纪 50 50 50 年代初期。

  1. 起源: 归并排序最早由约翰·冯·诺伊曼(John von Neumann)在 1945 1945 1945 年提出,并在他的著作《First Draft of a Report on the EDVAC》中描述了这一算法的基本原理。然而,彼时的计算机硬件水平并不足以支持归并排序的高效实现。
  2. 1960 年代: 归并排序在 1960 1960 1960 年代得到了更多的关注和研究。此时,归并排序成为了一种重要的外部排序算法,被应用于磁带排序和数据库系统等领域。在这一时期,归并排序的理论基础逐渐完善,并开始被广泛应用于实际系统中。
  3. 1980 年代: 随着计算机硬件的发展和算法研究的深入,归并排序得到了进一步的优化和改进。在 1980 1980 1980 年代,出现了一些新的归并排序的变种和优化算法,例如外部归并排序(External Merge Sort)和自然归并排序(Natural Merge Sort)等。
  4. 现代: 在当今计算机科学领域,归并排序仍然是一种非常重要和常用的排序算法。它的理论基础已经得到了深入研究和理解,并且在实际应用中得到了广泛的应用。虽然归并排序的时间复杂度较高,但其稳定性和可预测性使得它在某些场景下具有优势,特别是在外部排序和大规模数据处理等领域。

三、处理流程

场景假设:我们需要将下面的无序序列使用归并排序按从小到大进行排序。
workspace (1).png
归并排序的流程如下:

  1. 递归分割序列

workspace.png

  1. 递归合并序列并排序

workspace (2).png

四、算法实现

// 合并两个子数组
void merge(int[] array, int left, int mid, int right) {// 计算左右子数组的长度int leftLength = mid - left + 1;int rightLength = right - mid;// 创建临时数组存储左右子数组int[] leftArray = new int[leftLength];int[] rightArray = new int[rightLength];// 将数据拷贝到临时数组System.arraycopy(array, left, leftArray, 0, leftLength);System.arraycopy(array, mid + 1, rightArray, 0, rightLength);int i = 0, j = 0;int k = left;// 合并两个子数组while (i < leftLength && j < rightLength) {if (leftArray[i] <= rightArray[j]) {array[k++] = leftArray[i++];} else {array[k++] = rightArray[j++];}}// 处理剩余元素while (i < leftLength) {array[k++] = leftArray[i++];}while (j < rightLength) {array[k++] = rightArray[j++];}
}// 递归地进行归并排序
void mergeSort(int[] array, int left, int right) {if (left < right) {int mid = (left + right) / 2;// 递归地对左右子数组进行归并排序mergeSort(array, left, mid);mergeSort(array, mid + 1, right);// 合并左右子数组merge(array, left, mid, right);}
}public static void main(String args[]) {int[] array = {12, 11, 13, 5, 6, 7};System.out.println("原始数组:");for (int num : array) {System.out.print(num + " ");}System.out.println();// 调用归并排序算法mergeSort(array, 0, array.length - 1);System.out.println("\n排序后的数组:");for (int num : array) {System.out.print(num + " ");}
}

算法时间复杂度分析:

情况时间复杂度计算公式公式解释
最好情况 O ( n l o g n ) O(nlogn) O(nlogn) T ( n ) = 2 T ( n 2 ) + n T(n) = 2T(\frac{n}{2}) + n T(n)=2T(2n)+n归并排序在所有情况下都会将数组分成两半,然后递归地对它们进行排序,最后再将它们合并。这个过程的时间复杂度始终为 O ( n l o g n ) O(nlogn) O(nlogn)。其中, n n n 是数组的长度, l o g n logn logn 是因为每次都将数组分成两半。
平均情况 O ( n l o g n ) O(nlogn) O(nlogn) T ( n ) = 2 T ( n 2 ) + n T(n) = 2T(\frac{n}{2}) + n T(n)=2T(2n)+n同上
最坏情况 O ( n l o g n ) O(nlogn) O(nlogn) T ( n ) = 2 T ( n 2 ) + n T(n) = 2T(\frac{n}{2}) + n T(n)=2T(2n)+n同上

五、算法特性

归并排序是一种经典的排序算法,具有以下特性:

  1. 稳定性: 归并排序是一种稳定的排序算法,即相同元素的相对位置在排序前后不会改变。这意味着如果有相同元素存在,它们在排序后的顺序与排序前相同。
  2. 原地性: 归并排序通常不是一种原地排序算法,因为它需要额外的空间来存储临时数组。
  3. 适用性: 归并排序适用于各种数据类型和应用场景。由于其稳定性和时间复杂度的优势,归并排序被广泛应用于实际场景中,例如排序库、数据库索引等。
  4. 递归性: 归并排序是一种递归算法,它通过将数组分割成两个子数组,然后对每个子数组递归地应用归并排序来实现排序。这种递归性质使得归并排序的实现相对简单。

六、小结

归并排序是一种稳定、高效的排序算法,适用于各种数据类型和应用场景。其原理简单、实现直观,并且具有良好的性能表现,因此是排序算法中的重要一员。

推荐阅读

  1. Spring 三级缓存
  2. 深入了解 MyBatis 插件:定制化你的持久层框架
  3. Zookeeper 注册中心:单机部署
  4. 【JavaScript】探索 JavaScript 中的解构赋值
  5. 深入理解 JavaScript 中的 Promise、async 和 await

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

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

相关文章

树莓派4B_OpenCv学习笔记5:读取窗口鼠标状态坐标_TrackBar滑动条控件的使用

今日继续学习树莓派4B 4G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 版本是4.5.1&#xff1a; 今日学习:读取窗口鼠标状态坐标_TrackBar滑动条控件的使…

自然资源-《乡村振兴用地政策指南(2023年)》解读

自然资源-《乡村振兴用地政策指南&#xff08;2023年&#xff09;》解读 近期&#xff0c;自然资源部办公厅印发《乡村振兴用地政策指南&#xff08;2023年&#xff09;》&#xff08;以下简称《指南》&#xff09;。作为第一部针对乡村振兴用地政策的“工具包”&#xff0c;《…

Vue.js基础入门

Vue.js的基本概念和框架结构 Vue.js的基本概念 Vue实例 Vue实例是通过new Vue()创建的&#xff0c;它是Vue应用的核心。每个Vue应用都是由一个Vue实例开始的。示例代码&#xff1a; var app new Vue({el: #app,data: {message: Hello Vue!} });数据绑定 Vue.js提供了双向数据…

redis 05 复制 ,哨兵

01.redis的复制功能&#xff0c;使用命令slaveof 2. 2.1 2.2 3. 3.1 3.1.1 3.1.2 3.1.3 4 4.1 4.2 例子 5.1 这里是从客户端发出的指令 5.2 套接字就是socket 这里是和redis事件相关的知识 5.3 ping一下

idea编码问题:需要 <标识符> 非法的类型 、需要为 class、interface 或 enum 问题解决

目录 问题现象 问题解决 问题现象 今天在idea 使用中遇到的一个编码的问题就是&#xff0c;出现了这个&#xff1a; Error:(357, 28) java: /home/luya...........anageService.java:357: 需要 <标识符> Error:(357, 41) java: /home/luya............anageService.ja…

Cinema 4D 2024 软件安装教程、附安装包下载

Cinema 4D 2024 Cinema 4D&#xff08;C4D&#xff09;是一款由Maxon开发的三维建模、动画和渲染软件&#xff0c;广泛用于电影制作、广告、游戏开发、视觉效果等领域。Cinema 4D允许用户创建复杂的三维模型&#xff0c;包括角色、场景、物体等。它提供了多种建模工具&#x…

Channels无法使用ASGI问题

Django Channels是一个基于Django的扩展, 用于处理WebSockets, 长轮询和触发器事件等实时应用程序. 它允许Django处理异步请求, 并提供了与其他WebSockets库集成的功能.当我们在Django Channels中使用ASGI_APPLICATION设置时, 我们可以指定一个新的ASGI应用程序来处理ASGI请求.…

Day01 - Day05

Day01 - Day05 Day01&#xff08;1997年Text1&#xff09; After six months of arguing and final 16 hours of hot parliamentary debates, Australia’s Northern Territory became the first legal authority in the world to allow doctors to take the lives of incurab…

java非框架代码实现缓存并实现自动过期

要实现一个简单的Java缓存&#xff0c;可以使用ConcurrentHashMap和ScheduledExecutorService。以下是一个简单的示例&#xff1a; java import java.util.concurrent.*; public class SimpleCache<K, V> { private final ConcurrentHashMap<K, CacheItem<V>&g…

springboot中基于RestTemplate 类 实现调用第三方API接口,获取响应体内容不需要转换数据类型【丰富版】

RestTemplate 用法 和 http工具类 这篇就不说了 可以去看下面的博客 本篇文章是 针对 下面的博客 进行的扩展 https://blog.csdn.net/Drug_/article/details/137166797 我们在调用第三方 api接口 时候 在获取相应体的时候 不知道用什么数据类型 去接 响应体里的数据 用 字符串…

数据库期末设计——图书管理系统

目录 1.前置软件以及开发环境&#xff1a; 2.开发过程讲解 代码环节&#xff1a; 数据库代码 1.BookDao.java 2.BookTypeDao.java 3.UserDao.java 4.Book.java 5.BookType.java 6.User.java 7.DbUtil.java 8.Stringutil.java 9.BookAddInterFrm.java 10.BookMan…

前端学习----css基础语法

CSS概述 CAscading Style Sheets(级联样式表) CSS是一种样式语言,用于对HTML文档控制外观,自定义布局等,例如字体,颜色,边距等 可将页面的内容与表现形式分离,页面内容存放在HTML文档中,而用于定义表现形式的CSS在一个.css文件中或HTML文档的某一部分 HTML与CSS的关系 HTM…

freertos中的链表1 - 链表的数据结构

1.概述 freertos中链表的实现在 list.c 和 list.h。旨在通过学习freertos中的链表的数据结构&#xff0c;对freertos中的链表实现有一个整体的认识。freertos使用了三个数据结构来描述链表&#xff0c;分别是&#xff1a;List_t&#xff0c; MiniListItem_t&#xff0c;ListIt…

智能合约中时间依赖漏洞

时间依赖漏洞 时间依赖漏洞是智能合约中一个常见的安全问题&#xff0c;特别是在以太坊等区块链环境中。这是因为区块链的区块时间戳可以被矿工在一定程度上操纵&#xff0c;这使得依赖于时间戳的智能合约容易受到攻击。攻击者可以通过控制区块时间戳来触发合约中的某些条件&a…

B3637 最长上升子序列

最长上升子序列 题目描述 这是一个简单的动规板子题。 给出一个由 n ( n ≤ 5000 ) n(n\le 5000) n(n≤5000) 个不超过 1 0 6 10^6 106 的正整数组成的序列。请输出这个序列的最长上升子序列的长度。 最长上升子序列是指&#xff0c;从原序列中按顺序取出一些数字排在一起…

产品创新:驱动企业增长的核心动力

在当今快速变化的市场环境中&#xff0c;产品创新已成为企业生存和发展的关键。产品创新不仅涉及全新产品或服务的开发&#xff0c;也包括对现有产品或服务的持续改进和优化。本文将深入探讨产品创新的定义、重要性以及如何通过创新驱动企业增长&#xff0c;并结合实际案例进行…

Java核心: JarIndex的使用

在讲解Java类加载器的时候&#xff0c;我们发现URLClassLoader加载类或资源时通过访问ClassPath下的每一个路径&#xff0c;来确定类是否存在的&#xff0c;假设我们执行的命令是这样的 java -classpath D:\DiveInSpring\target\classes;C:\lib\spring-expression.jar;C:\lib\…

力扣第196题“删除重复的电子邮件

关注微信公众号 数据分析螺丝钉 免费领取价值万元的python/java/商业分析/数据结构与算法学习资料 在本篇文章中&#xff0c;我们将详细解读力扣第196题“删除重复的电子邮件”。通过学习本篇文章&#xff0c;读者将掌握如何使用SQL语句来解决这一问题&#xff0c;并了解相关的…

前端下载图片的几种方式

1.后端返回文件流&#xff0c;前端利用Blob解析文件流下载 2.下载资源必须是与页面地址同源时&#xff0c;直接利用a标签下载 注意点&#xff1a;下载资源必须与页面地址同源 3.利用fetch或者xhr从图片地址获取二进制数据&#xff08;blob&#xff09;进行下载 代码如下&am…

Robust Tiny Object Detection in Aerial Images amidst Label Noise

文章目录 AbstractIntroductionRelated WorkMethodsClass-aware Label CorrectionUpdateFilteringTrend-guided Learning StrategyTrend-guided Label ReweightingRecurrent Box RegenerationExperimentpaper Abstract 精确检测遥感图像中的小目标非常困难,因为这类目标视觉信…