归并排序详解(附代码)

归并排序

数据科学家每天都在处理算法。 然而,数据科学学科作为一个整体已经发展成为一个不涉及复杂算法实现的角色。 尽管如此,从业者仍然可以从建立对算法的理解和知识库中受益。

在本文中,对排序算法归并排序进行了介绍、解释、评估和实现。 这篇文章的目的是为您提供有关合并排序算法的可靠背景信息,这些信息可以作为更复杂算法的基础知识。

尽管归并排序被认为并不复杂,但了解该算法将帮助您认识到在选择最有效的算法来执行与数据相关的任务时应考虑哪些因素。 John Von Neumann 创建于 1945 年,他使用分而治之的方法开发了归并排序算法。

分而治之

要理解归并排序算法,您必须熟悉分而治之范式以及递归的编程概念。 计算机科学领域内的递归是指为解决问题而定义的方法涉及在其实现主体中调用自身。

换句话说,该函数重复调用自身。

分而治之算法(合并排序是一种)在其方法中使用递归来解决特定问题。 分而治之算法将复杂问题分解为更小的子部分,其中定义的解决方案递归地应用于每个子部分。 然后分别解决每个子部分,并重新组合解决方案以解决原始问题。

算法设计的分而治之方法结合了三个主要元素:

  • 将较大的问题分解为较小的子问题。 (划分)
  • 递归利用函数来解决每个较小的子问题。 (征服)
  • 最终解决方案是对较大问题的较小子问题的解决方案的组合。 (结合)

其他算法使用分而治之范式,例如快速排序、二分搜索和施特拉森算法。

归并排序

在按升序对列表中的元素进行排序的上下文中,合并排序方法将列表分成两半,然后遍历新的两半,不断将它们进一步细分为更小的部分。

随后,对较小的一半进行比较,并将结果组合在一起形成最终的排序列表。

步骤与实施

合并排序算法的实现是一个三步过程。 划分、征服和结合。

分而治之方法的划分部分是第一步。 此初始步骤将整个列表分成两个较小的部分。 然后,列表被进一步分解,直到它们不能再被分割,在每个减半的列表中只留下一个元素项。

归并排序第二阶段的递归循环关注的是列表的元素按特定顺序排序。 对于这种情况,初始数组按升序排序。

在下图中,您可以看到归并排序算法中涉及的除法、比较和组合步骤。

实现:

  • 创建一个名为 merge_sort 的函数,它接受一个整数列表作为其参数。 以下所有说明均在此功能内。
  • 首先将列表分成两半。 记录列表的初始长度。
  • 检查记录的长度是否等于 1。如果条件评估为真,则返回列表,因为这意味着列表中只有一个元素。 因此,不需要划分列表。
  • 获取元素个数大于1的列表的中点。使用Python语言时,//除法为无余数。 它将除法结果舍入到最接近的整数。 这也称为楼层划分。
  • 使用中点作为参考点,将列表分成两半。 这是分而治之算法范式的划分方面。
  • 在此步骤中利用递归来促进将列表划分为一半的组件。 变量“left_half”和“right_half”被分配给“merge_sort”函数的调用,接受初始列表的两半作为参数。
  • “merge_sort”函数返回对一个函数的调用,该函数合并两个列表以返回一个组合的、排序的列表。
def merge_sort(list: [int]):list_length = len(list)if list_length == 1:return listmid_point = list_length // 2left_half = merge_sort(list[:mid_point])right_half = merge_sort(list[mid_point:])return merge(left_half, right_half)
  • 创建一个“合并”函数,它接受两个整数列表作为其参数。 此函数包含分而治之算法范例的征服和组合方面。 以下所有步骤都在此函数体内执行。
  • 将一个空列表分配给保存排序整数的变量“output”。
  • 指针“i”和“j”分别用于索引左列表和右列表。
  • 在 while 循环中,比较左右列表的元素。 每次比较后,输出列表被填充到两个被比较的元素中。 附加元素列表的指针递增。
  • 要添加到排序列表的剩余元素是从当前指针值到相应列表末尾获得的元素。
def merge(left, right):output = []i = j = 0while (i < len(left) and j < len(right)):if left[i] < right[j]:output.append(left[i])i +=1else:output.append(right[j])j +=1output.extend(left[i:])output.extend(right[j:])return outputunsorted_list = [2, 4, 1, 5, 7, 2, 6, 1, 1, 6, 4, 10, 33, 5, 7, 23]
sorted_list = merge_sort(unsorted_list)
print(unsorted_list)
print(sorted_list)

性能和复杂性

大 O 表示法是根据算法的空间要求和执行时间来定义和组织算法性能的标准。

合并排序算法的时间复杂度在其最佳、最差和平均情况下是相同的。 对于大小为 n 的列表,归并排序算法完成的预期步数、最小步数和最大步数都是相同的。

正如本文前面所述,合并排序算法是一个三步过程:分治、合并。 “划分”步骤涉及列表中点的计算,无论列表大小如何,它都需要一个操作步骤。 因此,此操作的符号表示为 O(1)。

