news 2026/5/22 21:41:10

排序算法实战篇(二):4大进阶排序原理+Python代码+运行过程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
排序算法实战篇(二):4大进阶排序原理+Python代码+运行过程

上次分享了6种基础排序算法后,不少同学催更进阶款——毕竟面试和作业里,基数排序、快速排序、随机快速排序、堆排序这些“高效选手”才是常客。作为被数据结构折磨过的大学生,我把这4种进阶排序的原理、代码和运行过程扒得明明白白,这篇一次性讲透!

基数排序

定义与基本思想

  • 非比较型整数排序算法
  • 按照低位先排序,再收集;再按照高位排序,再收集;依次类推直到最高位

算法步骤

  • 取得数组中的最大数确定位数
  • 从最低位开始,使用稳定的排序算法(如计数排序)对每一位进行排序
  • 重复过程直到最高位完成排序

时间复杂度分析

  • 时间复杂度:O(d*(n+k)),其中d为最大位数,k为基数范围
  • 空间复杂度:O(n+k)

适用场景与优缺点

  • 适用于整数或字符串排序
  • 优点:线性时间复杂度,稳定排序
  • 缺点:对非整数数据不适用,空间开销较大

快速排序

定义与基本思想

  • 分治策略的排序算法
  • 通过选取基准元素将数组分为两部分,递归排序子数组

算法步骤

  • 选择基准元素(通常为第一个或最后一个元素)
  • 分区操作:将小于基准的元素移到左侧,大于基准的元素移到右侧
  • 递归排序左右子数组

时间复杂度分析

  • 平均时间复杂度:O(n log n)
  • 最坏时间复杂度:O(n²)(当数组已有序时)
  • 空间复杂度:O(log n)(递归栈空间)

适用场景与优缺点

  • 适用于大规模数据排序
  • 优点:平均性能优秀,原地排序
  • 缺点:最坏情况下性能较差,不稳定排序

随机快速排序

定义与基本思想

  • 快速排序的优化版本,通过随机化选择基准元素避免最坏情况

算法步骤

  • 随机选择基准元素
  • 分区操作与快速排序相同
  • 递归排序左右子数组

时间复杂度分析

  • 平均时间复杂度:O(n log n)
  • 最坏时间复杂度概率极低
  • 空间复杂度:O(log n)

适用场景与优缺点

  • 适用于需要避免最坏情况的场景
  • 优点:性能稳定,避免极端情况
  • 缺点:随机化增加额外开销

堆排序

定义与基本思想

  • 基于二叉堆的排序算法
  • 通过构建最大堆或最小堆实现排序

算法步骤

  • 构建最大堆(或最小堆)
  • 将堆顶元素与末尾元素交换,调整剩余元素为新堆
  • 重复过程直到堆为空

时间复杂度分析

  • 时间复杂度:O(n log n)(建堆和调整堆)
  • 空间复杂度:O(1)(原地排序)

适用场景与优缺点

  • 适用于需要原地排序的场景
  • 优点:时间复杂度稳定,不需要额外空间
  • 缺点:不稳定排序,缓存不友好

对比与总结

性能对比

  • 基数排序:线性时间但限制较多
  • 快速排序:平均性能最优但最坏情况差
  • 随机快速排序:避免最坏情况
  • 堆排序:稳定但缓存效率低

选择建议

  • 整数排序:基数排序
  • 通用排序:快速排序或随机快速排序
  • 内存受限:堆排序

应用场景举例

  • 基数排序:电话号码排序
  • 快速排序:大规模数据排序
  • 堆排序:优先级队列实现

一、基数排序:“按位拆分,逐位排序”

核心思路(大学生白话版)

像整理学号:先按个位把数字分到0-9号桶里,排好序;再按十位重新分桶排序;直到最高位处理完,整个数组就有序了。本质是“按位拆分+桶排序”的组合,专克多位数排序。

代码与运行过程

