算法思想
二元选择排序是对简单选择排序的改进,简单选择排序对序列每一次遍历只找出一个元素,而二元选择排序在每一次遍历中都会找出序列两端的元素(最大和最小),两端同时向中间逼近。这样理论上遍历的次数就减少了一半,加快了排序速度。
实现步骤
以从小到大排列为例:
1.遍历序列,找出最小元素和最大元素
2.将最小元素与无序部分第一个元素交换,最大元素与无序部分最后一个元素交换
3.更新无序部分边界
4.重复步骤1-3,直到无序部分不存在元素
源码
void BinarySelectionSort(std::vector<int> &vec)
{if (vec.size() <= 1) {return ;}int i, j, min_index, max_index;for (i = 0; i < vec.size()>>1; ++i) {//外层循环控制无序部分的边界min_index = i;max_index = vec.size()-i-1;for (j = i; j < vec.size()-i-1; ++j) {if (vec[j] < vec[min_index]) {min_index = j;}else if (vec[j] > vec[max_index]) {max_index = j;}}std::swap(vec[min_index], vec[i]);std::swap(vec[max], vec[vec.size()-i-1);}
}
第一段源码无论两端元素是否已经是最小(最大)值都进行交换,如果初始序列有相当一部分元素已经在正确的位置,这无疑增加了大量无意义的数值交换,下面是改进版:
void BinarySelectionSort(std::vector<int> &vec)
{if (vec.size() <= 1) {return ;}int i, j, min, max;for (i = 0; i < vec.size()>>1; ++i) { //外层循环控制无序部分的边界min_index = i;max_index = vec.size()-i-1;for (j = i; j < vec.size()-i-1; ++j) {if (vec[j] < vec[min_index]) {min_index = j;}else if (vec[j] > vec[max_index]) {max_index = j;}}if (min_index != i) {std::swap(vec[min_index], vec[i]);}if (max_index != vec.size()-i-1) {std::swap(vec[max_index], vec[vec.size()-i-1]);}}
}
第二段源码增加了判断条件,避免对已经有序的元素的数值交换。
时间复杂度
二元选择排序虽然将遍历次数减少了一半,但从时间复杂度来看与简单选择排序是一样的,都是O(n?),且两者对于同一序列的所需交换次数是一样的。
稳定性
与简单选择排序相同,对于相等元素,二元选择排序会破坏它们的相对次序,因此属于不稳定的排序。