“解决”步骤涉及划分和递归求解子数组——符号 log n 表示这一点。 “组合”步骤包括将结果组合成最终列表; 此操作执行时间取决于列表大小并表示为 O(n)。

其平均、最佳和最差时间复杂度的合并排序表示法是 log n * n * O(1)。 在大 O 表示法中,低阶项和常量可以忽略不计,这意味着归并排序算法的最终表示法是 O(n log n)。 关于归并排序算法的详细分析,可以参考这篇文章。

评估

合并排序在对大型列表进行排序时表现良好,但在用于较小列表时,其运行时间比其他排序解决方案慢。 合并排序的另一个缺点是即使初始列表已经排序,它也会执行操作步骤。 在排序链表的用例中,归并排序是最快的排序算法之一。 合并排序可用于外部存储系统(如硬盘驱动器)内的文件排序。

要点

本文通过根据其组成操作和逐步过程对其进行分解来描述归并排序技术。

合并排序算法是常用的,与其他排序算法相比,该算法背后的直觉和实现相当简单。 本文包括归并排序算法在Python中的实现步骤。

您还应该知道,合并排序方法在不同情况下的执行时间的时间复杂度,在最佳、最差和平均情况下保持不变。 推荐在以下场景应用归并排序算法:

  • 处理较大的数据集时,使用归并排序算法。 与其他排序算法相比,合并排序在小型数组上的表现不佳。
  • 链表中的元素引用列表中的下一个元素。 这意味着在合并排序算法操作中,指针是可以修改的,使得元素的比较和插入具有恒定的时间和空间复杂度。
  • 以某种形式确定数组未排序。 归并排序甚至会在已排序的数组上执行其操作,这是一种计算资源的浪费。
  • 当考虑到数据的稳定性时,使用归并排序。 稳定排序涉及维护数组中相同值的顺序。 与未排序的数据输入相比,稳定排序中整个数组中相同值的顺序在排序后的输出中保持在相同的位置。

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

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

相关文章

vue3从精通到入门4:diff算法的实现

Vue 3 的 diff 算法相较于 Vue 2 有了一些改进和优化&#xff0c;主要是为了应对更复杂的组件结构和更高的性能需求。 以下是 Vue 3 diff 算法在处理列表更新时的大致步骤&#xff1a; 头头比较&#xff1a;首先&#xff0c;比较新旧列表的头节点&#xff08;即第一个节点&…

生活 - 解决提出问题的人

文章目录 解决提出问题的人好心态是正确的认知和持续的行动减少预测、增加行动和感知屏蔽力 - 去掉一切人和信息 解决提出问题的人 有段时间比较沮丧&#xff0c;甚至思考&#xff0c;到底一切有什么意义。 但一直躺着是一定不会产生价值的&#xff0c;报了个团出门旅行&…

C++实现通过ICMP实现ping, 计算网络抖动,时延与丢包率