def RadixSort(a): base = 1 # 初始按个位排序(base=1) maxv = max(a) while base < maxv: bucket = [] # 初始化0-9共10个桶 for idx in range(10): bucket.append([]) # 按当前位(base)的值分桶 for num in a: idx = (num // base) % 10 # 取当前位的数字 bucket[idx].append(num) # 把桶里的元素按顺序放回原数组 l = 0 for idx in range(10): for v in bucket[idx]: a[l] = v l += 1 print(a) # 打印每轮排序结果 base *= 10 # 切换到更高位(个位→十位→百位...) a = [3121,897,3122,3,23,5,55,7,97,123,345,1423] RadixSort(a)

每轮按一位排序,逐步让数组整体有序:

[3121, 3122, 3, 23, 123, 1423, 5, 55, 345, 897, 7, 97] # 按个位排序 [3, 5, 7, 3121, 3122, 23, 123, 1423, 345, 55, 897, 97] # 按十位排序 [3, 5, 7, 23, 55, 97, 3121, 3122, 123, 345, 1423, 897] # 按百位排序 [3, 5, 7, 23, 55, 97, 123, 345, 897, 1423, 3121, 3122] # 按千位排序(最终有序)

特点

  • 时间复杂度:$O(d \times (n + k))$($d$是最高位数,$k=10$)

  • 空间复杂度:$O(n + k)$(需要10个桶)

  • 稳定排序

  • 适合多位数整数排序(如学号、手机号)

二、快速排序:“选基准,分左右,递归排序”

核心思路(大学生白话版)

像分水果:选一个“基准”(比如苹果),把比它小的放左边,比它大的放右边;再对左右两堆分别选基准、重复分堆,直到每堆只有一个水果——这就是“分治”思想的经典应用。

代码与运行过程

def QuickSortPivot(a, start, end): pivot = start # 选第一个元素做基准 j = start + 1 # 把比基准小的元素移到左边 for i in range(start+1, end+1): if a[i] < a[pivot]: a[j], a[i] = a[i], a[j] j += 1 # 把基准放到左右区间的中间 a[pivot], a[j-1] = a[j-1], a[pivot] pivot = j - 1 print(a[pivot], a[start:pivot], a[pivot+1:end+1]) # 打印基准和左右区间 return pivot def QuickSort(a, start, end): if start >= end: return pivot = QuickSortPivot(a, start, end) QuickSort(a, start, pivot-1) # 递归排序左区间 QuickSort(a, pivot+1, end) # 递归排序右区间 a = [8,5,12,6,4,3,7,9,2,1,10,11] QuickSort(a, start=0, end=11) print(a)

每轮选基准、分左右,逐步缩小排序区间:

8 [1,5,6,4,3,7,2] [12,9,10,11] # 基准8,左小右大 1 [] [5,6,4,3,7,2] # 左区间基准1,右边都是大的 5 [2,4,3] [7,6] # 左区间基准5,再分左右 ...最终得到有序数组:[1,2,3,4,5,6,7,8,9,10,11,12]

特点

  • 时间复杂度:$O(n\log n)$(平均),$O(n^2)$(最坏,数组已近有序)

  • 空间复杂度:$O(\log n)$(递归栈)

  • 不稳定排序

  • 实际应用中效率极高,是工业界常用排序算法

三、随机快速排序:“随机选基准,避免最坏情况”

核心思路(大学生白话版)

解决普通快速排序的“致命缺点”:如果数组已近有序,选第一个元素当基准会导致时间复杂度飙升到$O(n^2)$。随机选基准能避免这种极端情况,让时间复杂度稳定在$O(n\log n)$。

代码与运行过程

import random def QuickSortPivot(a, start, end): # 随机选一个元素和第一个元素交换,作为基准 randIdx = random.randint(start, end) a[start], a[randIdx] = a[randIdx], a[start] pivot = start j = start + 1 for i in range(start+1, end+1): if a[i] < a[pivot]: a[j], a[i] = a[i], a[j] j += 1 a[pivot], a[j-1] = a[j-1], a[pivot] pivot = j - 1 print(a[pivot], a[start:pivot], a[pivot+1:end+1]) return pivot def QuickSort(a, start, end): if start >= end: return pivot = QuickSortPivot(a, start, end) QuickSort(a, start, pivot-1) QuickSort(a, pivot+1, end) a = [8,5,12,6,4,3,7,9,2,1,10,11] QuickSort(a, start=0, end=11) print(a)

