选择排序是稳定排序吗?看完你就明白了

在学习算法的过程中,很多人会遇到一个常见问题:选择排序是稳定排序吗?答案其实很直接——不是。但为什么不是?这得从“稳定性”和选择排序的工作方式说起。

什么是排序的稳定性?

所谓排序的稳定性,指的是如果两个元素的值相同,排序后它们的相对位置是否保持不变。举个生活中的例子:你在整理一堆发票,按日期排序。如果有两张金额相同的发票,原本A在B前面,排序后A还是在B前面,那这个排序就是稳定的;如果A跑到了B后面,那就说明它不稳定。

选择排序是怎么工作的?

选择排序的核心思想很简单:每次从未排序的部分中找出最小(或最大)的元素,放到已排序部分的末尾。听起来挺靠谱,对吧?但它的问题就出在这个“交换”操作上。

比如有这样一个数组:[5, 2, 3a, 3b, 1],其中 3a3b 值相同,但出现顺序不同。选择排序第一步会找最小值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。这些方法能保证相同元素的相对位置不变。尤其是在处理复杂数据,比如学生成绩按姓名再按分数排序时,稳定性就显得特别重要。

所以回到最初的问题:选择排序是稳定排序吗?答案是否定的。它简单直观,适合教学,但在实际开发中,尤其是对顺序敏感的场景,最好别用它。