【数据结构】第十九弹---C语言实现冒泡排序算法

 ✨个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】

目录

1、冒泡排序基本思想

2、代码的初步实现

3、代码的优化

4、代码的测试

5、时空复杂度分析

6、模拟实现qsort

6.1、冒泡排序函数

6.2、交换数据函数

6.3、比较函数

总结


1、冒泡排序基本思想

冒泡排序法:(Bubble sort)是一种基础的交换排序。对数组进行遍历,每次对相邻两个进行比较大小,若大的数值在前面则交换位置(升序),完成一趟遍历后数组中最大的数值到了数组的末尾位置,再对前面n-1个数值进行相同的遍历,完成n-1次遍历则排序完成。

1. 第一趟对0~n-1遍历,依次对比前后的大小,若是不满足前小后大就交换,此时最大的数就被挪到了最后一个位置。

2. 对0~n-2遍历,继续比较前后大小,此时前n-2个数中最大的数就到了倒数第二个位置。

3. 重复上述动作继续遍历,每一次都将最大的数向后挤,直到遍历完毕排序成功。

2、代码的初步实现

对int 类型的数进行升序排序。

//交换函数
void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}
void BubbleSort(int* a, int n)
{for (int i = 0; i < n - 1; i++)//遍历n-1次{for (int j = 0; j < n - 1 - i; j++)//相邻两个数进行比较{if (a[j] > a[j + 1])//前面的值大于后面的值则交换{Swap(&a[j], &a[j + 1]);}}}
}

3、代码的优化

如果一次遍历,没有数据进行交换,则证明数组已经排好了顺序,不需要继续遍历,则引入exchange变量标志记录第一次遍历是否有数据交换。

