算法
简单选择排序法(Simple Selection Sort)就是通过n - i次关键字间的比较,从 n - i + 1个记录中选出关键字最小的记录,并和第 i (1 <= i <= n)个记录交换。
代码
// 对顺序表 L 作简单选择排序
void SelectSort(PSqlist L)
{
int i, j, min;
for (i = 1; i < L->length; i++)
{
// 将当前下标定义为最小值下标
min = i;
// 循环之后的数据
for (j = i + 1; j <= L->length; j++)
{
// 如果有小于当前最小值的关键字
if (L->r[min] > L->r[j])
// 将此关键字的下标赋值给min
min = j;
}
// 若min不等于i,说明找到最小值,交换
if (i != min)
swap(L, i, min);
}
}
理解
首先我们提供了一个用于排序用的顺序表结构,
以及它的构造函数:使用一个vector来对数组里的数据进行初始化
// 用于要排序数组的个数最大值,可以根据需要修改
#define MAXSIZE 10
typedef struct
{
int r[MAXSIZE + 1]; // 用于存储要排序数组,r[0]用作哨兵或临时变量
int length; // 用于记录顺序表的长度
SqList(std::vector<int>& arr)
{
// 首先将长度置为0
length = 0;
// 数组下标首先从1开始
int index = 1;
for (auto i : arr)
{
r[index] = i;
length++;
index++;
if (index > MAXSIZE)
break;
}
}
}SqList,*PSqlist;
接着提供了一个交换函数
// 交换L中数组r的下标为i和j的值
void swap(SqList* L, int i, int j)
{
int temp = L->r[i];
L->r[i] = L->r[j];
L->r[j] = temp;
}
然后我们可以再提供一个输出打印函数来检验结果
// 输出数组r中的值
void print(PSqlist L)
{
assert(L != nullptr);
for (int i = 1; i <= L->length; i++)
{
std::cout << L->r[i] << " ";
}
std::cout << std::endl;
}
我们假设待排序的关键字序列是 {9,1,5,8,3,7,4,6,2} ;
对 i 来说:从1循环到8;
当 i = 1 时:
L.r [i] = 9, min 开始是1,然后与 j=2 到 9 比较 L.r [min] 与 L.r [j] 的大小,因为 j = 2 时最小,所以 min=2。最后交换了 L.r [2]与L.r [1]的值,如图所示:
当 i = 2 时:
L.r [i] = 9,min开始是2,经过比较后,min=9,交换 L.r [min]与L.r [i] 的值。如图所示:
当 i = 3 时:
L.r [i] = 5,min开始是3,经过比较后,min=5,交换 L.r [min]与L.r [i] 的值。如图所示:
之后的数据比较和交换完全雷同;
最多经过 8 次交换,就可以完成排序工作。
测试代码
我们可以使用如下代码进行检验:
#include <iostream>
#include <vector>
#include "SortStruct.h"
using namespace std;
int main()
{
std::vector<int> ar = {9,1,5,8,3,7,4,6,2};
SqList a(ar);
std::cout << "原始序列为:" << std::endl;
print(&a);
SelectSort(&a);
std::cout << "排序后:" << std::endl;
print(&a);
return 0;
}
运行结果
运行结果如下:
复杂度分析
从简单选择排序的过程来看,它最大的特点就是交换移动数据次数相当少,这样也就节约了相应的时间。
无论最好还是最差,其比较次数都是一样的多,第 i 趟排序需要进行 n - i 次关键字的比较。
故,
总的时间复杂度为O(n^2) ;
空间复杂度:O(1) ;
稳定性:不稳定 。
参考资料
【1】程杰. 大话数据结构. 北京:清华大学出版社,2011:2.