排序算法总结

一、O (n²) 时间复杂度的排序算法(简单排序)

这类算法逻辑简单,适合小规模数据,但效率较低,核心是通过 "比较 - 交换" 逐步缩小无序范围。

1. 冒泡排序(Bubble Sort)
  • 方法
    从列表头部开始,重复比较相邻的两个元素,若前者大于后者则交换位置,直到最大的元素 "冒泡" 到列表末尾;然后缩小范围,对剩余元素重复操作。
    • 优化:若某一轮未发生交换,说明列表已有序,可提前结束。
  • 复杂度
    • 时间:最佳 O (n)(已排序),最坏 / 平均 O (n²)
    • 空间:O (1)(原地排序)
  • 特点:稳定排序(相等元素相对位置不变),适用于几乎有序的数据。
2. 选择排序(Selection Sort)
  • 方法
    每次从无序区中找到最小(或最大)的元素,将其与无序区的第一个元素交换,使无序区范围缩小 1,直到全部有序。
  • 复杂度
    • 时间:最佳 / 最坏 / 平均 O (n²)(无论是否有序,都需遍历找最值)
    • 空间:O (1)(原地排序)
  • 特点 :不稳定(例如 [3, 2, 2],第一个 2 可能被交换到第二个 2 后面),交换次数少(仅 n-1 次)。
3. 插入排序(Insertion Sort)
  • 方法
    将列表分为 "有序区" 和 "无序区",每次从无序区取一个元素,插入到有序区的合适位置(通过比较和后移元素),逐步扩大有序区。
    • 类比:整理扑克牌时,按顺序将新牌插入已有序的牌堆中。
  • 复杂度
    • 时间:最佳 O (n)(已排序),最坏 / 平均 O (n²)
    • 空间:O (1)(原地排序)
  • 特点:稳定排序,适用于小规模数据或部分有序数据(如接近有序的数组)。

二、O (n log n) 时间复杂度的排序算法(高效排序)

这类算法通过 "分治""归并" 等思想突破 O (n²) 瓶颈,适合大规模数据。

1. 快速排序(Quick Sort)
  • 方法
    1. 选一个 "基准值"(如第一个元素),通过分区操作将列表分为两部分:左边元素均小于基准值,右边均大于基准值(基准值归位)。
    2. 递归对左右两部分重复上述操作,直到子列表长度为 1(天然有序)。
  • 复杂度
    • 时间:最佳 / 平均 O (n log n),最坏 O (n²)(基准值选到最值,如已排序数组)
      • 优化:随机选择基准值或三数取中(避免最坏情况)。
    • 空间:O (log n)~O (n)(递归栈开销,平均 log n,最坏 n)
  • 特点:不稳定排序,实际应用中最快的排序之一(缓存友好,原地排序)。
2. 归并排序(Merge Sort)
  • 方法

    1. 分:将列表递归拆分为两个子列表,直到子列表长度为 1。
    2. 合:将两个有序子列表 "归并" 为一个有序列表(通过双指针比较,依次取较小元素)。
    • 类比:将两堆已排序的书合并为一堆,每次从两堆顶取较小的一本。
  • 复杂度

    • 时间:最佳 / 最坏 / 平均 O (n log n)(不受数据分布影响)
    • 空间:O (n)(需额外数组存储归并结果)
  • 特点:稳定排序,适合大规模数据或链表排序(链表归并无需额外空间)。

3. 堆排序(Heap Sort)
  • 方法

    1. 将列表构建为大顶堆(父节点 >= 子节点)。
    2. 每次将堆顶(最大值)与堆尾元素交换,缩小堆范围,再对新堆顶执行 "下沉" 操作(维持堆结构),重复至堆为空。
    • 堆:完全二叉树的一种,可通过数组索引快速访问父 / 子节点(父 i,左子 2i+1,右子 2i+2)。
  • 复杂度

    • 时间:最佳 / 最坏 / 平均 O (n log n)
    • 空间:O (1)(原地排序,堆结构通过数组索引维护)
  • 特点:不稳定排序,适合处理海量数据(堆结构可用于 Top K 问题)。

三、O (n) 时间复杂度的排序算法(非比较排序)

这类算法不通过元素比较实现排序,而是利用 "数值范围" 或 "哈希" 特性,仅适用于特定场景。