随机选基准后,区间划分更均匀:

6 [5,4,3,2,1] [8,12,7,9,10,11] # 随机选基准6,左小右大 3 [2,1] [5,4] # 左区间随机选基准3,划分均衡 ...最终同样得到有序数组:[1,2,3,4,5,6,7,8,9,10,11,12]

特点

  • 时间复杂度:$O(n\log n)$(平均/期望)

  • 空间复杂度:$O(\log n)$

  • 不稳定排序

  • 比普通快速排序更稳定,是实际开发的首选快速排序版本

四、堆排序:“利用堆结构,依次取最值”

核心思路(大学生白话版)

先把数组构建成大顶堆(堆顶是最大值),然后把堆顶(最大值)和堆尾元素交换,再把堆的规模缩小1,重新调整成大顶堆;重复这个过程,直到堆为空——最终数组就是升序排列的。

代码与运行过程

def maxHeapify(heap, start, end): """堆调整函数:将以start为根的子树调整为大顶堆""" son = start * 2 # 打印当前要调整的节点和其子节点范围 print(f" 调整堆节点 {start} (子节点范围: {son}~{end}) | 当前堆: {heap}") while son <= end: # 选择左右子节点中较大的那个 if son + 1 <= end and heap[son + 1] > heap[son]: son += 1 print(f" 选择右子节点 {son} (值更大)") # 如果子节点大于父节点,交换 if heap[son] > heap[start]: print(f" 交换节点 {start}({heap[start]}) 和 {son}({heap[son]})") heap[start], heap[son] = heap[son], heap[start] start, son = son, son * 2 # 继续向下调整 print(f" 调整后堆: {heap}") else: print(f" 无需交换,当前子树已是大顶堆") break def HeapSort(a): """堆排序主函数""" heap = [None] + a # 堆从索引1开始,方便计算父子节点 root = 1 l = len(heap) print("===== 第一步:构建大顶堆 =====") # 从最后一个非叶子节点开始,自下而上构建大顶堆 for i in range(l//2, root-1, -1): print(f"\n开始调整非叶子节点 {i}:") maxHeapify(heap, i, l-1) print("\n===== 第二步:堆排序(逐步取出最大值) =====") # 逐步将堆顶最大值放到数组末尾,然后调整剩余堆 for i in range(l-1, root, -1): print(f"\n将堆顶({heap[root]})与末尾节点 {i}({heap[i]}) 交换 | 交换前: {heap}") heap[i], heap[root] = heap[root], heap[i] print(f"交换后: {heap} (已确定位置 {i} 的值为 {heap[i]})") print(f"调整剩余堆(范围: 1~{i-1}):") maxHeapify(heap, root, i-1) return heap[root:] # 测试数组 a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14] print("原始数组:", a) result = HeapSort(a) print("\n===== 最终排序结果 =====") print(result)

构建大顶堆后,依次取最值得到有序数组:

