当前位置: 首页 > article >正文

从零开始完成冒泡排序(0基础)——C语言版

文章目录

    • 前言
    • 一、冒泡排序的基本思想
    • 二、冒泡排序的执行过程
      • (一)第一轮排序
      • (二)第二轮排序
      • (三)第三轮排序
      • (四)第四轮排序
    • 三、冒泡排序的代码实现(C语言)
      • (一)代码实现
      • (二)代码解析
    • 四、冒泡排序的时间复杂度和空间复杂度
      • (一)时间复杂度
      • (二)空间复杂度
    • 五、冒泡排序的优化
      • (一)设置标志位
      • (二)减少内层循环的范围
    • 六、总结

前言

在学习编程的过程中,排序算法是必须要掌握的知识之一。冒泡排序作为一种简单易懂的排序算法,非常适合初学者入门。今天,我们就从零开始,一起学习如何用C语言完成冒泡排序。
在这里插入图片描述

一、冒泡排序的基本思想

冒泡排序的基本思想是通过相邻元素之间的比较和交换,将最大的元素逐步移动到序列的末尾。就像水中的气泡一样,较小的元素会逐渐“浮”到序列的前面,而较大的元素会“沉”到序列的后面,因此得名冒泡排序。

举个生活中的例子,假设有5个人排成一列,他们想按照身高从矮到高排队。于是,第一个人和第二个人比较身高,如果第一个人比第二个人高,他们就交换位置;否则保持原位。接着,第二个人和第三个人进行比较和交换,依此类推,直到倒数第二个人和最后一个人比较。这样一轮下来,最高的人就会被“冒泡”到队伍的最后面。接下来,再对前面的4个人重复这个过程,直到所有人都排好序。

二、冒泡排序的执行过程

为了更好地理解冒泡排序,我们以一个具体的例子来说明。假设我们有这样一个数组:[5, 3, 8, 1, 2],我们要对其进行升序排序。

(一)第一轮排序

  1. 比较5和3,因为5>3,所以交换位置,数组变为[3,5,8,1,2]。
  2. 比较5和8,因为5<8,所以不交换位置,数组仍为[3,5,8,1,2]。
  3. 比较8和1,因为8>1,所以交换位置,数组变为[3,5,1,8,2]。
  4. 比较8和2,因为8>2,所以交换位置,数组变为[3,5,1,2,8]。

经过第一轮排序后,最大的元素8被移动到了数组的最后面。

(二)第二轮排序

  1. 比较3和5,因为3<5,所以不交换位置,数组仍为[3,5,1,2,8]。
  2. 比较5和1,因为5>1,所以交换位置,数组变为[3,1,5,2,8]。
  3. 比较5和2,因为5>2,所以交换位置,数组变为[3,1,2,5,8]。

经过第二轮排序后,第二大的元素5被移动到了数组的倒数第二位。

(三)第三轮排序

  1. 比较3和1,因为3>1,所以交换位置,数组变为[1,3,2,5,8]。
  2. 比较3和2,因为3>2,所以交换位置,数组变为[1,2,3,5,8]。

经过第三轮排序后,第三大的元素3被移动到了数组的倒数第三位。

(四)第四轮排序

比较1和2,因为1<2,所以不交换位置,数组仍为[1,2,3,5,8]。

经过四轮排序后,整个数组已经有序,排序完成。

三、冒泡排序的代码实现(C语言)

(一)代码实现

以下是用C语言实现的冒泡排序代码:

#include <stdio.h>void bubble_sort(int arr[], int n) {// 外层循环控制排序的轮数for(int i = 0; i < n-1; i++) {// 内层循环控制每轮中相邻元素的比较和交换for(int j = 0; j < n-i-1; j++) {if(arr[j] > arr[j+1]) {// 交换相邻元素的位置int temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}}
}int main() {int arr[] = {5, 3, 8, 1, 2};int n = sizeof(arr)/sizeof(arr[0]);printf("排序前的数组:");for(int i = 0; i < n; i++) {printf("%d ", arr[i]);}bubble_sort(arr, n);printf("\n排序后的数组:");for(int i = 0; i < n; i++) {printf("%d ", arr[i]);}return 0;
}

