目录
作者想说
介于网上的排序算法文章大多都是死板的文字,本人文字理解能力一直不强。决定花时间做图解,把困难的问题变简单,把抽象的思维变具体。给想学习程序的小伙伴更好理解的文章资源。
文学家的浪漫是把一切用文字来书写,程序员的浪漫是把我们心中所想用代码书写
这里我将用图解来书写,程序在我脑子里的样子,我叫@张三xy,致力于写出优质作品的编程爱好者
1.选择排序的简介
1.1.什么是选择排序
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。
1.2.选择排序的算法性能
时间复杂度
选择排序的交换操作介于 0 和 (n – 1) 次之间。选择排序的比较操作为 n (n – 1) / 2 次之间。选择排序的赋值操作介于 0 和 3 (n – 1) 次之间。
比较次数 O(n^2),比较次数与关键字的初始状态无关,
总的比较次数 N=(n-1)+(n-2)+…+1=n*(n-1)/2。交换次数 O(n),最好情况是,已经有序,交换 0 次;最坏情况交换 n-1 次,逆序交换 n/2 次。交换次数比冒泡排序少多了,由于交换所需 CPU 时间比比较所需的 CPU 时间多,n 值较小时,选择排序比冒泡排序快
2.选择排序图解
2.1第一轮排序
这里我们第一轮排序,i = 0,结束后 i 下标对应的值,1成为当前序列 i ~ n 中最小的值
此时,我们下一轮就只需要在剩下的序列里找新的最小值就可以了
2.2第二轮排序
这里我们第二轮排序,i = 1,因为我们的 i 下标对应的2本身就是当前序列 i ~ n 中最小的值,
且它本身位置有序
所以,在第二轮中,进行不断比较后,不发生改变
2.3第三轮排序
这里我们第三轮排序,i = 2,前面都是有序我们依旧不用管,找到最后发现3是当前序列 i ~ n 中最小的值,我们交换元素, 当前 i 元素又是有序的了
完成第三轮排序后,元素中就只剩最后一对数据了,只需要最多一次交换
2.4第四轮排序
第四轮排序来了,i = 3,我们后面只有一个元素,所以这里最多只会有一次比较
这里我们找到了剩下元素中的最小值 4
完成最后一次交换,我们完成了数组的排序
3.选择排序的思考
3.1.选择排序的时间复杂度是多少?
答:选择排序的时间复杂度是O(n^2)
3.2.选择排序的实现思路是什么?
答:不断的移动找到最小值(最大值),然后放到顶端,通过减少交换次数来增加效率
3.3.选择排序和冒泡排序的区别?
答:
冒泡排序:优点是数据稳定误差小。缺点是速度慢。
选择排序法:优点是移动数据的次数少。缺点是比较数据的次数多
4.选择排序的代码实现
4.1.定义数组并传入我们的选择排序函数
int main() {
//自定义一个数组演示
int len = 5; //数组长度
int a[] = {3,2,5,1,4};
//传入我们的选择排序函数
selectionSort(a,len);
return 0;
}
4.2.选择排序函数的实现
#include <stdio.h>
/**
* 选择排序 复杂度O(n^2)
* @param a 数组名
* @param len 数组长度
*/
void selectionSort(int a[],int len)
{
for (int i = 0; i < len; i++)
{
int min = a[i]; //假设i是最小值
int idx = i; //记录当前最小值i的位置
// j = i + 1,假设 0 ~ i都是有序的,我们从 i + 1开始找
for (int j = i + 1; j < len; j++) {
if(a[j] < min)
{
min = a[j]; //最小值更新
idx = j; //记录位置,后面进行更新
}
}
//交换一下值
if(idx == i)continue; //如果最小值就是 i 本身,不需要改变,直接跳过
else
{
//交换当前最小值
a[idx] = a[i]; //交换后位置的值更新
a[i] = min; //最左边更新成当前序列中的最小值
}
for (int x = 0; x < len; ++x)printf("%d ",a[x]);
puts("");
}
}
以上就是我们 选择排序 的全部内容了,
走过路过的小伙伴们点点关注三连支持一下吧!
你们的支持就是我创作内容的最大动力!