news 2026/10/30 15:30:04

新手小白学C语言——排序算法(冒泡、选择、插入)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
新手小白学C语言——排序算法(冒泡、选择、插入)

目录

一、引言

二、三种基础排序方式

1.冒泡排序

(1)代码复现

(2)代码演算

(3)逻辑概括

(4)应用场景

2.选择排序

(1)代码复现

(2)代码演算

(3)逻辑概括

(4)应用场景

3.插入排序

(1)代码复现

(2)代码演算

(3)逻辑概括

(4)应用场景

三、对三种排序的总结与思考

1、核心算法逻辑差异(本质区别)

2、应用场景差异(选型核心依据)

3、三者的相通之处与内在联系

4、核心总结与思考

四、编者的话


一、引言

排序算法作为一种常用的算法,与我们生活的方方面面息息相关,无论是做编程题还是解决具体生活场景中的问题,排序都发挥着重要的作用。因此,在C语言的学习中,要重视排序算法的学习并将其灵活运用。

二、三种基础排序方式

1.冒泡排序

(1)代码复现

void Sort1(int arr[6]) { for (int i = 0; i < 6; i++) { for (int j = 0; j < 6 - i - 1; j++) { int temp; if (arr[j] > arr[j + 1]) { temp = arr[j + 1]; arr[j + 1] = arr[j]; arr[j] = temp; } } } for (int i = 0; i < 6; i++) { printf("%4d", arr[i]); } }

(2)代码演算

下面我们通过一组无序数列进行对冒泡排序的学习:

3 5 1 4 2 8

我们先按照上述代码将这个无序数组进行排列:

i = 0:(j:0-->4) j = 0: arr[j] = 3 arr[j+1] = 5 //故if条件不成立,不进行数字交换 j = 1: arr[j] = 5 arr[j+1] = 1 //if成立,arr[j]和arr[j+1]发生交换 j = 2: arr[j] = 5 arr[j+1] = 4 //if成立,arr[j]和arr[j+1]发生交换 j = 3: arr[j] = 5 arr[j+1] = 2 //if成立,arr[j]和arr[j+1]发生交换 j = 4: arr[j] = 5 arr[j+1] = 8 //故if条件不成立,不进行数字交换

因此,经过第一大轮交换,数组变为3 1 4 2 5 8 。

i = 1:(j:0-->3) j = 0: arr[j] = 3 arr[j+1] = 1 //if成立,arr[j]和arr[j+1]发生交换 j = 1: arr[j] = 3 arr[j+1] = 4 //if条件不成立,不进行数字交换 j = 2: arr[j] = 4 arr[j+1] = 2 //if成立,arr[j]和arr[j+1]发生交换 j = 3: arr[j] = 4 arr[j+1] = 5 //if条件不成立,不进行数字交换

因此,经过第二大轮交换,数组变为1 3 2 4 5 8 。

i = 2:(j:0-->2) j = 0: arr[j] = 1 arr[j+1] = 3 //if条件不成立,不进行数字交换 j = 1: arr[j] = 3 arr[j+1] = 2 //if成立,arr[j]和arr[j+1]发生交换 j = 2: arr[j] = 3 arr[j+1] = 4 //if条件不成立,不进行数字交换

因此,经过第三大轮交换,数组变为1 2 3 4 5 8 。

其实可以发现,到这里数组已经变成了有序数组,那么后面 i = 3 和 i = 4的情况就不再继续阐述了,原理与步骤同上述操作。

(3)逻辑概括

相邻元素两两比较,逆序就交换,每轮把最大未排序数“冒”到末尾,重复至有序。

(4)应用场景

对小规模数据和接近有序的数组进行排序。

2.选择排序

(1)代码复现

void Sort4(int arr[6]) { int Idx,i,j,temp; for(i = 0;i <5;i++) { Idx = i; for(j = i+1;j < 6;j++) { if(arr[j] < arr[Idx]) { Idx = j; } } if(Idx != i) { temp = arr[i]; arr[i] = arr[Idx]; arr[Idx] = temp; } } for(int i = 0;i < 6;i++) { printf("%4d",arr[i]); } }

(2)代码演算

我们依然通过这个无序数组按照代码进行演算:

3 5 1 4 2 8
i = 0:(Idx = 0 j:1-->5) j = 1: arr[Idx] = 3 arr[j] = 5 //if不成立,Idx不与j交换 j = 2: arr[Idx] = 3 arr[j] = 1 //if成立,Idx与j交换 j = 3: arr[Idx} = 1 arr[j] = 4 //if不成立,Idx不与j交换 j = 4: arr[Idx} = 1 arr[j] = 2 //if不成立,Idx不与j交换 j = 5: arr[Idx} = 1 arr[j] = 8 //if不成立,Idx不与j交换

因此,经过第一轮循环,Idx变成了2,故数组变为 1 5 3 4 2 8 。