(二)代码解析

  1. #include <stdio.h>:引入标准输入输出库,用于使用printf等函数。
  2. void bubble_sort(int arr[], int n):定义了一个名为bubble_sort的函数,用于对数组进行冒泡排序。其中,arr是要排序的数组,n是数组的长度。
  3. 外层循环for(int i = 0; i < n-1; i++):控制排序的轮数。因为每一轮都会将最大的元素移到数组末尾,所以需要进行n-1轮排序。
  4. 内层循环for(int j = 0; j < n-i-1; j++):控制每轮中相邻元素的比较和交换。因为每一轮结束后,最后i个元素已经是有序的,所以内层循环的范围逐渐缩小。
  5. if(arr[j] > arr[j+1]):比较相邻的两个元素,如果前者大于后者,则需要交换位置。
  6. 交换元素的位置:通过临时变量temp来交换arr[j]arr[j+1]的值。
  7. int main():主函数,程序的入口。
  8. int arr[] = {5, 3, 8, 1, 2};:定义了一个要排序的数组。
  9. int n = sizeof(arr)/sizeof(arr[0]);:计算数组的长度。
  10. printf:用于输出数组的值,方便我们查看排序前后的结果。
  11. bubble_sort(arr, n);:调用冒泡排序函数,对数组进行排序。

四、冒泡排序的时间复杂度和空间复杂度

(一)时间复杂度

冒泡排序的时间复杂度取决于数组的初始状态。在最坏情况下,即数组完全逆序时,需要进行n-1轮比较,每轮比较的次数分别为n-1n-2、…、1次,总比较次数为(n-1)+(n-2)+…+1 = n(n-1)/2,因此最坏时间复杂度为O(n²)。在最好情况下,即数组已经有序时,只需要进行一轮比较,比较次数为n-1次,因此最好时间复杂度为O(n)。平均时间复杂度也为O(n²)

(二)空间复杂度

冒泡排序是一种原地排序算法,只需要一个临时变量来交换元素的位置,因此空间复杂度为O(1)

五、冒泡排序的优化

(一)设置标志位

在冒泡排序的过程中,如果某一轮没有发生任何交换操作,说明数组已经有序,可以提前结束排序。为此,我们可以设置一个标志位flag,在内层循环开始前将其置为0,如果发生了交换操作则将其置为1。每一轮结束后,如果flag仍为0,就直接跳出外层循环。

优化后的C代码如下:

#include <stdio.h>void bubble_sort_optimized(int arr[], int n) {// 外层循环控制排序的轮数for(int i = 0; i < n-1; i++) {int flag = 0;  // 设置标志位// 内层循环控制每轮中相邻元素的比较和交换for(int j = 0; j < n-i-1; j++) {if(arr[j] > arr[j+1]) {// 交换相邻元素的位置int temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;flag = 1;  // 发生交换,置为1}}if(flag == 0) {  // 如果没有发生交换,提前结束break;}}
}int main() {int arr[] = {5, 3, 8, 1, 2};int n = sizeof(arr)/sizeof(arr[0]);printf("排序前的数组:");for(int i = 0; i < n; i++) {printf("%d ", arr[i]);}bubble_sort_optimized(arr, n);printf("\n排序后的数组:");for(int i = 0; i < n; i++) {printf("%d ", arr[i]);}return 0;
}

(二)减少内层循环的范围

在每一轮排序中,最后i个元素已经是有序的,因此内层循环的范围可以进一步缩小,即从0到n-i-1。这样可以减少不必要的比较操作,提高算法的效率。

六、总结

通过本文的学习,我们从零开始,详细介绍了冒泡排序的基本思想、执行过程、C语言代码实现以及优化方法。冒泡排序作为一种简单的排序算法,虽然在实际应用中可能不如快速排序、归并排序等高效,但对于初学者来说,它是一个很好的入门算法,帮助我们理解排序算法的基本原理和实现方法。希望读者能够通过本文的学习,掌握冒泡排序的精髓,并在今后的学习中逐步深入,探索更多高效的排序算法。

相关文章:

从零开始完成冒泡排序(0基础)——C语言版

