五大经典排序算法详解
排序是数据结构与算法中最基础也最重要的操作之一。今天咱们来聊聊五种最经典的排序算法:插入、希尔、冒泡、选择和堆排序。我会结合代码和实际场景,带大家理清它们的核心逻辑与性能差异。
插入排序
核心思想
插入排序的思路非常直观,就像我们整理扑克牌一样。把数组分成'已排序'和'未排序'两部分,初始时已排序部分只包含第一个元素。每次从未排序部分取出一个元素,向前插入到已排序序列的正确位置,保持整体有序。重复这个过程直到所有元素归位。
代码实现
void InsertSort(int* a, int n) {
// 遍历未排序元素(从第 2 个元素开始)
for (int i = 1; i < n; i++) {
int end = i - 1; // 已排序部分末尾下标
int tmp = a[i]; // 保存当前待插入元素
// 向前查找合适位置,大于 tmp(降序)则后移
while (end >= 0) {
if (a[end] < tmp) {
a[end + 1] = a[end]; // 元素后移腾位置
end--;
} else {
break; // 找到位置,退出循环
}
}
a[end + 1] = tmp; // 插入到正确位置
}
}
注意:上述代码演示的是降序排列,若要升序只需将判断条件 a[end] < tmp 改为 a[end] > tmp。
效率分析
- 时间复杂度:最坏情况下需要比较 N²/2 次,为 O(N²)。但如果数组已经基本有序,每个元素只需比较 1 次,可优化至 O(N)。
- 空间复杂度:仅使用常数级辅助变量,O(1)。
- 稳定性:稳定。相等元素的相对位置在插入过程中不会改变。
希尔排序
核心思想
希尔排序可以看作是插入排序的升级版。它通过设定一个增量(步长),将数组分割成若干子序列进行分组插入排序。随着增量逐渐缩小,数组整体变得'基本有序',最后当增量为 1 时,进行一次标准的插入排序,此时效率极高。
代码实现
void ShellSort {
gap = n;
(gap > ) {
gap = gap / + ;
( j = ; j < gap; j++) {
( i = j; i < n - gap; i += gap) {
end = i;
tmp = a[i + gap];
(end >= ) {
(tmp > a[end]) {
a[end + gap] = a[end];
end -= gap;
} {
;
}
}
a[end + gap] = tmp;
}
}
}
}


