目录
选择排序
1.回顾
前面我们讲到了排序算法的一些预备知识和最开始的一个排序(冒泡排序)然后还顺便把冒泡排序的升级版讲过了。想要看冒泡排序的小伙伴可以点击下方链接,进入我们的上一讲。点击这里进入上一讲
2.选择排序的思想
前面的冒泡排序的思想好像不怎么接近人的想法。当排序一组数据的时候,人可不会只看着旁边的一个是不是比我大,是大那就交换,这样交换是不是有点太频繁了,我们能不能减少交换的次数。想一想,我们能不能这样来:
第一次,找出最大的那个数,然后和最后的一个数交换就行,这样最大的数就会到应该到的地方。
第二次,在去除已经排序好的那个数,然后和第一步一样,找出最大吗,和最后的交换。
........
一直到排序完全部数据。
🆗 选择排序的基本思路已经形成了,选择排序的意思就是,选择一个最大的数,放到这个数应该放的位置,当然你也能选择最小的数,这只是从大到小还是从小到大的一个结果而已。
现在我们唯一的问题就是,我要怎么选出最大的那个,把他放到最后一个位置。
接下来解决这个问题:
可以这样:先定义一个最大元素下标的变量max,初始化为0,说明一开始初始化为第0个元素是最大的。接下来用第0个元素和第1个元素比较,如果第1个元素比第0个元素大,那就说明0号元素不是最大,而是1号元素,所以max=1;然后用第一个和第二个比,第二个比第一个大那么max=2,如果不比第一个大,那么最大的就是第一个,需要变,一直比较我们一直用max小标和第i个下标做比较。,到最后一个,那么是不是找出了全部的元素中最大的那个。接下来要做的就是把最大的元素和最后一个元素交换就排好了一个元素。经过n-1次交换之后,是不是就排好了n个元素,你是不是要问为什么是n-1,不是n,这就给你解答:当你已经排序号n-1个元素的时候,那么还没有排序的那个元素肯定是最小的,它就在它自己的位置。所以是n-1。
3.选择排序代码
//选择排序
//在每一次循环中选出一个最大的,和最后一个元素交换
void selectSort(int data[], int n)
{
int cmpNum = 0;
int swapNum = 0;
int maxIndex = 0;
printf("————————选择排序————————\n");
//排序前打印数据
printArr(data, n);
for (int i = n - 1; i > 0; --i)
{
maxIndex = 0;
for (int j = 0; j <= i; ++j)
{
++cmpNum;
if (data[j] > data[maxIndex])
maxIndex = j;
}
++swapNum;
swap(data, maxIndex, i);//最大和最后一个交换
printArr(data, n);
}
//排序完打印数据
printArr(data, n);
printf(" 比较了%d 次,交换了%d 次\n", cmpNum, swapNum);
printf("————————选择排序————————\n");
}
其中各变量和各函数的功能在前面冒泡排序的是已经说过了。这里的变量名和函数都是和冒泡同一个这里就不介绍了。
我们来解释代码:
maxIndex :就是前面说到的最大数的下标。
看循环里面,第一个循环,控制循环次数,第二个循环是从第一个走到最后一个,每个比较一下。i在不断减小,第二个循环用的是j<i,这就说明最后一个一直在减小。这就是前面说的去除最后一个排序完了的元素的操作。然后找到最大的和最后一个元素交换就ok了。
4.代码运行结果
5.选择排序的优劣评价
时间复杂度:O(N^2)
空间复杂度:O(1)
稳定性:不稳定
相较于冒泡排序,选择排序的比较次数不减少,但是交换次数大大减少只需要n - 1次就能完成。
6.结语
接下来还有插入排序,希尔排序,堆排序,我们的排序算法还会不断更新,请持续关注。