文章目录 前言一、冒泡排序的基本思想二、冒泡排序的执行过程&#xff08;一&#xff09;第一轮排序&#xff08;二&#xff09;第二轮排序&#xff08;三&#xff09;第三轮排序&#xff08;四&#xff09;第四轮排序 三、冒泡排序的代码实现&#xff08;C语言&#xff09;&am…...

工业级POE交换机:助力智能化与自动化发展

随着工业互联网、物联网&#xff08;IoT&#xff09;和自动化技术的快速发展&#xff0c;网络设备在工业领域的应用日益广泛。然而&#xff0c;在严苛环境下&#xff0c;传统网络设备往往难以应对复杂的温湿度变化、电磁干扰和供电不稳定等挑战。为同时满足数据传输与供电一体化…...

使用ZYNQ芯片和LVGL框架实现用户高刷新UI设计系列教程(第五讲)

在上一讲我们讲解了按键回调函数的自定义函数的用法&#xff0c;这一讲继续讲解回调函数的另一种用法。 首先我们将上一讲做好的按键名称以及自定义回调事件中的按键名称修改&#xff0c;改为默认模式为“open”当点击按键时进入回调函数将按键名称改为“close”&#xff0c;具…...

Burp Suite Professional 2024版本安装激活指南

文章目录 burpsuite简介Burp Suite的主要组件&#xff1a;Burp Suite的版本使用场景 下载地址使用教程 burpsuite简介 Burp Suite 是一个广泛使用的网络安全测试工具&#xff0c;特别是在Web应用程序安全领域。它主要用于发现和修复Web应用中的安全漏洞&#xff0c;特别适用于渗…...

【c++深入系列】:类与对象详解(上)

&#x1f525; 本文专栏&#xff1a;c &#x1f338;作者主页&#xff1a;努力努力再努力wz &#x1f4aa; 今日博客励志语录&#xff1a; 你仰望的星辰并非遥不可及&#xff0c;而是跋涉者脚印的倒影&#xff1b;你向往的远方未必需要翅膀&#xff0c;只要脚下始终有路&#x…...

6、进程理论和简单进程创建

一、了解进程推荐看这个视频&#xff0c;很详细 1、概念 进程(Process)程序的运行过程&#xff0c;是系统进行资源分配和调度的独立单元程序的运行过程&#xff1a;多个不同程序 并发&#xff0c;同一个程序同时执行多个任务。 就需要很多资源来实现这个过程。 每个进程都有一…...

java八股文之JVM

1.什么是程序计数器 程序计数器是 JVM 管理线程执行的“定位器”&#xff0c;记录每个线程当前执行的指令位置&#xff0c;确保程序流程的连续性和线程切换的准确性。线程私有的&#xff0c;每个线程一份&#xff0c;内部保存的字节码的行号。用于记录正在执行的字节码指令的地…...

Todesk介绍

文章目录 ToDesk 软件介绍1. 软件概述2. ToDesk 的功能特点2.1 简单易用2.2 高质量的图像与流畅的操作2.3 跨平台支持2.4 多屏显示与协作2.5 文件传输功能2.6 实时聊天与语音通话2.7 远程唤醒与自动启动2.8 多种权限设置与安全性2.9 无需公网 IP 3. ToDesk 的应用场景3.1 个人使…...

每日总结3.27

蓝桥刷题 1. 团建 &#xff08;树dfs&#xff09; #include <bits/stdc.h> using namespace std; const int N200005; int a[N],b[N]; int ans; map<int,vector<int>>m1,m2; void dfs(int x,int y,int count) { if(a[x]!b[y]) {return;} ansmax(ans,c…...

Linux 进程3-fork创建子进程继承父进程缓冲区验证

目录 1. fork创建子进程继承父进程缓冲区验证 1.1 write向标准输出&#xff08;终端屏幕&#xff09;写入数据验证 1.1.1 write函数写入数据不带行缓冲刷新 \n 1.1.2 write函数写入数据带行缓冲刷新 \n 1.2 fork创建前执行printf函数 1.2.1 fork创建前执行printf函数带\n…...

应用服务接口第二次请求一直pending问题

