选择排序
算法描述:
选择排序也是一种相对简单的算法
选择排序的思想是:n次遍历数组,每一次遍历找出待排序数组中最大(最小)的元素,把他放在待排列数组的最前面(最后面)
排序个过程如下图:
图片来源于visualgo:排序
算法实现:
void SELsort(vector<int>& v)
{
for (int i = 0;i < v.size();i++)
{
int index = i;
for (int j = i+1;j < v.size();j++)
{
if (v[j] < v[index])
index = j;
}
int temp = v[i];
v[i] = v[index];
v[index] = temp;
}
}
针对以上代码,有以下的复杂度:
该算法的时间复杂度在各种情况下都为O(n^2),相比于冒泡排序,选择排序由于在平均情况下交换的次数较少,所以运行效率会略高于冒泡排序。
优化方案
我们使用选择排序的时候,是在待排序的数组中选择一个最大(最小)的元素放在待排序数组的最前面(最后面),那我们可以在一次遍历中即找到最大的元素,又找到最小的元素,把他们放在他们该在的位置,减少遍历的次数。
void SELsort(vector<int>& v)
{
for (int i = 0;i < v.size()/2;i++)
{
int indexMax = i;
int indexMin = i;
for (int j = i + 1;j < v.size()-i;j++)
{
if (v[j] < v[indexMin])
indexMin = j;
if (v[j] > v[indexMax])
indexMax = j;
}
int temp = v[i];
v[i] = v[indexMin];
v[indexMin] = temp;
if (i == indexMax)
v[v.size() - i - 1] = temp;
else
{
temp = v[v.size() - i - 1];
v[v.size() - i - 1] = v[indexMax];
v[indexMax] = temp;
}
}
}
相较上面的代码,这里的在每次遍历的时候找到了待排序数组中最大和最小的数,并把它们和最后面和最前面的数分别交换。
注意这一段代码:
if (i == indexMax)
v[v.size() - i - 1] = temp;
这段代码的作用是,如果遍历到的数组中最大的数刚好在数组的最前面,那么在最小的数交换的时候就会改变最大的数的位置。如果不加这一段代码的话,在某些情况下将会导致排序不正确。