目录
直接选择排序
基本思想
每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。
- 在元素集合array[i]--array[n-1]中选择关键码最大(小)的数据元素。
- 若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换。
- 在剩余的array[i]--array[n-2](array[i+1]--array[n-1])集合中,重复上述步骤,直到集合剩余1个元素。
直接选择排序是暴力选数值。
堆排序是在堆的结构上选数值。
👇一个一个找最小的值
而我们要实现的是,最小的和最大的一起找,最小的放到最前面,最大的放到最后面。
整体思路(升序)
- 在元素集合array[i]--array[n-1]中选择关键码最小的数据元素。
- 若它不是这组元素中的第一个元素,则将它与这组元素中的第一个元素交换。
- 在剩余的array[i]--array[n-2](array[i+1]--array[n-1])集合中,重复上述步骤,直到集合剩余1个元素。
- 最大的数的下标:maxi 最小的数的下标:mini
- 最大的数的位置的下标:begin = 0
- 最小的数的位置的下标:end = n-1
- 选出元素下标和对应位置的下标,的元素交换,不是覆盖❗
- 重复上诉过程,然后begin-- / end++ 直到它们相遇(begin < end )
单趟
【注意】
- ❗注意这里交换的是数值,下标没有交换🆗也就是说交换完之后maxi&mini任然指向原来的位置
试想,如果第一个数就是最大的呢?这样的话,maxi就是0,当Swap(&a[mini], &a[begin]);后,如图。那么如果我们接下来实行Swap(&a[maxi], &a[end]);就会把1和7交换,这样就错了!
- 最大值元素的下标maxi可能与begin下标重叠
多趟
单趟结束后,我们需要让begin++,end--,以便下一趟的开始。下一趟我们要比较的就是中间的数。 依次往下,直到begin和end相遇结束。
代码实现
void SelectSort(int* a, int n)
{
int begin = 0, end = n - 1;
while (begin < end)
{
int mini = begin, maxi = begin;
for (int i = begin + 1; i <= end; ++i)
{
if (a[i] < a[mini])
{
mini = i;
}
if (a[i] > a[maxi])
{
maxi = i;
}
}
Swap(&a[begin], &a[mini]);
if (maxi == begin)
{
maxi = mini;
}
Swap(&a[end], &a[maxi]);
++begin;
--end;
}
}
特性总结
1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
2. 时间复杂度:O(N^2)
- 最好的情况也是O(N^2),因为我们并不知道他是否有序。
3. 空间复杂度:O(1)
4. 稳定性:不稳定