选择排序
1067 字
5 分钟
选择排序
选择排序
选择类排序的核心操作:每趟选出最小(或最大)元素放到最终位置。代表算法有简单选择排序和堆排序。
简单选择排序
核心思想
- 在未排序区间
[i, n-1]中找到最小元素的下标min - 将
a[min]与a[i]交换,a[i]到达最终位置 - 每轮确定一个元素,共需 n-1 轮
代码实现
void SelectionSort(int a[], int n) { for (int i = 0; i < n - 1; i++) { int min = i; for (int j = i + 1; j < n; j++) if (a[j] < a[min]) min = j; if (min != i) { int tmp = a[i]; a[i] = a[min]; a[min] = tmp; } }}复杂度
| 指标 | 值 | 说明 |
|---|---|---|
| 比较次数 | n(n-1)/2 | 与初始序列无关 ⭐ |
| 最好交换 | 0 | 已有序 |
| 最坏交换 | n-1 | 每轮都需交换 |
| 时间复杂度 | O(n²) | 所有情况 |
| 空间 | O(1) | — |
| 稳定性 | 不稳定 | 反例:{2, 2, 1} |
⚠️ 易错:简单选择排序是不稳定的。反例 {5a, 5b, 3},第一趟选出 3 与 5a 交换 → {3, 5b, 5a},相对顺序颠倒。
⚠️ 易错:比较次数始终为 n(n-1)/2,与初始序列无关。408 常考”以下哪种排序的比较次数与初始序列无关”。
与冒泡排序对比
| 对比项 | 简单选择 | 冒泡 |
|---|---|---|
| 比较次数 | 固定 n(n-1)/2 | 最好 O(n),最坏 O(n²) |
| 交换次数 | 最多 n-1 | 最坏 O(n²) |
| 对输入敏感 | 否 | 是 |
| 稳定性 | 不稳定 | 稳定 |
堆排序
O(1) 空间的 O(n log n) 排序
堆排序只用 O(1) 额外空间就能保证最坏 O(n log n)——快排做不到。但 cache 不友好,实际速度常输给快排。
堆的概念
堆是一棵完全二叉树:
- 大顶堆(最大堆):每个结点 ≥ 其左右孩子
A[i] ≥ A[2i+1]且A[i] ≥ A[2i+2] - 小顶堆(最小堆):每个结点 ≤ 其左右孩子
A[i] ≤ A[2i+1]且A[i] ≤ A[2i+2]
下标关系(数组从 0 开始):
| 关系 | 公式 |
|---|---|
| 结点 i 的父结点 | (i - 1) / 2 |
| 左孩子 | 2i + 1 |
| 右孩子 | 2i + 2 |
建堆过程
自底向上的向下调整(sift-down):从最后一个非叶子结点(下标 n/2-1)开始,依次向前对每个结点执行 sift-down。
void SiftDown(int A[], int n, int i) { int largest = i; int left = 2 * i + 1; int right = 2 * i + 2; if (left < n && A[left] > A[largest]) largest = left; if (right < n && A[right] > A[largest]) largest = right; if (largest != i) { swap(A[i], A[largest]); SiftDown(A, n, largest); }}
void BuildMaxHeap(int A[], int n) { for (int i = n / 2 - 1; i >= 0; i--) SiftDown(A, n, i);}⚠️ 易错:建堆的时间复杂度是 O(n),不是 O(n log n)。大部分结点位于底层,调整距离短,总和为 O(n)。
排序过程
void HeapSort(int A[], int n) { BuildMaxHeap(A, n); for (int i = n - 1; i > 0; i--) { swap(A[0], A[i]); // 堆顶与末尾交换 SiftDown(A, i, 0); // 调整堆顶,堆规模减 1 }}堆的插入与删除
| 操作 | 方法 | 时间 |
|---|---|---|
| 插入 | 追加到末尾,向上调整(sift-up) | O(log n) |
| 删除堆顶 | 与末尾交换,规模减 1,sift-down | O(log n) |
⚠️ 注意:用 sift-up 逐个插入建堆的时间复杂度为 O(n log n),不如自底向上 sift-down 的 O(n)。
复杂度
| 指标 | 值 |
|---|---|
| 最好时间 | O(n log n) |
| 最坏时间 | O(n log n) |
| 平均时间 | O(n log n) |
| 空间 | O(1) |
| 稳定性 | 不稳定 |
Top-K 问题
从 n 个元素中选出前 K 大/小:
- 建一个大小为 K 的小顶堆(求前 K 大)或大顶堆(求前 K 小)
- 扫描剩余元素,比堆顶大则替换并调整
- 时间复杂度:O(n log K)
考研高频考点
简单选择排序
- ⭐ 比较次数始终为 n(n-1)/2,与初始序列无关
- ⭐ 不稳定排序,反例 {2, 2, 1}
- ⭐ 时间复杂度始终 O(n²)
堆排序
- ⭐ 建堆复杂度 O(n) 而非 O(n log n)(高频陷阱)
- ⭐ 不稳定排序
- ⭐ 空间复杂度 O(1),原地排序
- ⭐ 父子结点下标关系(从 0 / 从 1 开始)
- ⭐ Top-K 问题的堆解法
- 给定序列判断是否为堆 / 画出建堆中间过程
- 堆排序 vs 快排 vs 归并的综合比较
关联页面
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
相关文章智能推荐
1
排序基础概念
数据结构2026-07-07
2
外部排序
数据结构2026-07-07
3
交换排序
数据结构2026-07-07
4
插入排序
数据结构2026-07-07
5
非比较排序
数据结构2026-07-07
随机文章随机推荐










