面试高频考点,手写排序算法是基本功。本文以冒泡排序为例,拆解核心思想、逐轮演示、代码实现、边界细节与优化方向。
对长度为 n 的数组 a,执行 n-1 趟扫描。第 i 趟(i=1..n-1)在 a[0]..a[n-i] 中通过相邻比较交换,将最大元素「冒泡」到 a[n-i] 位置。
| 轮次 | 排序后数组 | 已确定有序区 |
|---|---|---|
| 1 | 0,2,3,6,4,8,5,1,7,9 | 9 |
| 2 | 0,2,3,4,6,5,1,7,8,9 | 8,9 |
| 3 | 0,2,3,4,5,1,6,7,8,9 | 6,7,8,9 |
| 4 | 0,2,3,4,1,5,6,7,8,9 | 5,6,7,8,9 |
| 5 | 0,2,3,1,4,5,6,7,8,9 | 4,5,6,7,8,9 |
| 6 | 0,2,1,3,4,5,6,7,8,9 | 3,4,5,6,7,8,9 |
| 7 | 0,1,2,3,4,5,6,7,8,9 | 2,3,4,5,6,7,8,9 |
| 8 | 0,1,2,3,4,5,6,7,8,9 | 全有序 |
| 9 | 0,1,2,3,4,5,6,7,8,9 | 全有序 |
注意:第 7 趟已有序,但标准冒泡仍会执行第 8、9 趟(外层固定 n-1 次)。
public void bubbleSort(int[] array) {
for (int i = 0; i < array.length - 1; i++) { // 外层 n-1 趟
for (int j = 0; j < array.length - i - 1; j++) { // 内层逐对比较
if (array[j] > array[j + 1]) {
int tmp = array[j];
array[j] = array[j + 1];
array[j + 1] = tmp;
}
}
}
}
i = 0 .. n-2,共 n-1 趟,固定不变j = 0 .. n-i-2,比较 j 与 j+1,范围随 i 递减(n-1)+(n-2)+...+1 = n(n-1)/2 = O(n²)boolean swapped 标记,某趟无交换直接 breakpublic void bubbleSortOptimized(int[] array) {
int n = array.length;
int lastSwap = n - 1;
for (int i = 0; i < n - 1; i++) {
boolean swapped = false;
int currentLastSwap = 0;
for (int j = 0; j < lastSwap; j++) {
if (array[j] > array[j + 1]) {
swap(array, j, j + 1);
swapped = true;
currentLastSwap = j;
}
}
if (!swapped) break;
lastSwap = currentLastSwap;
}
}
| 指标 | 标准版 | 优化版(最好) | 优化版(最坏) |
|---|---|---|---|
| 时间复杂度 | O(n²) | O(n) | O(n²) |
| 空间复杂度 | O(1) | O(1) | O(1) |
| 稳定性 | 稳定 | ||
lastSwap 作用