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

【初识数据结构】CS61B中的基数排序

本教程介绍 CS61B 中的基数排序,这是一种可以在某些情况下甚至超越归并排序、快速排序的特殊的排序方法,但是牺牲了内存空间

计数排序

连续编号情形

我们需要对一个编号从 0 到 11 的表进行排序
alt text
实际上我们可以拿出另一张同样大小的空白表,在遍历左边表时,我们不需要进行比较,就可以直接将元素填到正确的位置上!

这样我们的时间复杂度来到了 θ(N)\theta(N)θ(N),避免了之前我们提到的 NlogNNlogNNlogN 界限
但这种情况你必须保证编号是连续的

花色分类情形

alt text
我们要考虑的问题是,我怎么知道第一个红桃应该放在哪里呢?
我们要做的是,扫描两次,第一次扫描来计数每个相同的元素有多少个(同时根据优先级,我们可以知道每个元素的索引是多少),第二次扫描根据第一次扫描的结果来进行放置。

alt text
经过第一次扫描后,我可以根据counts表,得出这样一个 Starting Points 的元素索引表,来记录下一个对应的元素应该放置在哪个索引处,每次放置之后,更新索引表中的对应元素

计数排序 vs 快速排序

考虑城市人口排名的情形,城市人口是不连续的,如果在这里我们使用计数排序的话,需要列一个非常非常大的计数表
alt text

计数排序

实际上我需要两个变量来表示计数排序,一个用于告诉我元素的数量在增加,第二个变量告诉我,字母表的大小在增加
在花色分类中,字母表大小为4,而在城市人口排名中,字母表的大小为3700万

这样问题可以以两种不同方式增长
如果我们有 k 个不同的种类,而字母表大小为 R,那么时间复杂度为 θ(N+R)\theta(N+R)θ(N+R) ,空间使用情况仍然为 θ(N+R)\theta(N+R)θ(N+R)
(时间复杂度中的 R 来源于我在第一次遍历数组之后,还需要遍历 R 数组将对应的索引填进去

基数排序

LSD

我们可以将每一个编号看作一个数字或者具有不同位数的元素
我们从最低有效位开始排序,然后逐步向最高有效位排序,同时每次排序保证是稳定的(也就是相同的数字,相对位置保持不变)
alt text
这样我们的时间复杂度为 θ(W(N+R))\theta(W(N+R))θ(W(N+R))
其中 N 表示元素的数量,R 表示字母表的大小,W 表示元素的宽度(位数)
相当于对每一位都进行一次计数排序

MSD

但是如果我的字符串非常长,那么 LSD 可能就会变得很慢,归并排序不会在较长的字符串上变慢,因为必须比较所有字符

我们可以从最高有效位开始比较
但是 MSD 会出现不稳定的情况
alt text
这样直接从最高位开始进行排序,会因为不稳定导致排序错误
为此,我们可以将其分解成子问题,比如一旦将所有以 a 开头的单词归类,下一步将是对这个子问题进行排序,而这些元素不会越界到 b 的范围
alt text

MSD 的时间复杂度有不同的情况

  • 最好情况:比较最高位即完成θ(N+R)\theta(N+R)θ(N+R)
  • 最坏情况:需要比较每一位,退化成 LSD ,θ(WN+WR)\theta(WN+WR)θ(WN+WR)

LSD vs Merge Sort

实际情况;

  • 我们认为字母表是常数,LSD 时间复杂度为 θ(WN)\theta(WN)θ(WN)
  • 归并排序在 θ(NlogN)\theta(NlogN)θ(NlogN)θ(WNlogN)\theta(WNlogN)θ(WNlogN) 之间

而具体来说哪一个更好呢?这取决于实际情况

  • LSD 更快
    • N非常非常大
    • 比较的字符串之间非常相似
    • alt text
  • 归并排序更快
    • 比较的字符串之间差异非常大
    • alt text
http://www.dtcms.com/a/304256.html

相关文章:

  • 彻底清理ArcGIS 10.2残留的步骤
  • 【自制组件库】从零到一实现属于自己的 Vue3 组件库!!!
  • 堆的理论知识
  • uniapp如何封装uni.request 全局使用
  • qt webengine播放视频
  • VS+Qt中使用QCustomPlot绘制曲线标签(附源码)
  • 002 TrafficGenerator 类详解
  • FCN语义分割算法原理与实战
  • 八股训练营 40 天心得:一场结束,也是一场新的开始
  • 力扣热题100--------240.搜索二维矩阵
  • LeetCode热题100——46. 全排列
  • 研电赛-基于GD32的纳型无人机AI追踪系统1
  • vue相关的拖拉拽官网
  • minio安装 windows系统
  • C语言第六章函数递归
  • Linux文件归档和备份
  • Qt 多线程网络编程实战
  • iOS 能耗·电池·电量监控实战指南:如何全面查看与优化 App 电能消耗
  • VTK开发笔记(一):VTK介绍,Qt5.9.3+VS2017x64+VTK8.2编译
  • AI驱动的浏览器自动化革命:Claude Code + BrowserCat MCP深度实践指南
  • 【MySQL学习|黑马笔记|Day2】SQL|DML、DGL、DCL,函数,约束
  • Python 打造 Excel 到 JSON 转换工具:从开发到打包全攻略
  • Java后端开发数据校验工作
  • Qt 嵌入式开发环境搭建
  • .NET测试平台Parasoft dotTEST在汽车电子行业的核心功能及应用
  • PCIE4.0/5.0/DDR4/DDR5使用以及布局布线规则-集萃
  • python cli命令 cli工具命令 自定义cli命名 开发 兼容 window、mac、linux,调用示例
  • ath12k_mac_op_tx到数据包发送的完整调用路径
  • Java把word转HTML格式
  • Hexo+Shoka 博客搭建保姆级教程