目录
一、排序思想
每一趟从待排序的元素序列中选出关键字最小(或最大)的元素,顺序放在已排好序的子序列的最前面(或最后面),直到全部元素排序完毕。
二、算法过程
以升序为例,对 n 个元素的数组进行简单选择排序,共需进行 n - 1 趟选择。
第 i 趟选择(i 从 0 开始):
1、设置一个变量 min,记录当前趟最小元素的下标,初始值为 i。
2、从第 i + 1 个元素开始遍历到末尾,逐一与 a[min] 比较。
3、若发现更小的元素,则更新 min 的值。
4、一趟遍历结束后,若 min != i,则将 a[min] 与 a[i] 交换。
5、此时前 i + 1 个元素已经是有序的最小值序列。
示例:
初始序列:{ 49, 38, 65, 97, 76, 13, 27, 49 }
| 趟数 | 当前序列 | 选出最小值 | 交换位置 | 结果序列 |
|---|---|---|---|---|
| 第1趟 | 49, 38, 65, 97, 76, 13, 27, 49 | 13 (下标5) | 与 49(下标0) 交换 | 13, 38, 65, 97, 76, 49, 27, 49 |
| 第2趟 | 13, 38, 65, 97, 76, 49, 27, 49 | 27 (下标6) | 与 38(下标1) 交换 | 13, 27, 65, 97, 76, 49, 38, 49 |
| 第3趟 | 13, 27, 65, 97, 76, 49, 38, 49 | 38 (下标6) | 与 65(下标2) 交换 | 13, 27, 38, 97, 76, 49, 65, 49 |
| 第4趟 | 13, 27, 38, 97, 76, 49, 65, 49 | 49 (下标5) | 与 97(下标3) 交换 | 13, 27, 38, 49, 76, 97, 65, 49 |
| 第5趟 | 13, 27, 38, 49, 76, 97, 65, 49 | 49 (下标7) | 与 76(下标4) 交换 | 13, 27, 38, 49, 49, 97, 65, 76 |
| 第6趟 | 13, 27, 38, 49, 49, 97, 65, 76 | 65 (下标6) | 与 97(下标5) 交换 | 13, 27, 38, 49, 49, 65, 97, 76 |
| 第7趟 | 13, 27, 38, 49, 49, 65, 97, 76 | 76 (下标7) | 与 97(下标6) 交换 | 13, 27, 38, 49, 49, 65, 76, 97 |
经过 7 趟选择后,序列有序:{ 13, 27, 38, 49, 49, 65, 76, 97 }
三、代码实现
下列代码示例均是排成升序。
cpp
#include <stdio.h>
// 打印数组
void Print(int* a, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
printf("\n");
}
// 交换两个元素
void Swap(int* p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
// 简单选择排序(升序)
void SelectSort(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; // 更新最小值下标
}
}
// 将最小元素交换到第 i 个位置
if (min != i)
{
Swap(&a[i], &a[min]);
}
}
}
int main()
{
int arr[] = { 49, 38, 65, 97, 76, 13, 27, 49 };
int n = sizeof(arr) / sizeof(arr[0]);
printf("排序前:");
Print(arr, n);
SelectSort(arr, n);
printf("排序后:");
Print(arr, n);
return 0;
}
运行结果: 
四、效率分析
(一)时间复杂度
无论初始序列是有序、逆序还是乱序,简单选择排序都需要进行固定的比较次数。
比较次数:
第 1 趟:n - 1 次
第 2 趟:n - 2 次
...
第 n - 1 趟:1 次
总比较次数 = (n - 1) + (n - 2) + ... + 1 = n(n - 1)/2
交换次数:
最多 n - 1 次(每趟都交换),最少 0 次(已有序)。
因此,时间复杂度:O(n²)
(二)空间复杂度
仅使用常数个额外辅助变量(min、tmp 等),与问题规模无关。
因此,空间复杂度:O(1)
五、稳定性分析
简单选择排序是不稳定的排序算法。
反例说明:
初始序列:{ 2, 2, 1 }(带下划线的 2 表示第二个 2,用于区分相同关键字)
第 1 趟:选出最小值 1,与第 1 个元素 2 交换,得到 { 1, 2, 2 }
此时两个 2 的相对位置发生了改变(原第二个 2 现在到了第一个 2 的前面),故不稳定。
六、总结
| 特性 | 简单选择排序 |
|---|---|
| 排序思想 | 每趟选最小(大)值放到有序区末尾 |
| 时间复杂度 | O(n²) |
| 空间复杂度 | O(1) |
| 稳定性 | 不稳定 |
| 适用场景 | 数据量较小,或交换代价远高于比较代价时 |
感谢阅读,本文如有疏漏不当之处,烦请各位指正。