一、介绍
1、冒泡排序的基本思想就是不断地比较、交换,通过交换完成最终的排序;而相比冒泡排序来说,选择排序法的基本思想是在排序时找到合适的关键字再做交换,且只移动一次就完成相应关键字的排序定位,也就是说每一趟在n - i + 1(i = 1, 2......, n - 1)个记录中选取关键字最小的记录作为有序序列的第i个记录。
二、简单选择排序算法
1、简单选择排序法(Simple Selection Sort)就是每次通过n - i次关键字间的比较,从n - i + 1个记录中选出关键字最小的记录,并和第i(1<=i<=n)个记录进行交换。
2、简单选择排序算法实现
#include <stdio.h>
// 定义待排序记录类型
typedef int RecordType;
/**
* 将待排序记录数组的下标i和下标j的两个记录进行交换
*/
void Swap(RecordType *rs, int i, int j)
{
RecordType tmp = *(rs + i);
*(rs + i) = *(rs + j);
*(rs + j) = tmp;
}
/**
* 打印待排序记录数组
*/
void PrintRs(RecordType rs[])
{
int i, count = rs[0];
for (i = 1; i <= count; i++)
{
printf("%d ", rs[i]);
}
printf("\n");
}
/**
* 对记录列表进行简单选择排序
*/
void SimpleSelectionSort(RecordType *rs)
{
int i, j, count = rs[0];
int min; // 用于保存每趟比较中最小的记录的下标
for (i = 1; i < count; i++)
{
min = i; // 首先将min初始化为这一趟比较的第一个记录的下标
for (j = i + 1; j <= count; j++)
{
if (*(rs + min) > *(rs + j))
{
min = j; // 如果当次比较发现下标j的记录更小,则使得min指向该记录的下标
}
}
// 该趟比较完毕,如果min不再指向初始记录下标,说明找到了更小的记录,则进行交换
if (min != i)
{
Swap(rs, i, min);
}
}
}
int main()
{
RecordType rs[] = {5, 1, 5, 3, 2, 4};
printf("排序前记录列表排序为:\t\t");
PrintRs(rs);
SimpleSelectionSort(rs);
printf("从小到大排序后,记录列表排序为:");
PrintRs(rs);
return 0;
}
3、时间复杂度
从以上简单选择排序的实现来看,最大的特点就是减少了每一趟比较过程中的记录交换次数,所以能节约不少时间。对于时间复杂度来说,无论是最好还是最坏情况,其比较次数都是一样的,对于第i趟排序需要进行n - i次关键字的比较,所以共需要比较n(n - 1)/2次;但是对于交换次数来说,最好的情况就是记录本身有序,无需交换;最坏情况就是记录是倒序排列的,交换次数需要n - 1次,基于最终的排序时间是比较和交换的次数总和,所以总的时间复杂度为O(n^2)。
参考书籍:《大话数据结构》