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

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

文章目录

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

一、归并排序

归并排序是一种基于分治思想的排序算法,它将一个待排序的数组分为两个子数组,然后对每个子数组递归地应用归并排序,直到子数组长度为 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滑动条控件的使…

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请求.…

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

目录 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…

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

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

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

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

Java核心: JarIndex的使用

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

Robust Tiny Object Detection in Aerial Images amidst Label Noise

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

Facebook开户|Facebook广告设计与测试优化

早上好家人们~今天Zoey给大家伙带来的是Facebook广告设计与测试优化&#xff0c;需要的家人们看过来啦&#xff01; 一、避免复杂用图和过多的文字 根据Facebook的数据显示&#xff0c;用户平均浏览一个贴文的时间在手机上仅花1.7秒、在电脑上则为2.5秒。因此&#xff0c;广告…

【Linux】进程7——进程地址空间

1.再谈fork 之前提到了fork之后对父子进程返回不同的id值&#xff0c;给父进程返回子进程的pid&#xff0c;给子进程返回0&#xff0c;所以对于一个id如何存储两个值的说法&#xff0c;在我们之前已经提到过了一个概念叫做写时拷贝&#xff0c;就是在子进程要想修改父进程的id…

首途第三十三套清新简约卡片风格蓝紫渐变色短视频模板 | 苹果CMSV10主题

首途第三十三套清新简约卡片风格蓝紫渐变色短视频模板 | 苹果CMSV10主题 我们的简约风格&#xff0c;以纯洁的白色和深邃的紫色为主色调&#xff0c;为您提供了一种清新、时尚的浏览体验。在这个简洁而美丽的界面中&#xff0c;您可以轻松畅享各种精彩短视频。我们专注于简单的…

C++命名空间的定义、C++命名空间的使用、C++输入输出等的介绍

文章目录 前言一、C命名空间的定义1. C命名空间产生的原因2. 作用域限定符3. C变量的访问顺序 二、C命名空间的使用1. 加命名空间名称及作用域限定符2. 使用using将命名空间中某个成员引入3. 使用using namespace 命名空间名称 引入4. 嵌套命名空间使用 三、 C输入&输出总结…

向AI请教如何说不

面对父母的催婚&#xff0c;你可以采取以下几个步骤来进行沟通和表达自己的立场&#xff1a; 理解与尊重&#xff1a;首先&#xff0c;要理解父母催婚背后的关心和期望。他们可能出于对你未来幸福和生活稳定的考虑。表达对他们关心的感激&#xff0c;这有助于建立良好的沟通基础…

超详解——python条件和循环——小白篇

目录 1. 缩进和悬挂else 2. 条件表达式 3. 和循环搭配的else 4. 可调用对象 总结&#xff1a; 1. 缩进和悬挂else 在Python中&#xff0c;代码块是通过缩进来表示的。条件判断和循环结构的代码块需要正确缩进。悬挂else指的是else子句和相应的if或循环在同一级别的缩进。 …

⌈ 传知代码 ⌋ 基于曲率的图重新布线

&#x1f49b;前情提要&#x1f49b; 本文是传知代码平台中的相关前沿知识与技术的分享~ 接下来我们即将进入一个全新的空间&#xff0c;对技术有一个全新的视角~ 本文所涉及所有资源均在传知代码平台可获取 以下的内容一定会让你对AI 赋能时代有一个颠覆性的认识哦&#x…

扩散模型Stable Diffusion

扩散模型构成 Text Encoder(CLIPText) Clip Text为文本编码器。以77 token为输入&#xff0c;输出为77 token 嵌入向量&#xff0c;每个向量有768维度。 Diffusion(UNetScheduler) 在潜在空间中逐步处理扩散信息。以文本嵌入向量和由噪声组成的起始多维数组为输入&#xff0c…

1909java内部知识管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java内部知识管理系统是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助采用了java设计&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统采用web模式&#xff0c;系统主要采用B/S模式开发。开 发环境为TOMCAT7.0,Myeclipse8.5开发&…

热题系列章节5

169. 多数元素 给定一个大小为 n 的数组&#xff0c;找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的&#xff0c;并且给定的数组总是存在多数元素。 示例 1: 输入: [3,2,3] 输出: 3 示例 2: 输入: [2,2,1,1,1,2,2] 输出:…