目录 一、问题背景二、问题排查过程三、解决方案四、总结 一、问题背景 升级内容发布到灰度环境&#xff0c;验证相关服务&#xff0c;查看接口调用日志&#xff0c;发现第一次请求正常&#xff0c;第二次相同接口请求就一直pending&#xff0c;其他服务也是如此 二、问题排查…...

基于FPGA的ESP8266无线数据传输(温湿度DTH11、光照强度BH1750、WIFI模块)连接中国移动onenet云平台,仿真+上板

文章目录 一、创建云平台产品设备二、FPGA仿真WIFI模块通信过程仿真分析2.上板 总结 一、创建云平台产品设备 使用串口助手测试传输过程 相关信息记录 二、FPGA仿真WIFI模块通信过程 仿真分析 //各个状态tx_dataalways (posedge clk or negedge rst_n) beginif(!rst_n) beg…...

5款视觉OCR开源模型

一、号称「世界上最好的 OCR 模型」Mistral OCR Mistral OCR 擅长理解复杂的文档元素&#xff0c;包括交错图像、数学表达式、表格和高级布局&#xff08;如 LaTeX 格式&#xff09;。该模型可以更深入地理解丰富的文档&#xff0c;尤其是包含图表、图形、公式和数字的科学论文…...

计算机二级(C语言)考试高频考点总汇(三)—— 结构体和共用体、结构体对齐规则、联合体大小计算

目录 九、结构体和共用体 十、结构体对齐规则 十一、联合体大小计算 九、结构体和共用体 141. 结构体是&#xff08;不同类型成员的集合&#xff09;&#xff0c;是⼀种用户自定义的数据类型&#xff0c;可以将不同类型的成员组合在⼀起&#xff0c;用于表示&#xff08;复…...

transformers中学习率warmup策略具体如何设置

在使用 get_linear_schedule_with_warmup&#xff08;如 Hugging Face Transformers 库中的学习率调度器&#xff09;时&#xff0c;参数的合理设置需要结合 数据量&#xff08;dataset size&#xff09;、批次大小&#xff08;batch size&#xff09; 和 训练轮数&#xff08;…...

“线程通信“一个案例

今天在处理项目需求的时候, 遇到这样一个问题: 项目中需要将用户界面上传的某种模型文件转换成另一种格式的文件, 以便进行预览操作. 而这个转换的过程需要调用到专业软件的脚本程序, 简单来说就是一个比较耗时的步骤. 并且这个转换还要分为两步进行, 需要调用两个脚本程序. 简…...

Charles抓HTTPS包

一、电脑端 1、证书下载与安装 安装完之后&#xff0c;重新点开看一看&#xff0c;确认下证书状态&#xff0c;安装的没问题 2、charles设置 抓电脑端要把这个点开 3、抓包 正经人看浏览器的包一般是F12&#xff0c;不过这里就用浏览器代替电脑软件了 如果配制好charles之后…...

JavaScript模板字符串:

1.示例代码&#xff08;包含注释&#xff09;: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>JS-数…...

【系统架构设计师】数据库系统 ③ ( 数据库设计过程 | 概念结构设计 | ER 图 简介 | 概念设计阶段 工作拆分 )

文章目录 一、数据库设计过程 概述二、ER 图 简介1、ER 图 概念2、ER 图 示例3、ER 图 关系类型① 一对一 ( 1:1 ) 关系② 一对多 ( 1:n ) 关系③ 多对多 ( n:n ) 关系 三、概念设计阶段 工作拆分 一、数据库设计过程 概述 数据库设计过程 : 需求分析阶段 : 明确 用户需求 ; …...

Servlet开发与生命周期详解-2

一、在集成开发环境当中开发Servlet程序 1.集成开发工具很多&#xff0c;其中目前使用比较多的是&#xff1a; IntelliJ IDEA&#xff08;这个居多&#xff0c;IDEA在提示功能方面要强于Eclipse&#xff0c;也就是说IDEA使用起来比Eclipse更加智能&#xff0c;更好用。JetBrai…...

将网络安全和第三方风险管理与业务目标相结合

