直接选择排序
基本思想
直接选择排序(Straight Select Sorting) 是一种简单的排序方法,它的基本思想是:每一次从待排序的数据元素中选出最小(或最大)的一个元素,通过交换存放在序列的起始位置(或最后一个位置),直到全部待排序的数据元素排完 。
排序过程
第一次从R[0]-R[n-1]中选取最小值(或最大值),与R[0]交换,第二次从R[1]-R[n-1]中选取最小值(或最大值),与R[1]交换,…,第i次从R[i-1]-R[n-1]中选取最小值(或最大值),与R[i-1]交换,…,第n-1次从R[n-2]-R[n-1]中选取最小值(或最大值),与R[n-2]交换,总共通过n-1次,得到一个按排序码从小到大(或从大到小)排列的有序序列。
这个算法也可以优化为在每次遍历数组寻找选择最值元素时,同时选出最大和最小的两个元素,然后进行交换,可以减少排序时间。
begin是需要遍历寻找最值元素的区间的第一个元素,end是需要遍历寻找最值元素的区间的最后一个元素,[begin, end]是一个闭区间,这个区间从[0, n-1]逐渐缩小至begin与end相遇,每次在区间内遍历,寻找最小元素下标min_index和最大元素下标max_index,以升序排序为例,然后将最小元素与区间内第一个元素交换,最大元素与区间最后一个元素进行交换,然后begin++,end–,直到begin与end相遇,此时即完成了整个数组的升序排序。
C语言代码实现
// 交换函数
void Swap(int* a, int* b)
{
int t = *a;
*a = *b;
*b = t;
}
// 升序排序
void SelectSort(int* a, int n)
{
int begin = 0;
int end = n - 1;
int min_index = 0, max_index = 0;
while (begin <= end)
{
min_index = max_index = begin;
for (int i = begin + 1; i <= end; ++i)
{
if (a[i] < a[min_index])
min_index = i;
if (a[i] > a[max_index])
max_index = i;
}
Swap(&a[begin], &a[min_index]);
if (max_index == begin)
max_index = min_index;
Swap(&a[end], &a[max_index]);
++begin;
--end;
}
}
时间复杂度
设整个需要排序的数组含有N个元素,在直接选择排序中,每次只选择出一个最值元素时,一共需要进行N-1次的选择和交换,即除了最后一个元素,其余所有元素均需要一次,每次选择则需要进行N-i(1<=i<=N-1)次的比较,而每次交换则需要最多三次移动,因此总的比较次数为(N*N-N)/2,总的移动次数为3(n-1)。所以直接选择排序的时间复杂度为O(N^2)。
在直接选择排序算法中,无论待排序的序列有序的程度怎样,均不会影响排序所消耗的时间,故其时间复杂度无论何时都是O(N^2)。
空间复杂度
从代码实现中可以容易看出,算法额外使用的空间是常数个,在交换元素时额外新开了一个变量的空间,与需要排序的元素个数无关,所以直接插入排序的空间复杂度为O(1)。
稳定性
直接选择排序时每一次选择最值元素,然后交换至第一或最后一个位置,如果在一趟选择中,选出了最小元素需要放在第一位,但是恰好最小元素与第一位元素中间有另一个和第一位元素相等的元素,此时交换之后两个相同的元素会被改变原来的相对前后位置,例如:序列6,3,6,1,7,第一次会选出最小的元素1和第一个元素6进行交换,而这样交换后两个6的相对位置发生了变化,这样就破坏了稳定性,所以直接选择排序是不稳定的。