排序算法有哪些?这7种常用算法,程序员天天都在用

你写个 Python 脚本想把一串成绩从高到低排好,结果 list.sort() 一敲就完事——但有没有想过,背后它到底调用了哪种排序?其实,排序算法不是只有「系统自带」这一种答案,而是有一整套方法论。今天咱们不讲虚的,直接掰开揉碎,看看日常开发里真正用得上的几种排序算法

冒泡排序:最“憨”的入门款

就像水里的气泡往上冒,大的数一点点“浮”到末尾。每次比较相邻两个数,大的往后挪。虽然效率低(时间复杂度 O(n²)),但代码简单到一眼看懂:

def bubble_sort(arr):
n = len(arr)
for i in range(n):
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr

适合教学、小数据量手动调试,比如给 20 个学生名单按学号临时排个序,手写一个也花不了半分钟。

选择排序:每次挑个最小的放前面

思路直白:第一轮在全部数里找最小的,放到第 0 位;第二轮在剩下数里找最小的,放到第 1 位……以此类推。交换次数少(最多 n-1 次),但比较次数照样是 O(n²)。

插入排序:像理扑克牌一样自然

你摸牌时,一边摸一边往手里已排好的序列里插——这就是插入排序。对小数组或基本有序的数据(比如每天新增几条日志再整体排序),它比快排还快。Python 的 list.sort() 在小数据量时就悄悄用它打底。

归并排序:稳扎稳打的“分治派”

先把数组劈成两半,分别排好,再把两个有序数组合并成一个。时间稳定在 O(n log n),不随输入波动,适合对稳定性有要求的场景,比如按姓名排序后再按年龄二次排序——归并能保住第一次的顺序。

快速排序:实战中的“扛把子”

选个“基准数”,把比它小的全甩左边,大的全甩右边,然后左右两边递归重复。平均性能极佳(O(n log n)),内存占用小,C++ std::sort、Java Arrays.sort 对于基本类型都默认用它改良版。唯一小心点:如果原数组已经逆序,又没随机化基准,可能退化成 O(n²)。

堆排序:靠“堆”结构硬核上场

利用二叉堆的特性,先建大顶堆,再反复取堆顶、调整堆。时间始终 O(n log n),空间只需 O(1),适合内存紧张的嵌入式环境。不过实际开发中用得比快排和归并少些,毕竟写起来多绕两步。

计数排序:专治“范围小、种类少”

不靠比较,靠统计。比如给 1000 个学生的分数(0~100)排序,直接开个长度为 101 的数组,统计每个分数出现几次,再按顺序输出——O(n+k),快得飞起。但它只适用于整数,且值域不能太大,不然内存直接爆掉。

说到底,没有“最好”的算法,只有“最合适”的场景。写个小工具脚本,冒泡或插入够用;处理百万级用户订单,就得上快排或归并;做嵌入式固件?堆排序可能更靠谱。下次看到 sort(),别光点运行,想想它正在哪条算法流水线上干活。