【C语言篇】简单选择排序法

🎐上篇文章,我们详细讲解了冒泡排序法,这篇文章,我们会对冒泡排序法进行深一步的分析、反思,引出一种比冒泡排序法更优的解法——简单排序法。🌠


💧引入–(冒泡排序再思考)

其实通过我们最先分析冒泡排序法的时候,也就是优化之前,会发现,这个代码的效率是很低的。这里再次引用一下:

#include<stdio.h>
#define N 10
int main()
{
	int arr[N] = {0};//创建一个整形数组
	int temp = 0;//创建一个变量,作用是在交换元素的过程中起到“空瓶”作用
	int i = 0;
	for (i = 0; i < N; i++)//for循环输入10个数字
	{
		scanf("%d", &arr[i]);
	}

	//循环控制变量i、j
	int j = 0;
	for (i = 0; i < N-1; i++)//外层循环:控制趟数
	{
		for (j = 0; j < N - 1 - i; j++)//这里j的作用有2个,第二个是充当元素下标(所以从0开始的好处)
		{
			if (arr[j] > arr[j + 1])//交换
			{
				temp = arr[j + 1];
				arr[j + 1] = arr[j];
				arr[j] = temp;
			}
		}
	}
	
	for ( i = 0; i < N ; i++)//输出
	{
		printf("%d\n", arr[i]);
	}


	return 0;

}

为什么这么说呢:原因有1,如果数组中元素在趟数执行完之前已经有序,但是剩余的趟数还是会照例执行,其实这是没有必要的(虽然后面我们优化了,但是这里我们仅对上面这个代码讨论),我们看,一次完整的大循环走下来,总共交换的次数最多会执行(N-1)+(N-2)+(N-3)+…1.这是一个等差数列,结果为N(N-1)/2,当N很大时,这个结果也会很大:
在这里插入图片描述

而每一次交换需要执行三行代码,所以时间效率无疑很低。
所以关键点就是:如何通过减少交换的次数,来提高代码的效率呢?
这就引出了第二种排序方法:简单选择排序法

🎄简单排序法–思路

根据上文,我们发现冒泡排序法交换次数太多。接下来,我们会逐步分析,如何实现选择排序:
step1思考: 冒泡排序中,每一趟都要比较,并且一旦if成立,则实现交换,这种不断比较、交换的目的是什么?是为了最大的那个数落在合适的位置对吧?当然,比较肯定是少不了的,因为只有通过比较,才能找出此趟中的最大数。那么交换次数能否减少呢?
step2如何减少:其实,每一趟,我们只希望此趟的最大数落在正确位置,那么能不能通过比较,找到这个最大数(假设不在正确位置),然后让这个最大数直接和正确位置(此趟中最大数被排好后的那个位置,该位置也放了我们的假设最大值)的那个数进行交换(如果正确位置本来就储放了此趟中最大数,则不交换)。也直接实现了:一趟排好一个数字的目的。并且大大减少了交换次数。因为一趟中最多只交换一次。(先选择,找出最大数,再交换)
step3:如何实现: 思路有了,那么代码如何实现呢。
(这里我们是按照先找最小值,再进行交换,讲解。本质和先找最大值,再交换是一样的)
首先肯定是需要两层循环,外层控制趟数,内层控制比较次数。
step①:第一趟:
假设第一个数(角标:0)就为最小值,角标记为k,将它和它后面的数进行比较,如果后面的数比它还小,那么k此时就与该数角标交换(直接k=角标,赋值即可)当然,这里肯定不是通过交换的数据,而是通过角标来实现,待会具体看。
step②:一趟内循环下来后,该角标代表的就是该组数字中最小数的角标。知道了角标,其实就是找到了这个最小数。
step③:直接将该角标和初始角标0进行交换,那么最小值就排在第一个,也就是正确位置,这样一趟下来,就有一个数字被排好。
第二趟,因为第一个数字已经排好了,所以假设第二个数字最小(k=1)…<步骤同上>
由此,每趟排好1个数,共需要9趟。
具体看如下图解和代码:

🎀图解

在这里插入图片描述

