前言
如果说选择排序是'点兵点将',那么交换排序就是'同台竞技'。核心逻辑非常纯粹:通过两个元素之间的比较与位置交换,让有序的序列逐渐浮现。
本篇我们将深度拆解冒泡排序的极致优化,以及快速排序的工业级实现细节,包括 Hoare 版本、挖坑法、前后指针法以及非递归实现。
一、冒泡排序
1.1 算法思想
冒泡排序模拟了水中气泡上升的过程。大的数值(大气泡)会通过相邻位置的比较,一层一层地往数组末尾浮动。它不跨级,只和邻居讲道理。
核心步骤:
- 比较相邻的两个元素。如果第一个比第二个大,就交换它们。
- 对每一对相邻元素做同样的工作,从第一对到最后一对。
- 每一轮结束,最大的数都会被挪到当前待排序列的最后一位。
- 重复上述步骤,直到没有任何一对数字需要比较。
1.2 为什么你的冒泡排序总是比别人慢?
很多教科书给出的冒泡排序是'死'的。如果数组已经有序了,它依然会傻傻地跑完所有循环。
极致优化思路: 设置一个标记。如果在一轮遍历中没有发生任何交换,说明数组已经有序,直接提前终止!
1.3 代码实现
void BubbleSort(int* a, int n) {
// 外层循环:控制排序的轮数
// 每执行完一轮,待排序序列中最大的那个数就会被'冒泡'到数组的最后一位
// n 个元素通常需要比较 n-1 轮
for (int i = 0; i < n; i++) {
// 【优化关键】:设置一个标记变量 flag
// 初始设为 0,假设这一轮遍历中没有发生任何交换(即数组已经有序)
int flag = 0;
// 内层循环:负责在当前待排序区间内进行相邻两数的比较
// 随着 i 的增加,数组末尾已经排好序的元素越来越多
// 因此内层循环的边界是 n - i - 1
for (int j = 0; j < n - i - 1; j++) {
// 如果前一个数比后一个数大,则说明顺序不对,需要交换
if (a[j] > a[j + 1]) {
Swap(&(a[j]), &(a[j + 1]));
// 只要发生了交换,就说明此时数组可能还没完全有序
// 将 flag 置为 1
flag = 1;
}
}
(flag == )
;
}
}