void BubbleSort(int* a, int n)
{for (int i = 0; i < n - 1; i++){bool exchange = false;//默认false,值没变则没有交换for (int j = 0; j < n - 1 - i; j++)//遍历n-1次{if (a[j] > a[j + 1])//相邻两个数进行比较{Swap(&a[j], &a[j + 1]);//前面的值大于后面的值则交换exchange = true;}}if (exchange == false)//值没变则退出内循环break;}
}

4、代码的测试

测试代码:

//测试冒泡排序
int main()
{int a[] = { 9,8,7,6,5,4,3,2,1,0 };//给一组数据int sz = sizeof(a) / sizeof(a[0]);//计算数组元素个数printf("排序前:\n");ArrayPrint(a, sz);BubbleSort(a, sz);printf("排序后:\n");ArrayPrint(a, sz);return 0;
}

测试结果: 

5、时空复杂度分析

时间复杂度:

最坏情况:

当我们需要排升序的时候,原数组为降序,则为最坏情况。此时每次交换操作需要比较的次数从 n-1 次减少到 1 次,总共的比较次数是 (n-1) + (n-2) + … + 1 = n(n-1)/2,这是一个二次函数,因此时间复杂度为 O(n^2)。

最好情况:

当我们需要排升序时,原数组也是升序,我们只需要循环n次则可以判断结束,此时时间复杂度为O(N)。

由于时间复杂度取决于最坏情况,因此冒泡排序的时间复杂度为O(N^2)。

空间复杂度:

冒泡排序是一种原地排序算法,除了输入数组外,它只需要有限的几个变量(比如,交换标记和循环计数器)。因此,它的空间复杂度为常数空间O(1)。

6、模拟实现qsort

C语言中库函数 qsort是通过函数指针cmp传入数据类型的比较方式,实现对各种数据类型都能进行排序的功能。

我们将模仿qsort函数使用冒泡排序算法实现对各种数据类型都能进行排序的函数,并且使用const关键字严格限制参的属性,达到很高的健壮性要求。

6.1、冒泡排序函数

库函数qsort()函数接口:

void qsort (void* base, size_t num, size_t size,int (*com)(const void*,const void*));

模拟实现的函数接口:

void bubble_sort(void* base, //待排序数组首元素地址size_t num, //待排序数组元素个数size_t size,//待排序数组元素类型大小,单位为字节int (*com)(const void*,const void*)//函数指针 如何进行比较函数
);

6.2、交换数据函数

void swap(char* buf1, char* buf2, size_t size);

思想:

以1个字节为单位对两个指针指向的内容进行交换交换size次即可。

参数:

buf1:被交换的数据的地址。
buf2:被交换的数据的地址。
size:被交换数据类型的字节大小。

void swap(char* buf1, char* buf2, size_t size)
{assert(buf1 && buf2);//断言,指针不为空才能交换size_t i = 0;for (i = 0; i < size; i++){char tmp = *buf1;*buf1 = *buf2;*buf2 = tmp;buf1++;buf2++;}
}

6.3、比较函数

int cmp(const void* e1, const void* e2);

 void*是一个空类型的指针,可以存放任意类型的指针。

此处就用到了void*,void*为空指针,不能直接使用但是可以强转为其他的任何类型,那么此处我们应该强转成什么类型呢?直接强转成int*?很显然,如果强转为int*,那么char*,short*就不好进行转化了,因此此处转化为char*,如果要用到其他的类型,我们通过+数据类型大小就可以得到因此我们需要将指针转换成char*,依次按照字节进行交换。

返回值:

大于0,e1大;等于0,一样大;小于0,e2大。

参数:

e1:被比较的数据的地址,由void*指针接收,由const限制不能改变指针指向,但可以改变指针指向的内容。
e1:被比较的数据的地址,由void*指针接收,由const限制不能改变指针指向,但可以改变指针指向的内容。

函数体:

用户自定义实现数值的比较规则。

传参:

1. 被比较数值的地址由void*指针接收。

2. 数值在数组中第 i 个位置:将void*转换成char指针,(char*)base + i*size 。

一些规则的演示:

//int类型数据比较(升序)
int cmp(const void* e1, const void* e2)
{return *(int*)e1 - *(int*)e2;
}//int类型数据比较(降序)
int cmp(const void* e1, const void* e2)
{return *(int*)e2 - *(int*)e1;	//降序就是把e1,e2的位置交换一下
}//字符串比较(按字母升序)
#include <string.h>
int cmp(const void* e1, const void* e2)
{return strcmp((char*)e1, (char*)e2);	//字符串比较函数,与前面的比较规则一致
}

冒泡排序法的实现

#include <assert.h>		//引入头文件<assert.h>,使用assert函数断言//交换数据
void swap(char* buf1, char* buf2, size_t size)
{assert(buf1 && buf2);//断言,指针不为空才能交换size_t i = 0;for (i = 0; i < size; i++){char tmp = *buf1;*buf1 = *buf2;*buf2 = tmp;buf1++;buf2++;}
}//冒泡排序法
void bubble_sort(void* base,size_t num,size_t size,int (*cmp)(const void* e1,const void* e2))
{size_t i = 0;for (i = 0; i < num - 1; i++){size_t j = 0;for (j = 0; j < num - 1 - i; j++){//if (arr[j] > arr[j + 1])//(char*)base+j*size,(char*)base+(j+1)*sizeif(cmp((char*)base + j * size, (char*)base + (j + 1) * size)>0){swap((char*)base + j * size, (char*)base + (j + 1) * size,size);}}}
}

1.整型数组降序排序的演示

//整型降序比较函数
int cmp_int(void* e1, void* e2)
{return *((int*)e2) - *((int*)e1);
}void test1()
{int arr[] = { 0,1,2,3,4,5,6,7,8,9 };int sz = sizeof(arr) / sizeof(arr[0]);print_arr(arr, sz);//打印数组元素bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);print_arr(arr, sz);//打印数组元素
}

测试结果: 

2.结构体演示 

struct Stu
{char name[20];int age;
};int cmp_stu_by_age(const void* e1,const void* e2)
{return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}void test2()
{struct Stu arr[] = { {"zhangsan",18},{"lisi",32},{"wangwu",20} };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
}

测试结果: 

总结


本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/32018.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

针对 AI 优化数据湖仓一体:使用 MinIO 仔细了解 RisingWave

RisingWave 是现代数据湖仓一体处理层中的开源流数据库&#xff0c;专为性能和可扩展性而构建。RisingWave 旨在允许开发人员在流数据上运行 SQL。鉴于 SQL 是数据工程的通用语言&#xff0c;此功能非常重要。它具有强大的架构&#xff0c;包括计算节点、元节点和压缩器节点&am…

分享一个 Fail2ban 过滤规则

今天明月给大家分享个 Fail2ban 的过滤&#xff08;Filter&#xff09;规则&#xff0c;有关 Fail2ban 的文章大家可以参考【服务器全面使用 Fail2Ban 初见成效】和【使用 Fail2ban 禁止垃圾采集爬虫&#xff0c;保护 Nginx 服务器】等文了解&#xff0c;总之 Fail2ban 是 Linu…

分流井设备的监测控制和智慧运维

分流井是一种用于将雨水和污水进行分离的设施&#xff0c;通常设置在雨水管和污水管的汇合处。它可以根据不同的情况&#xff0c;将雨水和污水分别排放到不同的管道中&#xff0c;从而实现雨污分流的目的。 以下是一些常见的分流井类型和工作原理&#xff1a; 1、智能分流井&a…

java-SpringBoot执行定时任务-任务调度-@EnableScheduling和@Scheduled

文章目录 java借助springBoot框架&#xff0c;执行定时任务0. 项目地址1. 需求分析2、新建springBoot项目3. 编写定时任务3.1 开启调度任务3.2 编写定时任务方法 java借助springBoot框架&#xff0c;执行定时任务 0. 项目地址 https://github.com/OrangeHza/JavaDemo 1. 需求…

Redis小对象压缩

小对象压缩存储 如果Redis内部管理的集合数据结构很小&#xff0c;他会使用紧凑存储形式压缩存储。 Redis的ziplist是一个紧凑的字节数组结构&#xff0c;如下图所示&#xff0c;每个元素之间都是紧挨着的。 如果他存储的是hash结构&#xff0c;那么key和value会作为两个ent…

竞赛 机器视觉的试卷批改系统 - opencv python 视觉识别

文章目录 0 简介1 项目背景2 项目目的3 系统设计3.1 目标对象3.2 系统架构3.3 软件设计方案 4 图像预处理4.1 灰度二值化4.2 形态学处理4.3 算式提取4.4 倾斜校正4.5 字符分割 5 字符识别5.1 支持向量机原理5.2 基于SVM的字符识别5.3 SVM算法实现 6 算法测试7 系统实现8 最后 0…

Maven添加reactor依赖失败

目录 情况说明 解决过程 情况说明 起初是自己在学spring boot3&#xff0c;结果到了reactor这一部分的时候&#xff0c;在项目的pom.xml文件中添加下列依赖报错&#xff1a; <dependencyManagement><dependencies><dependency><groupId>io.projectr…

【CPP】插入排序、希尔排序

目录 1.插入排序1.1直接插入排序简介代码分析 1.2直接插入对比冒泡排序简介代码对比分析(直接插入排序与冒泡的复杂度效率区别) 1.3希尔排序简介代码分析 1.插入排序 基本思想&#xff1a;把一个待排数字按照关键码值插入到一个有序序列中&#xff0c;得到一个新的有序序列。 …

前沿技术丨S2S自动化测试解决方案

技术背景 随着面向服务的架构&#xff08;Service-Oriented Architecture&#xff0c;SOA&#xff09;在整车架构中的逐步推进及应用&#xff0c;车内网络通信中会一直并存基于以太网的面向服务和基于传统网络的面向信号的两类控制器&#xff0c;S2S&#xff08;Signal to Ser…

AXI学习笔记

文章目录 AXI口诀&#xff1a;AXI三种总线&#xff0c;三种接口&#xff0c;一个协议背景知识一、 AMBA&#xff1a;二、AXI2.1 通信协议与握手机制2.2 AXI协议特点2.3 三种AXI总线类型&#xff08;AXI4、AXI4-lite、AXI4-stream&#xff09;2.3.1 AXI通道&#xff08;5通道&am…

GD32 MCU的选项字节是什么?

GD32 MCU的选项字节是什么&#xff0c;有什么功能呢&#xff1f;选项字节被误篡改如何回复&#xff1f; 读者朋友们是否会有以上的疑问&#xff0c;首先我们先为大家介绍选项字节是什么以及选项字节的功能。 以GD32F30X系列MCU为例&#xff0c;其选项字节说明如下表所示&…

力扣每日一题 6/22 字符串/贪心

博客主页&#xff1a;誓则盟约系列专栏&#xff1a;IT竞赛 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 2663.字典序最小的美丽字符串【困难】 题目&#xff1a; 如果一个字符串满…

2024年7月JLPT日语N1真题试卷和答案解析,《Navi日语社》小程序在线答题考试,你的专属考试助手,日语学习神器!

掌握日语&#xff0c;从日语社小程序开始。这款小程序专为日语学习者设计&#xff0c;提供全面的JLPT备考资源&#xff0c;包括日语N1至N5等级考试的历年真题和2024年最新题目。无论你是日语新手还是备考高手&#xff0c;都能在这里找到适合自己的学习路径。 核心功能&#xf…

uniapp 打包 H5 实现在 uniapp 打包 APP 的 webview 通信

一、前言 遇到 uniapp 打包的 APP 在 webview 内嵌入 uniapp 打包的 H5 页面的需求&#xff0c;并实现通信。本篇主要总结了如何实现并总结遇到的问题&#xff0c;希望可以帮助大家减少负担。 实现需求主要有三个地方需要处理&#xff1a; index.html 的打包配置导入 uni.we…

书生·浦语大模型LagentAgentLego智能体应用搭建 第二期

文章目录 智能体概述智能体的定义智能体组成智能体范式 环境配置Lagent&#xff1a;轻量级智能体框架实战Lagent Web Demo用 Lagent 自定义工具 AgentLego&#xff1a;组装智能体“乐高”直接使用AgentLego作为智能体工具使用 用 AgentLego 自定义工具 智能体概述 智能体的定义…

网络编程之XDP技术的基础eBPF

一、XDP和TC的技术支撑 在前面分析了XDP和TC技术&#xff0c;从它们的细节里可以看出&#xff0c;它们都在调用eBPF的钩子函数。那么eBPF是什么呢&#xff1f;在2021年曾经写过一篇《eBPF介绍》的初级文章&#xff0c;对eBPF做了一个入门级的普及。但是未曾在技术层面上进行展…

win制作git局域网仓库,克隆

仓库目录制作成共享文件 共享目录\USER-20230725LO 然后win使用git克隆\USER-20230725LO\git\wbrj

发布微信小程序需要icp证吗?

微信小程序需要办理ICP许可证吗&#xff1f; 微信小程序需不需要办理ICP许可证&#xff0c;具体要看你的小程序类目是什么&#xff0c;还要看你的小程序具体是做什么的&#xff1f; 根据《互联网信息服务管理办法》 第四条 国家对经营性互联网信息服务实行许可制度&#xff1b…

ffmpeg windows系统详细教程

视频做预览时黑屏&#xff0c;但有声音问题解决方案。 需要将 .mp4编成H.264格式的.mp4 一般上传视频的站点&#xff0c;如YouTube、Vimeo 等&#xff0c;通常会在用户上传视频时自动对视频进行转码&#xff0c;以确保视频能够在各种设备和网络条件下流畅播放。这些网站通常…

以10位明星为你献上的祝福视频为标题的科普介绍文章-华媒舍

祝福视频的意义和影响 祝福视频是指明星通过录制的视频&#xff0c;向观众表达美好的祝愿和关怀。这种视频以真挚的情感和鼓舞人心的话语&#xff0c;给人们带来了不同寻常的温暖和感动。由于明星的影响力和号召力&#xff0c;他们的祝福视频可以更广泛地传播&#xff0c;让更…