当前位置: 首页 > news >正文

【初识数据结构】CS61B 中的归并排序和选择排序

本教程介绍 归并排序和插入排序

归并排序

设想

首先我们设想一个情景,如果我们有两个已排序的数组,现在我们要把这两个数组进行合并成一个有序的大数组,应该需要多少的时间复杂度?
答案是O(N)O(N)O(N)!

alt text
我们每次取两数组中最小的那个进行比较,然后把较小者放入合并后的数组即可

分析

我们知道选择排序的时间复杂度为 O(N2)O(N^2)O(N2) ,我们现在以 N=64N=64N=64 的数组进行分析,如果我们直接对它进行选择排序,那我们消耗的时间为:642=409664^2=4096642=4096
那我们如果对他进行一次归并呢,也就是把他化为两个小数组,分别排序再合并
alt text
我们会发现,原本 N2N^2N2 的时间,变为了 N+2∗(N/2)2=N+N2/2N+2*(N/2)^2=N+N^2/2N+2(N/2)2=N+N2/2
虽然这看起来仍然是平方的时间复杂度,但是因为 N+N2/2<N2N+N^2/2<N^2N+N2/2<N2,所以我们的时间还是变快了

不断地归并

现在我们通过初步的分析知道,通过归并可以让时间变短,那如果我就这样贪婪地不断进行归并呢?
我们对原本的数组不断进行归并,直到无法再归并了,也就是基本情况,现在我们再来分析一下所需的时间是多少
alt text
我们会发现除了最后一层以外,上面的每一层都只需要进行线性操作即可,也就是对两个已经排序的数组进行合并
而最后一层呢?只有一个元素! 也就是不需要进行排序
所以其实我们只需要进行这些合并的线性操作即可

时间复杂度分析

接下来我们可以看到,第一层为 1∗N1*N1N,第二层为 2∗N/22 * N/22N/2 ,第三层为 4∗N/44*N/44N/4……,我们可以发现每一层的时间都是 NNN
那么一共有多少层呢,这实际上是一个完全二叉树,也就是 logNlogNlogN
所以我们可以得出时间复杂度为: θ(NlogN)\theta(NlogN)θ(NlogN)
空间复杂度为 θ(N)\theta(N)θ(N) ,因为我们需要一个额外的N数组,来储存合并后的结果

btw

归并排序是一种非常讲究组织的排序,他会将一个大数组不断地进行分割,再不断进行合并,可能它会具有比较好的并行性能

插入排序

插入排序其实很像我们在构造堆中的“上浮”和“下沉”操作,我们往下看

算法核心

alt text
我们以这个插入排序为例,对于未排序的首个元素,这个元素向左看,是否小于该元素:

  • 是,则交换
  • 否,则放置在这里,然后考虑下一个未排序的元素

算法流程

在这里,第一个元素为32,它左边没有可比较的元素,那他就放在这里
然后考虑15,和 32 比较,小于32?是的,进行交换;左边没有可以比较的,就放在这里
考虑2,小于32?是的,交换;小于15?是的,交换;左边没有元素,放在这里
考虑17,小于32?是的,交换;小于15?否,放在这,考虑下一个

类比

插入排序每次取出的元素不像选择排序那样,每次都需要取出最值元素,每次取出的元素没有限制,取出元素后,直接进入已排序的区域然后发生“下沉”,如果发现无法下沉了,这里就一定是他该待的位置了

时间复杂度分析

最好的情况是,我们每次取出一个元素,发现都无需发生“下沉”,也就是每个元素都已经在它该在的位置了,这里时间复杂度为 Ω(N)\Omega(N)Ω(N)
最坏的情况是,每次取出一个元素,都要下沉到底,尽可能地做交换,第一次是0,最后一次是 N-1,这里时间复杂度为 O(N2)O(N^2)O(N2)

优势

插入排序的优势在于,在我的整个数组已经大部分都已排序的情况下,它的表现比其他的算法更好
比如我的整个已排序的数组中有一个数据被篡改了,现在我要重新排序,插入排序的性能表现相较于归并排序或者插入排序就非常棒了

http://www.lryc.cn/news/598405.html

相关文章:

  • [网安工具] 自动化威胁检测工具 —— D 盾 · 使用手册
  • kubernetes集群中部署CoreDNS服务
  • OceanBase 4.3.5 解析:DDL性能诊断
  • 爆肝整理,性能测试详细汇总,从0到1打通(二)
  • 基于深度学习的胸部 X 光图像肺炎分类系统(三)
  • 在 OceanBase 中,使用 TO_CHAR 函数 直接转换日期格式,简洁高效的解决方案
  • 深入理解 eMMC RPMB 与 OP-TEE 在 Linux 系统中的应用开发
  • 使用宝塔面板搭建 PHP 环境开发一个简单的 PHP 例子
  • 解决VSCode无法加载Json架构问题
  • 《计算机网络》实验报告八 加密、数字签名与证书
  • 力扣844. 比较含退格的字符串
  • 借助Aspose.HTML控件,在 Python 中将 HTML 转换为 Markdown
  • 【bug解决】 esp32 在WSL-ubuntu20.04环境下找不到设备
  • MIT线性代数01_方程组的几何解释
  • 造成服务器内存不足的原因有什么
  • 飞腾D2000/E2000/D3000如何从头制作UBOOT引导系统镜像
  • Pycharm、Python安装及配置小白教程
  • 【docker | 部署 】Jetson Orin与AMD平台容器化部署概述
  • 用LangChain重构客服系统:腾讯云向量数据库+GPT-4o实战
  • 使用爬虫获取游戏的iframe地址
  • DRF - 博客列表API
  • Django Models详解:数据库模型的核心
  • Unity3D + VR头显 × RTSP|RTMP播放器:构建沉浸式远程诊疗系统的技术实践
  • Ascendc msOpST测试报错问题
  • 【Unity开发】数据存储——XML
  • MySQL的命令行客户端
  • Code Composer Studio:CCS 设置代码折叠
  • MySQL零基础教程增删改查实战
  • [语言模型训练]基于 PyTorch 的双向 LSTM 文本分类器实现:基于旅店的评论分类语言模型
  • 与deepseek的问答:dot net与Borland VCL的关系