🙇‍♀️代码实现

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define N 10
int main()
{
	int arr[N] = { 0 };

	int i = 0;
	int j = 0;
	int temp = 0;
	for (i = 0; i < N; i++)
	{
		scanf("%d", &arr[i]);
	}
	for (i = 0; i < N - 1; i++)
	{
		int k = i;
		int Min = arr[k];//假设角标为k的元素为最小
		for (j = k+1; j < N ; j++)//注意,这里j初始化为i,因为按照这个程序进行,每趟中数字是从小到大排列
		{
			if (arr[k] >arr[j])//
			{
				k = j;//设置角标的好处:直接进行赋值,无需进行元素交换
			}
		}//一趟内层循环下来,虽然最小数没有处在正确位置(因为没有元素交换位置呀)
		//但是我们找到了这组数字中最小数的角标,为k
		if (k != i)//说明最小值并不是我们初始设的那个,说明找到了此趟最小值,所以直接把找到的最小值和假设的最小值交换位置即可
		{
			temp = arr[i];
			arr[i] = arr[k];
			arr[k] = temp;
		}
	}
	for (i = 0; i < N ; i++)
	{
		printf("%d\n", arr[i]);
	}

	return 0;

}

在这里插入图片描述


最后,希望此篇文章对你有帮助。可能有不正确、不准确的地方,还请大家多多指出。

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
第一 基础知识 实例1 数据类型转换 实例2 转义字符 实例3 关系和逻辑运算 实例4 自增自减 实例5 普通位运算 实例6 位移运算 实例7 字符译码 实例8 指针操作符 实例9 if判断语句 实例10 else-if语句 实例11 嵌套if语句 实例12 switch语句 实例13 for语句 实例14 while语句 实例15 do-while语句 实例16 break和continue语句 // 实例17 exit()语句 // 实例18 综合实例 实例19 一维数组 实例20 二维数组 实例21 字符数组 // 实例22 数组初始化 // 实例23 数组应用 实例24 函数的值调用 实例25 函数的引用调用 //swap 实例26 数组函数的调用 // 实例27 命令行变元 // 实例28 函数的返回值 实例29 函数的嵌套调用 实例30 函数的递归调用 实例31 局部和全局变量 实例32 变量的存储类别 实例33 内部和外部函数 实例34 综合实例1 实例35 综合实例2 实例36 变量的指针 实例37 一维数组指针 实例38 二维数组指针 实例39 字符串指针 实例40 函数指针 实例41 指针数组 实例42 二维指针 实例43 指针的初始化 实例44 综合实例 第二 深入提高 实例45 结构体变量 实例46 结构体数组 实例47 结构体指针变量 实例48 结构体指针数组 实例49 共用体变量 实例50 枚举类型 实例51 读写字符 实例52 读写字符串 实例53 格式化输出函数 实例54 格式化输入函数 实例55 打开和关闭文件 实例56 fputc()和fgetc() 实例57 函数rewind() 实例58 fread()和fwrite() 实例59 fprintf()和fscanf() 实例60 随机存取 实例61 错误处理 实例62 综合实例 实例63 动态分配函数 实例64 常用时间函数 实例65 转换函数 实例66 查找函数 实例67 跳转函数 实例68 排序函数 实例69 伪随机数生成 实例70 可变数目变元 第三 常用算法 实例71 链表的建立 实例72 链表的基本操作 实例73 队列的应用 实例74 堆栈的应用 实例75 串的应用 实例76 树的基本操作 实例77 冒泡排序 实例78 堆排序 实例79 归并排序 实例80 磁盘文件排序 实例81 顺序查找 实例82 二分查找 实例83 树的动态查找 实例84 二分求解方程 实例85 牛顿迭代求解方程 实例86 弦截求解方程 实例87 拉格朗日插值 // 实例88 最小二乘拟合 ?? 实例89 辛普生数值积分 实例90 改进欧拉 实例91 龙格-库塔 实例92 高斯消去 实例93 正定矩阵求逆 第四 综合应用 实例94 用C语言实现遗传算法 实例95 人工神经网络的C语言实现 实例96 K_均值算法 实例97 ISODATA算法 实例98 快速傅立叶变换 实例99 求解野人与传教士问题 实例100 简单专家系统
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是瑶瑶子啦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值