目录
前言
✅选择排序
基本思想
实现逻辑
动图演示
复杂度分析
代码实现
优化改进-->二元选择排序
改进代码
在学数据结构的第一节课就知道了数据结构课程是要管理并且学会操作数据,当然操作数据首先想到的就是数据的排序,排过顺序的数据的使用价值才够大。前面我们学习了顺序表也学习了链表等等,这些就是储存数据的方法,下面我们来看一看选择排序的特点与效率怎么样。
选择排序(Selection sort)是一种简单直观的排序算法。
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
选择排序的思想其实和冒泡排序有点类似,都是在一次排序后把最小的元素放到最前面,或者将最大值放在最后面。但是过程不同,冒泡排序是通过相邻的比较和交换,而选择排序是通过对整体的选择,每一趟从前往后查找出无序区最小值,将最小值交换至无序区最前面的位置。
⭕ 第一轮从下标为 1 到下标为 n-1 的元素中选取最小值,若小于第一个数,则交换
⭕ 第二轮从下标为 2 到下标为 n-1 的元素中选取最小值,若小于第二个数,则交换
⭕ 依次类推下去……
注:红色表示当前最小值,黄色表示已排序序列,绿色表示当前位置。
✅平均时间复杂度:O(N^2)
✅最佳时间复杂度:O(N^2)
✅最差时间复杂度:O(N^2)
✅空间复杂度:O(1)
✅稳定性:不稳定
void Swap(int* p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void SimpleSelectSort(int *a,int len)
{
int min;
for (int i = 0;i < len - 1;i++)
{
min = i;
for (int j = i + 1;j < len;j++)
{
if (a[min] > a[j])
{
min = j;
}
}
if (min != i)
{
Swap(&a[min], &a[i]);
}
}
}
改进思路: 简单选择排序,每趟循环只能确定一个元素排序后的定位。根据之前冒泡排序的经验,我们可以考虑改进为每趟循环确定两个元素(当前趟最大和最小记录)的位置,从而减少排序所需的循环次数。改进后对n个数据进行排序,最多只需进行[n/2]趟循环即可。
//二元选择排序
void Swap(int* p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void SelectSort(int* a, int n)
{
int begin = 0, end = n - 1;
while (begin < end)
{
int mini = a[begin];
int maxi = a[begin];
for (int i = begin; i <= end; i++)
{
if (a[i] > a[maxi])
maxi = i;
if (a[i] < a[mini])
mini = i;
}
Swap(&a[begin], &a[mini]);
// 如果maxi和begin重叠,修正一下即可
if (begin == maxi)
maxi = mini;
Swap(&a[end], &a[maxi]);
begin++;
end--;
}
}