在学习算法的过程中,很多人会遇到一个常见问题:选择排序是稳定排序吗?答案其实很直接——不是。但为什么不是?这得从“稳定性”和选择排序的工作方式说起。
什么是排序的稳定性?
所谓排序的稳定性,指的是如果两个元素的值相同,排序后它们的相对位置是否保持不变。举个生活中的例子:你在整理一堆发票,按日期排序。如果有两张金额相同的发票,原本A在B前面,排序后A还是在B前面,那这个排序就是稳定的;如果A跑到了B后面,那就说明它不稳定。
选择排序是怎么工作的?
选择排序的核心思想很简单:每次从未排序的部分中找出最小(或最大)的元素,放到已排序部分的末尾。听起来挺靠谱,对吧?但它的问题就出在这个“交换”操作上。
比如有这样一个数组:[5, 2, 3a, 3b, 1],其中 3a 和 3b 值相同,但出现顺序不同。选择排序第一步会找最小值1,然后把它和第一个元素5交换,变成:[1, 2, 3a, 3b, 5]。看起来没问题。
但关键在后续步骤。假设现在处理到第二个位置,当前最小的是2,不用换。接着是3a,也没问题。但如果中间某个阶段,有一个和3a相等的元素被提前交换到了前面,那原本的先后顺序就被打破了。
看一段代码更清楚
void selectionSort(int arr[], int n) {
for (int i = 0; i < n-1; i++) {
int min_idx = i;
for (int j = i+1; j < n; j++) {
if (arr[j] < arr[min_idx])
min_idx = j;
}
swap(arr[i], arr[min_idx]);
}
}
注意最后那行交换操作。即使 arr[i] 和 arr[min_idx] 的值相等,只要 min_idx 更小,就会发生交换。而一旦交换发生在相同值之间,原有的顺序就可能被打乱。这就是它不稳定的根源。
那有没有稳定的替代方案?
当然有。如果你需要稳定排序,可以考虑插入排序、归并排序或者系统自带的 stable_sort。这些方法能保证相同元素的相对位置不变。尤其是在处理复杂数据,比如学生成绩按姓名再按分数排序时,稳定性就显得特别重要。
所以回到最初的问题:选择排序是稳定排序吗?答案是否定的。它简单直观,适合教学,但在实际开发中,尤其是对顺序敏感的场景,最好别用它。