热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

排序算法专题归并排序

归并排序是一种十分经典的冲破O(n2)时间复杂度的排序算法,该算法是基于分治的思想,讲解算法原理之前,先看一下下面这张图。图片来源&#x

  归并排序是一种十分经典的冲破O(n2)时间复杂度的排序算法,该算法是基于分治的思想,讲解算法原理之前,先看一下下面这张图。
在这里插入图片描述


  • 图片来源:【算法】排序算法之归并排序
      上图就是归并算法的一个简单示例。该算法就是每次将数组递归拆解为两部分,直到所有部分包含元素为1,之后递归的将各个部分进行归并。
  • 具体的算法步骤如下:
  • 1:递归拆解数组,直到每个区块包含元素数量为1
    2:归并数组,直到归并后的数组长度等于原数组长度
    3: 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
    4:设定两个指针,最初位置分别为两个已经排序序列的起始位置
    5:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
    5:重复步骤 4直到某一指针达到序列尾
    7:将另一序列剩下的所有元素直接复制到合并序列尾
    8:重复步骤2-7

  从上述可以看出,该算法的实现是基于递归思想,但是所有的递归都可以转换成迭代,因此该算法有两个实现方式,递归和迭代。


  • 代码如下,以递归为例:
  • 如果单从原理原理上来直接写代码会比较复杂,我们可以将该算法拆解为两个部分,及分割和归并。分割是一个简单的递归,代码如下:

def mergeSort(nums):"""将输入数组递归拆分&#xff0c;直到长度为1时返回&#xff0c;对每一步返回的left,right进行顺序归并>>>mergeSort(3,38, 5, 44, 15, 36)>>>[3, 5, 15, 36, 38, 44]"""if len(nums) < 2:return numsmid &#61; len(nums)//2left, right &#61; nums[:mid], nums[mid:]return mergeHelp(mergeSort(left), mergeSort(right))

  • 其中mergeHelp是mergeSort的一个help方法&#xff0c;用于对拆分后的数组进行顺序归并。
  • 以[3,38, 5, 44, 15, 36]举个栗子&#xff0c;说一下递归过程&#xff1a;
  • 1&#xff1a;[3, 38, 5] [44, 15, 36]
    2&#xff1a;[3] [38, 5]
    3&#xff1a;[38] [5]
    4&#xff1a;[44] [15, 36]
    5&#xff1a;[15] [36]

  • 接下来我们实现mergeHelp方法&#xff0c;就是给定两个有序数组&#xff0c;将其按顺序合并为一个数组&#xff0c;代码如下&#xff1a;

def mergeHelp(left, right):"""归并排序的help方法&#xff0c;用于将拆分的left和right进行顺序归并>>>mergeHelp([1, 3, 5], [2, 4, 5]):>>>[1, 2, 3, 4, 5, 5]"""res &#61; []while left and right:if left[0] <&#61; right[0]:res.append(left.pop(0))else:res.append(right.pop(0))while left:res.append(left.pop(0))while right:res.append(right.pop(0))return res

  • 当我们实现了这个方法之后&#xff0c;看一下分割&#43;归并的过程
  • [3, 38, 5] [44, 15, 36]  第一次分割
    左数组[3, 38, 5]部分&#xff1a;
    [3] [38, 5]  第一次分割
    [38] [5]  第二次分割&#xff08;左数组分割完毕&#xff0c;所有部分元素均为1&#xff09;
    [5, 38]  第一次归并
    [3, 5, 38]emsp; 第二次归并&#xff0c;完成[3, 38, 5]部分序列的排序
    右数组[44, 15, 36]部分&#xff1a;
    [44] [15, 36]  第一次分割
    [15] [36]  第二次分割
    [15, 36]  第一次合并
    [15, 36, 44]  第二次合并
    原数组的所有子序列完成排序&#xff0c;进行最终的合并
    [3, 5, 15, 36, 38, 44]  排序完成

  • 算法解析&#xff1a;算法的时间复杂度从两个部分分来来看&#xff0c;很明显在mergeSort()递归方法里面&#xff0c;迭代公式为mid &#61; len(nums)//2&#xff0c;该方法的时间复杂度是O(log n)&#xff0c;而在mergeHelp()归并方法里面&#xff0c;每一步像res里面追加一下元素&#xff0c;最终的的运行次数为len(left)&#43;len(right)&#xff0c;很明显时间复杂度为O(n)&#xff0c;因此归并排序算法的总时间复杂度为O(n log n)。由于算法运行过程中&#xff0c;会递归生成原数组的切片&#xff0c;切片总长度为n&#xff0c;所以归并排序算法的空间复杂度为O(n)。
  • 注意到我们在进行归并操作是&#xff0c;使用的是如下代码