原始数组: [1,2,3,4,5,6,7,8,9,10,11,12,13,14] ===== 第一步:构建大顶堆 ===== 开始调整非叶子节点 7: 调整堆节点 7 (子节点范围: 14~14) | 当前堆: [None, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] 无需交换,当前子树已是大顶堆 开始调整非叶子节点 6: 调整堆节点 6 (子节点范围: 12~14) | 当前堆: [None, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] 无需交换,当前子树已是大顶堆 ... ===== 第二步:堆排序(逐步取出最大值) ===== 将堆顶(14)与末尾节点 14(7) 交换 | 交换前: [None, 14, 13, 12, 10, 11, 6, 7, 8, 9, 4, 5, 2, 3, 1] 交换后: [None, 1, 13, 12, 10, 11, 6, 7, 8, 9, 4, 5, 2, 3, 14] (已确定位置 14 的值为 14) 调整剩余堆(范围: 1~13): 调整堆节点 1 (子节点范围: 2~13) | 当前堆: [None, 1, 13, 12, 10, 11, 6, 7, 8, 9, 4, 5, 2, 3, 14] 选择左子节点 2 (值更大) 交换节点 1(1) 和 2(13) 调整后堆: [None, 13, 1, 12, 10, 11, 6, 7, 8, 9, 4, 5, 2, 3, 14] ... ===== 最终排序结果 ===== [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

特点

  • 时间复杂度:$O(n\log n)$(最好/最坏/平均)

  • 空间复杂度:$O(1)$(原地排序)

  • 不稳定排序

  • 适合需要找最值的场景(比如TopK问题)

4大进阶排序算法选型总结

算法

时间复杂度

空间复杂度

稳定性

适用场景

基数排序

$O(d \times (n+k))$

$O(n+k)$

稳定

多位数整数排序

快速排序

$O(n\log n)$(平均)

$O(\log n)$

不稳定

大规模数据(实际效率高)

随机快速排序

$O(n\log n)$(期望)

$O(\log n)$

不稳定

大规模数据(更稳定)

堆排序

$O(n\log n)$

$O(1)$

不稳定

大规模数据、TopK问题

到这里,基础+进阶共10种排序算法就全讲完啦!从$O(n^2)$的简单排序,到$O(n\log n)$的高效排序,每种算法都有自己的“生存空间”——理解它们的适用场景,写代码时才能既高效又省心。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/21 12:14:30

目标检测怎么做?TensorFlow Object Detection API 使用指南

TensorFlow Object Detection API 实战指南&#xff1a;从零构建工业级目标检测系统 在智能摄像头遍布楼宇、工厂和道路的今天&#xff0c;让机器“看见”并理解图像中的物体&#xff0c;早已不再是实验室里的概念。无论是自动识别产线上的瑕疵品&#xff0c;还是自动驾驶车辆…

作者头像 李华
网站建设 2026/5/20 13:22:55

GitHub提交图谱终极指南:如何用Le Git Graph轻松掌握代码演进历史

GitHub提交图谱终极指南&#xff1a;如何用Le Git Graph轻松掌握代码演进历史 【免费下载链接】le-git-graph Browser extension to add git graph to GitHub website. 项目地址: https://gitcode.com/gh_mirrors/le/le-git-graph 还在为GitHub上密密麻麻的提交记录感到…

作者头像 李华
网站建设 2026/5/20 21:23:15

MoveCertificate终极指南:轻松实现Android证书移动

MoveCertificate终极指南&#xff1a;轻松实现Android证书移动 【免费下载链接】MoveCertificate 支持Android7-15移动证书&#xff0c;兼容magiskv20.4/kernelsu/APatch, Support Android7-15, compatible with magiskv20.4/kernelsu/APatch 项目地址: https://gitcode.com/…

作者头像 李华
网站建设 2026/5/21 10:41:20

Monaco Editor性能调优终极指南:从卡顿到流畅的完整解决方案

Monaco Editor性能调优终极指南&#xff1a;从卡顿到流畅的完整解决方案 【免费下载链接】monaco-editor A browser based code editor 项目地址: https://gitcode.com/gh_mirrors/mo/monaco-editor 作为一名前端开发者&#xff0c;当你使用Monaco Editor进行代码编辑时…

作者头像 李华
网站建设 2026/5/21 4:40:07

Lunar:智能自适应亮度的外接显示器终极解决方案

Lunar&#xff1a;智能自适应亮度的外接显示器终极解决方案 【免费下载链接】Lunar Intelligent adaptive brightness for your external monitors 项目地址: https://gitcode.com/gh_mirrors/lu/Lunar Lunar是一款专为macOS系统设计的智能显示器亮度控制工具&#xff0…

作者头像 李华
网站建设 2026/5/20 11:30:24

Windows包管理革命:告别繁琐安装的Scoop实战指南

你是否曾为Windows软件安装的复杂流程感到困扰&#xff1f;下载安装包、运行向导、手动配置环境变量...这些重复性工作不仅耗时&#xff0c;还容易出错。今天&#xff0c;让我们一同探索Scoop这个命令行神器&#xff0c;它将彻底改变你对Windows软件管理的认知。 【免费下载链接…

作者头像 李华