冒泡/选择/插入排序
面试官在白板上写下数字:5, 3, 8, 4, 2
"手写一下冒泡排序,给我演示这个数组是怎么排序的。"
候选人小张刷刷刷写完了代码:
面试官看了一眼,问:"这个代码有问题,你知道吗?"
小张愣住了...
一、从一个问题开始
三大基础排序(冒泡、选择、插入)是排序算法的入门三件套,也是面试中的常客。
90%的候选人能写出冒泡排序,但能正确写出优化版的不到50%,能分析清楚三种排序适用场景的不到30%。
今天,我们把基础排序彻底讲透。
【直观类比】
三种排序就像整理扑克牌:
- 冒泡排序:从头到尾比较相邻两张牌,把大的往后"冒",一遍遍重复
- 选择排序:每次从牌堆里选最小的,放到最前面
- 插入排序:摸到一张牌,插到左边已经排好序的牌里
二、冒泡排序
2.1 标准版
过程演示:
2.2 优化版:提前退出
面试官问的问题就出在这里:如果数组已经有序,冒泡排序还在傻傻地比较吗?
2.3 再优化:记录最后交换位置
三、选择排序
3.1 标准版
核心思路:每轮从未排序区间选出最小元素,放到已排序区间末尾。
过程演示:
3.2 选择排序的致命缺点
选择排序的致命问题:不是原地排序的稳定版本!
四、插入排序
4.1 标准版
核心思路:把每个元素插入到左边已排序区间的正确位置。
过程演示:
4.2 插入排序的精髓:数据局部性
4.3 插入排序 vs 冒泡排序
五、复杂度分析
5.1 时间复杂度对比
5.2 空间复杂度
三种排序都是原地排序(in-place),空间复杂度都是O(1)。
5.3 为什么插入排序实际更快?
虽然三者最坏时间复杂度都是O(n²),但插入排序有优势:
- 比较次数更少:找到位置就停,不像冒泡要比较完所有对
- 交换次数更少:插入排序是后移元素,最后一次交换
- 缓存友好:访问的是连续内存
六、边界与特例
6.1 空数组和单元素数组
6.2 完全有序数组
6.3 完全逆序数组
七、常见误区
❌ 误区一:选择排序比冒泡排序好
实际情况:虽然选择排序的交换次数少,但选择排序是不稳定的,在某些场景下会导致问题。
❌ 误区二:排序算法越快越好
实际情况:对于小规模数据(n < 50),O(n²)的算法可能比O(nlogn)更快,因为:
- 没有递归栈开销
- 小数据量时常数项影响更大
- Java的Arrays.sort()在小数据量时用的就是插入排序
❌ 误区三:冒泡排序一无是处
实际情况:冒泡排序虽然慢,但它是稳定的,且实现简单,适合教学和小数据量场景。
八、记忆技巧
用一句话记住三种排序的核心特点:
冒泡:相邻比较,大的后冒;选择:选最小,放前面;插入:摸牌插队
用口诀记住稳定性:
选冒插,择不稳,冒插稳
九、实战检验
检验一:力扣912题 - 排序数组
检验二:判断排序稳定性
十、总结
三大基础排序各有特点:
- 冒泡排序:稳定,但效率低;优化后对有序情况有改善
- 选择排序:不稳定,但交换次数固定;适合交换成本高的场景
- 插入排序:稳定,对近乎有序的数据效率高;适合链表和小数据量
记住这三句话:
- 没有最好的排序算法,只有最适合场景的排序算法
- 稳定性和时间复杂度同样重要
- 近乎有序时,插入排序是隐藏的王者
下一篇文章,我们来聊聊面试中的高频考点——快速排序。