i = 1:(Idx = 1 j:2-->5) j = 2: arr[Idx] = 5 arr[j] = 3 //if成立,Idx与j交换 j = 3: arr[Idx] = 3 arr[j] = 4 //if不成立,Idx不与j交换 j = 4: arr[Idx] = 3 arr[j] = 2 //if成立,Idx与j交换 j = 5: arr[Idx] = 2 arr[j] = 8 //if不成立,Idx不与j交换

因此,经过第二轮循环,Idx变成了4,故数组变为 1 2 3 4 5 8。

i = 2:(Idx = 2 j:3-->5) j = 3: arr[Idx] = 3 arr[j] = 4 //if不成立,Idx不与j交换 j = 4: arr[Idx] = 3 arr[j] = 5 //if不成立,Idx不与j交换 j = 5: arr[Idx] = 3 arr[j] = 8 //if不成立,Idx不与j交换

因此,我们发现,第三轮循环已经没有交换出现了,故后续i = 3和i = 4不再赘述。

(3)逻辑概括

每次从未排序区间选出最小值,放到已排序区间末尾。

(4)应用场景

对数据量很小的数据进行排序。

3.插入排序

(1)代码复现

void Sort2(int arr[6]) { for (int i = 1; i < 6; i++) { if (arr[i] < arr[i - 1]) { int temp = arr[i]; int j; for (j = i - 1; j >= 0&&(arr[j] > temp); j--) { arr[j+1] = arr[j]; } arr[j+1] = temp; } } for (int i = 0; i < 6; i++) { printf("%4d", arr[i]); } }

(2)代码演算

我们依然通过这个无序数组按照代码进行演算:

3 5 1 4 2 8

下面进行推演:

3 5 1 4 2 8 i = 0: 3 5 | 1 4 2 8 temp = 1 □ 3 5 | 4 2 8 temp小于3 5 ,故3 5 都后移一位 1 3 5 4 2 8 i = 1: 1 3 5 | 4 2 8 temp = 4 1 3 □ 5 | 2 8 temp小于5 ,故5后移一位 1 3 4 5 2 8 i = 2: 1 3 4 5 | 2 8 temp = 2 1 □ 3 4 5 | 8 temp小于3 4 5 ,故3 4 5 都后移一位 1 2 3 4 5 8 i = 3 此时,arr[i] > arr[i - 1]故排序结束

(3)逻辑概括

把未排序元素依次插入到前面有序序列的正确位置。

(4)应用场景

对数据量小和接近有序的数组进行排序。

三、对三种排序的总结与思考

冒泡、选择、插入是最基础的三种内部排序算法,三者时间复杂度均为O(n²),属于简单暴力的排序算法,核心均通过双层循环完成有序化,但在核心逻辑、操作方式、性能特点和应用场景上存在显著差异,同时底层设计又具备高度相通性,以下从区别、场景、关联三方面整体总结。

1、核心算法逻辑差异(本质区别)

三者最核心的不同,在于每轮排序的目标和操作方式完全不同:

1. 冒泡排序:相邻交换,倒逼极值归位

通过相邻元素两两对比,逆序则交换,每一轮遍历都会将当前未排序区间的最大值“冒泡”到区间末尾,通过多次交换逐步实现整体有序。核心是「边比较、边交换」,交换次数最多。

2. 选择排序:先找极值,定点归位

全程遍历未排序区间,先找出区间内的最小值(最大值),仅用一次交换,将极值放到已排序区间末尾。核心是「多比较、少交换」,比较次数多,交换次数极少。

3. 插入排序:逐个插入,构建有序区间

默认数组前段为有序区间,依次取出未排序区间的元素,向前遍历,插入到有序区间的对应正确位置。核心是「移位插入、逐步构建有序」,无无效比较,贴合有序数组特性。

2、应用场景差异(选型核心依据)

三者虽都不适合大规模乱序数据,但根据自身性能特点,适配场景各有侧重:

1. 冒泡排序:仅适用于数据量极小、数组接近有序的场景,优化版冒泡可提前终止循环,效率最优;主要用于算法入门教学,实际项目极少使用,交换开销过高。

2. 选择排序:适配交换操作成本极高的场景(如复杂对象排序),凭借最少的交换次数降低性能损耗;不依赖数组有序度,稳定性差,适合小规模无序数据。

3. 插入排序:三者中实际可用性最高,数据量小、数组基本有序时效率远超另外两者;同时是唯一适配链表排序的算法,也是高级排序(快排、归并)的底层优化辅助算法。

3、三者的相通之处与内在联系

1.复杂度与层级相通:三者均为简单排序,平均、最坏时间复杂度均为O(n²),空间复杂度均为O(1),属于原地排序,无需额外开辟内存,仅依靠原数组完成排序。