文章目录 目的关于ICMPsocket 编程实现ICMP编译error代码参考博客扩展了解目的 通过C++编程实现ping, 也算是对于SOCKET编程初步了解掌握。 了解ICMP协议了解对应socket编程关于ICMP 请参考我的博客Ping工作原理 socket 编程实现ICMP Ping 使用 Internet 控制消息协议(IC…

《Stable Diffusion AI绘画宝典:从入门到精通,解锁创意新境界》

前沿 在数字化浪潮席卷全球的时代&#xff0c;人工智能以其惊人的创造力和创新性引领着科技新风尚。党的二十大报告明确提出了“实施科教兴国战略&#xff0c;强化现代化建设人才支撑”的宏伟蓝图&#xff0c;展现了我国在新动能、新优势方面的坚定决心和强大气魄。在这个大背…

【Linux】进程的优先级环境变量

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1. 前言2. 进程的优先级2.1 什么是优先级2.2 为什么要有优先级2.3 优先级的查看方式2.4 对优先级调整 3. 命令行参数4. 环境变量4.1 环境变量与配置文件4.1.1 环境变量初步介绍4.1.2 配置文件 4.2 更多环境变量4.3 整…

Postgresql源码(125)游标恢复执行的原理分析

问题 为什么每次fetch游标能从上一次的位置继续&#xff1f;后面用一个简单用例分析原理。 【速查】 恢复扫描需要知道当前页面、上一次扫描到的偏移位置、当前页面一共有几条&#xff1a; 当前页面&#xff1a;HeapScanDesc结构中记录了扫到的页面&#xff08;scan->rs_cb…

Apache Paimon 流式湖仓介绍说明

文章目录 前言选择 Paimon 的原因Apache Paimon 功能一致性保证Paimon 表类型数据湖写入标签和时间线回溯捕获变更数据写入数据湖LSM 和分层文件重用流处理案例使用 Paimon 作为消息队列 前言 Apache Flink 自诞生以来经历了重大演变&#xff0c;如今&#xff0c;它不仅充当批…

毕设选51还是stm32?51太简单?

如果你更倾向于挑战和深入学习&#xff0c;STM32可能是更好的选择。如果你希望更专注于底层硬件原理&#xff0c;51可能更适合。我这里有一套嵌入式入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习嵌入式&#xff0c;不妨点个关注&#xff…

正则表达式中 “$” 并不是表示 “字符串结束

作者&#xff1a;Seth Larson 译者&#xff1a;豌豆花下猫Python猫 英文&#xff1a;Regex character “$” doesnt mean “end-of-string” 转载请保留作者及译者信息&#xff01; 这篇文章写一写我最近在用 Python 的正则表达式模块&#xff08;re&#xff09;开发 CPyth…

c++ 面向对象之 Lambda 表达式

一、简介 Lambda 表达式是 c11 中语法之一&#xff08;所以不要在 dev c 没添加 -stdc11/-stdc14 时使用了&#xff0c;等待你的是报错&#xff09;。Lambda 表达式把函数看作对象&#xff0c;把这个表达式当做对象使用。 二、使用 Lambda 表达式难以声明类型&#xff0c;故使…

阿里云迁移到AWS云,九河云保姆级教程

随着云计算技术的不断发展,越来越多的企业开始将传统的IT基础设施迁移到云平台上,以获得更高的灵活性、可扩展性和成本效益。在众多云服务提供商中,阿里云和AWS都是备受青睐的选择。本文将探讨如何将阿里云上的资源顺利迁移到AWS云平台,并针对性地进行优化。我们九河云&#xf…

[图解]DDD领域驱动设计伪创新-聚合根06

0 00:00:00,740 --> 00:00:02,200 那刚才讲了 1 00:00:02,480 --> 00:00:04,211 Evans这个隐喻 2 00:00:04,211 --> 00:00:06,520 实际上背后是把集合 3 00:00:06,800 --> 00:00:08,560 当成了聚合 4 00:00:10,580 --> 00:00:14,350 那为什么有这样的一个隐…

OpenHarmony实战开发-如何使用AKI轻松实现跨语言调用。

介绍 针对JS与C/C跨语言访问场景&#xff0c;NAPI使用比较繁琐。而AKI提供了极简语法糖使用方式&#xff0c;一行代码完成JS与C/C的无障碍跨语言互调&#xff0c;使用方便。本示例将介绍使用AKI编写C跨线程调用JS函数场景。通过调用C全局函数&#xff0c;创建子线程来调用JS函…

阿尔法编程使用

使用登录 平台地址&#xff1a;https://nuc.alphacoding.cn/&#xff08;建议使用最新的chrome、firefox、safari、edge打开&#xff0c;不要从微信直接打开&#xff09; 教师体验账号&#xff1a;teacher01-teacher10&#xff0c;一共10个账号&#xff0c;密码是123456&#…

GIS 数据格式转换

1、在线工具 mapshaper 2、数据上传 3、数据格式转换 导入数据可导出为多种格式&#xff1a;Shapefile、Json、GeoJson、CSV、TopJSON、KML、SVG

APP广告变现项目

APP广告变现项目 很多人觉得不可能&#xff0c;这是肯定存在的&#xff0c;不是现在才有的一个项目&#xff0c;这个项目的原理是怎么样呢&#xff0c;就是通过某些特定的app&#xff0c;然后看完广告就有收益&#xff0c;基本单次的观看单价都是在几毛到1块之间。 养机养好的…

java面试题(7)|Java 中的 Set 集合是如何保证添加元素不重复的?

文章目录 HashSetTreeSetLinkedHashSet 在 Java 中&#xff0c;Set 集合通过其实现类来确保不包含重复元素。常见的实现类有 HashSet、TreeSet 和 LinkedHashSet。 HashSet HashSet 使用 HashMap 来存储元素&#xff0c;其中元素作为键&#xff0c;而值则是一个常量。当你尝试…

ES6 import / export / export default type=module

1.export可以导出多个变量&#xff0c;函数&#xff0c;变量&#xff0c;函数需要一个一个导出&#xff0c;也可以以对象的方式导出{}; 2.import的时候&#xff0c;也需要加{}&#xff0c;且变量名&#xff0c;函数名需要和导出的一样。 3.export default 只能导出一个对象&…

阿里云服务器带宽多少钱?公网带宽收费标准全解析

阿里云服务器的公网带宽计费模式分为“按固定带宽”和“按使用流量”&#xff0c;有什么区别&#xff1f;按固定带宽是指直接购买多少M带宽&#xff0c;比如1M、5M、10M、100M等&#xff0c;阿里云直接分配用户所购买的带宽值&#xff0c;根据带宽大小先付费再使用&#xff1b;…

ADC通道检测功能-单片机通用模板

ADC通道检测功能-单片机通用模板 使用ADC外设的流程&#xff1a; 先初始化ADC外设的时钟&#xff1b;选择ADC的参考电压以及需要采集的通道&#xff1b;ADSOC1 开始转换&#xff0c;死循环等待转换完成ADSOC0&#xff1b;从ADCDH、ADCDL数据寄存器取出ADC转换数值&#xff1b;…