1. 计数排序(Counting Sort)
  • 方法

    1. 找出数据的最大值和最小值,创建一个计数数组(长度为 max-min+1),统计每个值出现的次数。
    2. 根据计数数组的累计次数,反向填充原数组(保证稳定性)。
    • 示例:排序 [2, 1, 3, 1, 2],计数数组统计后,按累计次数放回元素。
  • 复杂度

    • 时间:O (n + k)(n 为数据量,k 为数值范围 max-min+1)
    • 空间:O (k)(计数数组开销)
  • 特点:稳定排序,仅适用于数值范围小且为整数的数据(如年龄、成绩)。

2. 桶排序(Bucket Sort)
  • 方法

    1. 将数据分到若干个 "桶" 中(每个桶对应一个范围),桶内数据用其他排序算法(如插入排序)排序。
    2. 按桶的顺序拼接所有桶的结果。
    • 示例:排序 [0.42, 0.32, 0.33, 0.52, 0.37],按 0.1 间隔分桶,每个桶排序后拼接。
  • 复杂度

    • 时间:O (n + k)(n 为数据量,k 为桶数,若数据均匀分布,桶内排序接近 O (1))
    • 空间:O (n + k)(桶的存储空间)
  • 特点:稳定排序,适用于均匀分布的数据(如浮点数、身份证号分段)。

3. 基数排序(Radix Sort)
  • 方法

    1. 按 "低位到高位"(或反之)依次对数据的每一位进行排序(每位用计数排序 / 桶排序)。
    2. 每轮排序后,数据按当前位有序,最终整体有序。
    • 示例:排序 [123, 45, 678],先按个位排序,再按十位,最后按百位。
  • 复杂度

    • 时间:O (d*(n + k))(d 为位数,k 为每一位的基数,如十进制 k=10)
    • 空间:O (n + k)(临时存储桶)
  • 特点:稳定排序,适用于位数固定的数据(如整数、字符串)。

总结:排序算法对比表

排序算法 平均时间复杂度 最坏时间复杂度 空间复杂度 稳定性 适用场景
冒泡排序 O(n²) O(n²) O(1) 稳定 小规模、几乎有序数据
选择排序 O(n²) O(n²) O(1) 不稳定 小规模数据,交换成本高的场景
插入排序 O(n²) O(n²) O(1) 稳定 小规模、部分有序数据
快速排序 O(n log n) O(n²) O(log n) 不稳定 大规模数据(实际应用首选)
归并排序 O(n log n) O(n log n) O(n) 稳定 大规模数据、链表排序
堆排序 O(n log n) O(n log n) O(1) 不稳定 大规模数据,内存有限场景
计数排序 O(n + k) O(n + k) O(k) 稳定 数值范围小的整数
桶排序 O(n + k) O(n²) O(n + k) 稳定 均匀分布的数据
基数排序 O(d*(n + k)) O(d*(n + k)) O(n + k) 稳定 位数固定的数据(整数、字符串)

选择建议

小规模数据:插入排序(最快)。

  • 大规模数据:快速排序(平均最优)、归并排序(稳定)、堆排序(内存紧张)。
  • 特殊场景:数值范围小用计数排序,均匀分布用桶排序,位数固定用基数排序。
相关推荐
热爱生活的猴子11 分钟前
算法148. 排序链表
数据结构·算法·链表
孤独得猿19 分钟前
Redis类型之Hash
redis·算法·哈希算法
এ᭄画画的北北40 分钟前
力扣-5.最长回文子串
算法·leetcode
浩浩测试一下1 小时前
02高级语言逻辑结构到汇编语言之逻辑结构转换 if (...) {...} else {...} 结构
汇编·数据结构·数据库·redis·安全·网络安全·缓存
点云侠1 小时前
【2025最新版】PCL点云处理算法汇总(C++长期更新版)
c++·算法·计算机视觉·3d·可视化
暮乘白帝过重山2 小时前
负载因子(Load Factor) :哈希表(Hash Table)中的一个关键性能指标
开发语言·数据结构·哈希算法·散列表·负载因子·暮乘白帝过重山
zaiyang遇见2 小时前
【递归完全搜索】CCC 2008 - 24点游戏Twenty-four
算法·游戏·c/c++·全排列·信息学奥赛
似水流年流不尽思念2 小时前
常见的排序算法有哪些?它们的平均时间复杂度是多少?
后端·算法
楽码3 小时前
端到端应用Hmac加密
服务器·后端·算法