while left and right:if left[0] <&#61; right[0]:res.append(left.pop(0))else:res.append(right.pop(0))

  • 也就是说对于同样大小的元素&#xff0c;我们先插入位于左边的&#xff0c;而后插入右边的&#xff0c;因此归并排序不会改变相同元素的相对位置&#xff0c;因此该算法是稳定的。

推荐阅读
  • 使用Matlab创建动态GIF动画
    动态GIF图可以有效增强数据表达的直观性和吸引力。本文将详细介绍如何利用Matlab软件生成动态GIF图,涵盖基本代码实现与高级应用技巧。 ... [详细]
  • H5技术实现经典游戏《贪吃蛇》
    本文将分享一个使用HTML5技术实现的经典小游戏——《贪吃蛇》。通过H5技术,我们将探讨如何构建这款游戏的两种主要玩法:积分闯关和无尽模式。 ... [详细]
  • 在2022年11月2日的AcWing每日编程挑战中,任务是计算一个长度为n的整数序列中的逆序对数量。逆序对是指在序列中,若存在两个下标i和j(i < j),且a[i] > a[j],则称这两个元素构成一个逆序对。本题要求实现一个算法来高效地统计这些逆序对的数量。 ... [详细]
  • 作文记录:合并区间的技巧与应用
    本文详细记录了合并区间问题的解题技巧与应用场景。首先介绍了问题背景和题目描述,接着从排序最大值的角度探讨了解决思路,并提供了具体的程序代码及运行结果。此外,还探讨了其他可能的解决方案。最后,对整个解题过程进行了总结,为读者提供了全面的理解和参考。 ... [详细]
  • 贡献转移在计算每个元素的作用的时候,我们可以通过反向枚举作用效果,添加到作用元素的身上,这种方法叫做贡献转移。更正式的说, ... [详细]
  • 本文回顾了作者在求职阿里和腾讯实习生过程中,从最初的迷茫到最后成功获得Offer的心路历程。文中不仅分享了个人的面试经历,还提供了宝贵的面试准备建议和技巧。 ... [详细]
  • 本文详细探讨了在Java中如何将图像对象转换为文件和字节数组(Byte[])的技术。虽然网络上存在大量相关资料,但实际操作时仍需注意细节。本文通过使用JMSL 4.0库中的图表对象作为示例,提供了一种实用的方法。 ... [详细]
  • 本题要求实现一个名为fun的函数,该函数的功能是从给定的字符串s中移除所有ASCII码为偶数值的字符,并将剩下的字符组成的新字符串存储在由t指向的数组中。 ... [详细]
  • 使用Vue指令实现下拉菜单效果
    使用Vue指令实现下拉菜单效果模仿重庆红岩历史革命博物馆官网的导航栏内容和效果,使用Vue实现。官网地址如下:https:www.hongyan.info官网效果效果图片展示代码展 ... [详细]
  • MySQL InnoDB 存储引擎索引机制详解
    本文深入探讨了MySQL InnoDB存储引擎中的索引技术,包括索引的基本概念、数据结构与算法、B+树的特性及其在数据库中的应用,以及索引优化策略。 ... [详细]
  • Go从入门到精通系列视频之go编程语言密码学哈希算法(二) ... [详细]
  • 张正友相机标定算法解析:无需棋盘格
    本文深入探讨了张正友教授于1998年提出的单平面标定技术,该方法结合了传统标定与自标定的优势,通过简易的棋盘格实现了高效准确的相机标定。 ... [详细]
  • Windows操作系统提供了Encrypting File System (EFS)作为内置的数据加密工具,特别适用于对NTFS分区上的文件和文件夹进行加密处理。本文将详细介绍如何使用EFS加密文件夹,以及加密过程中的注意事项。 ... [详细]
  • Laravel 开发技巧:如何为集合中的每个元素添加递增编号
    本文将介绍如何在 Laravel 集合中为每个数组元素添加递增的编号,帮助开发者更好地管理和操作数据。 ... [详细]
  • 双指针法在链表问题中应用广泛,能够高效解决多种经典问题,如合并两个有序链表、合并多个有序链表、查找倒数第k个节点等。本文将详细介绍这些应用场景及其解决方案。 ... [详细]
author-avatar
天若无雨666
这个菇凉很宅,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有