news 2026/4/23 22:21:56

排序算法实战篇(二):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/4/22 18:50:40

Wan2.2-S2V-14B完全指南:掌握下一代AI视频生成技术

Wan2.2-S2V-14B完全指南&#xff1a;掌握下一代AI视频生成技术 【免费下载链接】Wan2.2-S2V-14B 【Wan2.2 全新发布&#xff5c;更强画质&#xff0c;更快生成】新一代视频生成模型 Wan2.2&#xff0c;创新采用MoE架构&#xff0c;实现电影级美学与复杂运动控制&#xff0c;支持…

作者头像 李华
网站建设 2026/4/23 12:55:10

宝塔面板v7.7.0离线部署终极手册:无网环境完美安装方案

宝塔面板v7.7.0离线部署终极手册&#xff1a;无网环境完美安装方案 【免费下载链接】btpanel-v7.7.0 宝塔v7.7.0官方原版备份 项目地址: https://gitcode.com/GitHub_Trending/btp/btpanel-v7.7.0 在当今高度隔离的内网环境中&#xff0c;如何高效部署服务器管理平台成为…

作者头像 李华
网站建设 2026/4/22 10:28:20

Robo-Diffusion:从噪声到机械艺术的生成之旅

Robo-Diffusion&#xff1a;从噪声到机械艺术的生成之旅 【免费下载链接】robo-diffusion 项目地址: https://ai.gitcode.com/hf_mirrors/ai-gitcode/robo-diffusion 开篇&#xff1a;当AI遇见机械美学 在数字艺术创作的前沿&#xff0c;一个专门致力于机器人图像生成…

作者头像 李华
网站建设 2026/4/23 10:51:24

Arduino Uno蜂鸣器音乐代码核心要点总结

用Arduino Uno玩转蜂鸣器音乐&#xff1a;从零开始的嵌入式音频入门你有没有试过用一块几块钱的无源蜂鸣器&#xff0c;让Arduino“唱”出《小星星》&#xff1f;这看似简单的项目背后&#xff0c;其实藏着微控制器如何生成声音、时间如何被精确控制、以及编程如何与音乐理论交…

作者头像 李华
网站建设 2026/4/22 23:37:47

打造炫酷桌面音乐可视化:Monstercat Visualizer终极配置手册

打造炫酷桌面音乐可视化&#xff1a;Monstercat Visualizer终极配置手册 【免费下载链接】monstercat-visualizer A real time audio visualizer for Rainmeter similar to the ones used in the Monstercat videos. 项目地址: https://gitcode.com/gh_mirrors/mo/monstercat…

作者头像 李华
网站建设 2026/4/23 1:33:42

ACT++模仿学习实战指南:从入门到精通的完整解决方案

项目亮点&#xff1a;为何选择ACT&#xff1f; 【免费下载链接】act-plus-plus 项目地址: https://gitcode.com/gh_mirrors/ac/act-plus-plus 在机器人技术快速发展的今天&#xff0c;模仿学习已成为让机器人快速掌握复杂技能的关键技术。ACT项目正是为解决这一挑战而生…

作者头像 李华