在网络安全风险领域&#xff0c;我们经常遇到与企业语言不通的问题。这可能导致网络安全风险管理计划得不到支持。当发现网络安全风险时&#xff0c;困难在于以符合组织语言和目标的方式来表达它。 第三方风险属于另一个灰色地带。在组织内部&#xff0c;许多利益相关者&#…...

NO.58十六届蓝桥杯备战|基础算法-枚举|普通枚举|二进制枚举|铺地毯|回文日期|扫雷|子集|费解的开关|Even Parity(C++)

枚举 顾名思义&#xff0c;就是把所有情况全都罗列出来&#xff0c;然后找出符合题⽬要求的那⼀个。因此&#xff0c;枚举是⼀种纯暴⼒的算法。 ⼀般情况下&#xff0c;枚举策略都是会超时的。此时要先根据题⽬的数据范围来判断暴⼒枚举是否可以通过。 使⽤枚举策略时&#xf…...

postman测试调用WebService时不会自动添加命名空间

这两天在学习调用webservice&#xff0c;发现Postman直接调用时&#xff0c;返回 no namesapce on "myservice" element. you must send a soap message 找了很久&#xff0c;才明白&#xff0c;Postman 不会自动为请求添加命名空间&#xff0c;得手动在请求的 XML 数…...

【已解决】Git:为什么 .gitignore 不生效?如何停止跟踪已提交文件并阻止推送?

你可能遇到的问题 你已经提交了某个文件夹&#xff08;如 dataset&#xff09;到 Git 仓库&#xff0c;之后修改了它&#xff0c;但发现修改内容被 Git 持续跟踪&#xff0c;无法通过 .gitignore 忽略。尝试在 .gitignore 中添加规则后&#xff0c;修改的文件仍然显示为"…...

WebRTC协议全面教程:原理、应用与优化指南

一、WebRTC协议概述 **WebRTC&#xff08;Web Real-Time Communication&#xff09;**是一种开源的实时通信协议&#xff0c;支持浏览器和移动应用直接进行音频、视频及数据传输&#xff0c;无需插件或第三方软件。其核心特性包括&#xff1a; P2P传输&#xff1a;点对点直连…...

深度学习框架对比评测:TensorFlow、PyTorch、PaddlePaddle与MXNet的技术演进与应用实践

本文针对当前主流的四大深度学习框架&#xff08;TensorFlow 2.15、PyTorch 2.2、PaddlePaddle 2.5、MXNet 1.9&#xff09;&#xff0c;从架构设计、开发效率、训练性能、部署能力及生态系统等维度展开系统性评测。通过图像分类、自然语言处理、强化学习三类典型任务的基准测试…...

Ethernet(以太网)详解

一、Ethernet的定义与核心特性 以太网&#xff08;Ethernet&#xff09;是一种 基于IEEE 802.3标准的局域网&#xff08;LAN&#xff09;技术&#xff0c;用于设备间通过有线或光纤介质进行数据通信。其核心特性包括&#xff1a; 标准化&#xff1a;遵循IEEE 802.3系列协议&am…...

Python正则表达式(二)

目录 六、re.findall()函数和分组 1、0/1分组情况 2、多分组情况 七、或“|”的用法 1、作用域 2、用法 八、贪婪模式和懒惰模式 1、量词的贪婪模式 2、量词的懒惰模式 九、匹配对象 1、相关函数 六、re.findall()函数和分组 1、0/1分组情况 在正则表达式中&#x…...

学习《JS数据结构与算法》

博主这些日子去实习所以断更了&#xff0c;现在回归想接着学习一下数据结构与算法&#xff0c;学校也有上这门课&#xff0c;但博主去实习很多课都没上&#xff0c;现在自己看书学习一下&#xff0c;每天记录一下自己学习进度规范一下自己&#xff0c;需要这本书的可以私聊博主…...

图解AUTOSAR_SWS_FlashDriver

AUTOSAR Flash驱动(FLS)模块详解 AUTOSAR基础软件存储抽象层组件详细解析 目录 1. 概述 1.1. Flash驱动模块简介1.2. 功能和作用2. 架构设计 2.1. 模块架构2.2. API接口设计2.3. 状态机设计2.4. 异步操作时序2.5. 配置结构2.6. 任务处理流程3. 总结 3.1. 设计优势3.2. 应用场景…...