2.排序思想同源:均采用「分区间排序」思路,将数组划分为已排序区间+未排序区间,通过多轮遍历,不断缩小未排序区间、扩大已排序区间,直至整体有序。

3.迭代逻辑一致:底层均依赖双层循环实现,外层循环控制排序轮数(确定已排序区间长度),内层循环负责未排序区间的比较、交换或移位操作。

4、核心总结与思考

从算法优劣来看,常规场景:插入排序 > 选择排序 > 冒泡排序。冒泡排序冗余交换最多,性能最差;选择排序牺牲比较次数换取最少交换,适配特殊场景;插入排序利用数据有序性,容错率最高、实用性最强。

三种基础排序的设计,体现了排序算法的核心优化思路:从“盲目交换”(冒泡),到“减少无效交换”(选择),再到“利用已有有序性、减少无效遍历”(插入),是算法从粗糙到精细的迭代过程。同时,三者的分区排序思想,也是后续快速排序、归并排序等高效分治算法的基础逻辑雏形。

此外,三者的特性也印证了算法选型的核心原则:没有最优算法,只有最适配场景的算法,需根据数据规模、有序程度、操作开销(比较/交换)灵活选择。

四、编者的话

小编作为安工大25级物联网工程学生,学习三种基础排序让我收获很多。

三者虽都是O(n²)算法,但设计思路、适用场景差异明显,也让我明白算法没有绝对好坏,要结合硬件资源取舍,其中插入排序更贴合物联网有序传感器数据处理需求。简单排序是高阶算法的基础,代码细节直接影响嵌入式设备功耗与效率。

希望以后能跟大家一起坚持手写推演吃透基础,结合单片机实验落地代码,同步刷题进阶分治、轻量化算法,依托竞赛与大创项目,把算法知识融入物联网软硬件开发,实现自己的专业梦!

PS:小编对算法类内容接触较少,也是刚开始系统性学习这方面的知识,如有不当,请您批评指正,小编将不尽感激,谢谢您!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 10:01:23

HTTP和HTTPS

目录 HTTP 请求行 方法 get和post的区别&#xff1a; URL 查询语句&#xff1a; 版本号 请求报头 3&#xff1a;Content-Type&#xff1a; 4&#xff1a;User-Agent(UA)&#xff1a; 6&#xff1a;Cookie&#xff1a; HTTP格式简略图为&#xff1a; HTTP的响应 响…

作者头像 李华
网站建设 2026/10/20 10:01:26

AI会话越多越忙?搭建首个自改进业务代理团队的完整实践

想象你正在经营一个内容服务型业务。早上打开Claude起草周内容&#xff0c;切换窗口让它处理销售跟进&#xff0c;再开一个窗口扫描潜在客户列表。几个小时后&#xff0c;你发现自己花在“管理AI”上的时间&#xff0c;比直接产出还多。输出量确实上去了&#xff0c;但注意力被…

作者头像 李华
网站建设 2026/10/20 10:01:45

微信支付证书自动化管理:Java平台证书下载工具深度解析

微信支付证书自动化管理&#xff1a;Java平台证书下载工具深度解析 【免费下载链接】CertificateDownloader Java 微信支付 APIv3 平台证书的命令行下载工具 项目地址: https://gitcode.com/gh_mirrors/ce/CertificateDownloader 在微信支付APIv3的集成过程中&#xff0…

作者头像 李华
网站建设 2026/10/30 1:47:24

Relative Rotation Graph(相对旋转图)|Highcharts创建RRG 图示列代码

本示例采用 Highcharts 构建 RRG 相对旋转图&#xff0c;可直观呈现个股 / 板块相对强弱轮动轨迹&#xff1b;灵活实现四象限专业分区、时序轨迹连线&#xff0c;搭配交互式悬浮提示与图表导出&#xff0c;多终端自适应&#xff0c;无缝嵌入投研分析系统&#xff0c;快速落地专…

作者头像 李华
网站建设 2026/10/20 4:25:49

Aperture多语言SDK使用教程:Go、Java、Python、JavaScript全攻略

Aperture多语言SDK使用教程&#xff1a;Go、Java、Python、JavaScript全攻略 【免费下载链接】aperture Rate limiting, caching, and request prioritization for modern workloads 项目地址: https://gitcode.com/gh_mirrors/ape/aperture 想要为您的现代工作负载实现…

作者头像 李华
网站建设 2026/10/22 16:46:40

Golang学习-sync.RWMutex 读写锁

sync.RWMutex 读写锁一、读写锁解决了什么问题 普通的 Mutex 不管操作是读还是写&#xff0c;一律互斥。但很多场景下&#xff0c;读操作远多于写操作&#xff0c;读操作之间本可以安全并发——它们不会修改数据。 RWMutex 提供两种锁&#xff1a; 读锁&#xff08;RLock&#…

作者头像 李华