C语言进阶之冒泡排序
✨ 猪巴戒:个人主页✨
所属专栏:《C语言进阶》
🎈跟着猪巴戒,一起学习C语言🎈
目录
前情回顾
1、回调函数
2、冒泡排序
3、库函数qsort
cmp(sqort中的比较函数,需要我们自定义)
整形的升序排列
整形的倒序排列
结构体的排序
结构体按照名字(char类型)排序
结构体按照年龄(int类型)排序
库函数qsort的模拟实现(bubble_sort)
呈现bubble_sort函数的整体代码:
bubble_sort的结构体排序
age:
name:
前情回顾
函数指针
我们有一个函数,为Add,我们将函数的地址用指针来存储,这个指针就叫做函数指针。
int Add(int x,int y)
{return x+y;
}int main()
{int (*pf)(int,int) = Add;//pf就是函数指针。return 0;
}
函数指针数组
把函数指针放在数组中,就是函数指针的数组。
int Add(int x,int y)
{return x+y;
}
int Sub(int x,int y)
{return x-y;
}
int Mul(int x,int y)
{return x*y;
}
int Div(int x,int y)
{return x/y;
}
int main()
{int (*arr[4])(int ,int) = {Add,Sub,Mul,Div};//这个就是函数指针数组。return 0;
}

函数指针数组就可以调用函数:
int main()
{int i = 0;scanf("%d",&i);int ret = arr[i](8,4);printf("%d\n",ret);
}
1、回调函数
回调函数就是应该通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由这个函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
我们可以把Add函数称为回调函数。
int Add(int x,int y)
{return x+y;
}
int main()
{int (*pf)(int,int) = Add;int ret = pf(8,4);return 0;
}
2、冒泡排序
对一个数组进行升序排序。
void bubble_sort(int arr[],int sz)
{int i=0;//趟数for(i=0;i<sz-1;i++){//一趟冒泡排序的过程int j = 0;for(j=0;j<sz-1-i;j++){if(arr[j]>arr[j+1]){int tmp = arr[j];arr[j] =arr[j+1];arr[j+1] = tmp;}} }
}
int main()
{int arr[] = {9,8,7,6,5,4,3,2,1 };//把数组排成升序int sz = sizeof(arr)/sizeof(arr[0]);bubble_sort(arr,sz);int i = 0;for(i=0;i<sz;i++){printf("%d",arr[i]};}
这个冒泡排序不够高效,如果我们进行一趟冒泡排序,但是一个数字都没有交换,就说明这个数组已经排序好了,就不用继续排序了,
我们可以通过,在进行这一趟冒泡排序前设定int flag = 1;
如果数字进行了交换,就把flag的值改为0;
没有数字进行交换,那么flag的值还是1;
我们通过判断flag的值看数组是否已经排好序。
void bubble_sort(int arr[],int sz)
{int i=0;//趟数for(i=0;i<sz-1;i++){int flag = 1;//假设数组是排好序的。//一趟冒泡排序的过程int j = 0;for(j=0;j<sz-1-i;j++){if(arr[j]>arr[j+1]){int tmp = arr[j];arr[j] =arr[j+1];arr[j+1] = tmp;flag = 0;//数组进行了排序}} if(flag == 1){break;} }}
int main()
{int arr[] = {9,8,7,6,5,4,3,2,1 };//把数组排成升序int sz = sizeof(arr)/sizeof(arr[0]);bubble_sort(arr,sz);int i = 0;for(i=0;i<sz;i++){printf("%d",arr[i]};}return 0;
}
3、库函数qsort
使用快速排序的思想实现的一个排序函数。
qsort可以排序任何类型的数据
void qsort(void* base,//你要排序的数据的起始位置size_t num,//待排序的数据元素的个数size_t width,//待排序的数据元素的大小(单位是字节)int(* cmp)(const void* e1,const void* e2)//函数指针-比较函数);
cmp(sqort中的比较函数,需要我们自定义)
int(* cmp)(const void* e1,const void* e2)中的e1,e2就是我们要比较数据的地址。
在这个比较函数中我们实现不同类型的元素比较
void*是无具体类型的指针,可以接收任何类型的地址
void*是无具体类型的指针,所以不能解引用操作,也不能+-整数
当比较函数返回的是大于0的数字,那么两组数据就会进行交换。
进行整型数据的比较, 这是进行升序排列
int cmp_int(const void* e1,const void* e2)
{return (*(int*)e1 - *(int*)e2);
}
整形的升序排列
通过qsort来将数组进行升序排序
//比较两个整形元素
//e1指向一个整形
//e2指向另外一个整形
#include <stdio.h>
#include <stdlib.h>
int cmp_int(const void* e1,const void* e2)
{return (*(int*)e1 - *(int*)e2);
}
int main()
{int arr[] = {9,8,7,6,5,4,3,2,1};int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr,sz,sizeof(arr[0]),cmp_int);int i = 0;for(i=0;i<sz;i++){printf("%d ",arr[i]);} return 0;
}
cmp_int就是回调函数
整形的倒序排列
当我们需要进行降序排列,只要将e2和e1的顺序倒过来就可以实现
int cmp_int(const void* e1,const void* e2)
{return (*(int*)e2 - *(int*)e1);
}
结构体的排序
结构体按照名字(char类型)排序
char类型的数据不能够直接比较,我们用到strcmp进行比较,
库函数strcmp
头文件<string.h>
int strcmp( const char *string1, const char *string2 );
如果string1小于string2,就会返回小于0的数
如果string1等于string2,就会返回0
如果string1大于string2,就会返回大于0的数
#include<stdlib.h>
#include<string.h>
struct Stu
{char name[20];int age;
};
int cmp_stu_by_name(const void* e1,const void* e2)
{return strcmp(((struct Stu*)e1)->name,((struct Stu*)e2)->name);
}
int main()
{struct Stu s[] = {{"zhangsan",15},{"lisi",30},{"wangwu",25}};int sz = sizeof(s) / sizeof(s[0]);qsort(s,sz,sizeof(s[0]),cmp_stu_by_name);return 0;
}
cmp_stu_by_name就是回调函数
结构体按照年龄(int类型)排序
#include<stdlib.h>
#include<string.h>
struct Stu
{char name[20];int age;
};
int cmp_stu_by_age(const void*e1,constvoid* e2)
{return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
int main()
{struct Stu s[] = {{"zhangsan",15},{"lisi",30},{"wangwu",25}};int sz = sizeof(s) / sizeof(s[0]);qsort(s,sz,sizeof(s[0]),cmp_stu_by_age);return 0;
}
库函数qsort的模拟实现(bubble_sort)
如何实现qsort函数?库函数qsort的设计原理是什么?
创建自定义函数实现库函数qsort的功能。
基于qsort实现原理,实现将整形数组升序排列
设计自定义函数bubble_sort,等同于库函数qsort
void bubble_sort(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
base:数据的起始位置,首元素的地址
sz: 数据元素的个数,比较数组的话,就是数组中元素的个数
width:待排序的数据元素的大小(单位是字节),比较整形数组的话,就是4个字节,数组元素占内存的大小
cmp:自定义的比较函数。
关于bubble_sort的设计细节
这是我们对解决整形数组升序排列问题,也就是冒泡排序,原来的的bubble_sort.
但是我们现在要设计的bubble_sort,需要与qsort有相同的功能(排序任何类型的数据)
void bubble_sort(int arr[],int sz)
{int i=0;//趟数for(i=0;i<sz-1;i++){int flag = 1;//假设数组是排好序的。//一趟冒泡排序的过程int j = 0;for(j=0;j<sz-1-i;j++){if(arr[j]>arr[j+1]){int tmp = arr[j];arr[j] =arr[j+1];arr[j+1] = tmp;flag = 0;//数组进行了排序}} if(flag == 1){break;} }}
1.
void bubble_sort(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
参数void类型可以接收任何类型的数据
2.
判断大小,
原来:数组元素比较大小
现在:比较一种无知类型元素大小,通过比较函数(cmp)来比较,由于我们不知道要比较的元素类型是什么,但是我们要找到每个元素的地址,就通过(char*)base + j * width,
第一个元素的地址就是首元素的地址,
第二个元素的地址就是首元素的地址加上一个元素的字节
width:待排序的数据元素的大小(单位是字节)
在bubble_sort中,cmp((char*)base + j * width, (char*)base + (j + 1) * width)
3.
自定义函数(cmp)的实现,已知我们要比较的是整形元素的大小,和库函数qsort解决整形的升序排列一样
int cmp_int(const void* e1, const void* e2)
{return *(int*)e1 - *(int*)e2;
}
4.
交换元素
cmp_int的功能
当比较函数返回的是大于0的数字,那么两组数据就会进行交换。
进行整型数据的比较, 这是进行升序排列
在bubble_sort中,当cmp判断>0时
if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
进行交换
交换函数
我们要找到各个元素我们才能进行比较,所以和cmp函数的实现类似,
我们要传递的参数
Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
找到了各个元素的地址,也知道元素的大小(字节),就可以进行比较,
一个一个字节进行比较,
Swap函数实现:
void Swap(char* buf1, char* buf2, int width)
{int i = 0;for (i = 0; i < width; i++){char tmp = *buf1;*buf1 = *buf2;*buf2 = tmp;buf1++;buf2++;}
}
5.
为了函数的高效性,我们把原来的flag的设计保留。
也就是int flag = 1;(假设数组已经排列好)
如果在这一趟的冒泡排序的过程中,数字进行了交换,就把flag的值改为0;
没有数字进行交换,那么flag的值还是1,就可以直接跳出循环;
呈现bubble_sort函数的整体代码:
#include<stdio.h>
void Swap(char* buf1, char* buf2, int width)
{int i = 0;for (i = 0; i < width; i++){char tmp = *buf1;*buf1 = *buf2;*buf2 = tmp;buf1++;buf2++;}
}
int cmp_int(const void* e1, const void* e2)
{return *(int*)e1 - *(int*)e2;
}
void bubble_sort(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
{int i = 0;//趟数for (i = 0; i < sz - 1; i++){int flag = 1;//假设数组是排好序//一趟冒泡排序的过程int j = 0;for (j = 0; j < sz - 1 - i; j++){if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0){//交换Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);flag = 0;}}if (flag == 1){break;}}
}
int main()
{int arr[] = { 9,8,7,6,5,4,3,2,1,0 };//0 1 2 3 4 5 6 7 8 9//把数组排成升序int sz = sizeof(arr) / sizeof(arr[0]);//bubble_sort(arr, sz);bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);int i = 0;for (i = 0; i < sz; i++){printf("%d ", arr[i]);}
}

bubble_sort的结构体排序
前面有完整的bubble_sort的实现,这里就不把bubble_sort写上了
#include<string.h>
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;
}
int cmp_stu_by_name(const void* e1, const void* e2)
{return strcmp(((struct Stu*)e1)->name , ((struct Stu*)e2)->name);
}
void test()
{struct Stu s[] = { {"zhangsan", 15}, {"lisi", 30}, {"wangwu", 25} };int sz = sizeof(s) / sizeof(s[0]);bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_name);//bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_age);
}
int main()
{test();return 0;
}
age:

name:

相关文章:
C语言进阶之冒泡排序
✨ 猪巴戒:个人主页✨ 所属专栏:《C语言进阶》 🎈跟着猪巴戒,一起学习C语言🎈 目录 前情回顾 1、回调函数 2、冒泡排序 3、库函数qsort cmp(sqort中的比较函数,需要我们自定义) …...
零代码编程:用ChatGPT将SRT字幕文件批量转为Word文本文档
一个文件夹中有多个srt视频字幕文件,srt文件里面有很多时间轴: 现在想将其批量转为word文档,去掉里面与字符无关的时间轴,在ChatGPT中输入提示词: 你是一个Python编程专家,要完成一个批量将SRT字幕文件转为…...
力扣刷题第二十六天--二叉树
前言 昨天看总决赛,差距太大,看的没意思,真的是一点变通没有啊。难受,没有写题的状态了。大概率是最后一次看比赛了,青春已复过,白日忽相催。召唤师要和生活对线了。英雄们的语音,台词…...
电脑显示msvcp140_1.dll丢失的5个常用解决方法,亲测可修复
常见于计算机操作中的"msvcp140_1.dll丢失"错误警示,往往令部分应用程序无法正常启动。为了解决这个问题,我们需要采取一些措施来修复丢失的文件。本文将介绍6个解决msvcp140_1.dll丢失的方法,帮助大家快速恢复计算机的正常运行。 …...
hive sql 行列转换 开窗函数 炸裂函数
hive sql 行列转换 开窗函数 炸裂函数 准备原始数据集 学生表 student.csv 讲师表 teacher.csv 课程表 course.csv 分数表 score.csv 员工表 emp.csv 雇员表 employee.csv 电影表 movie.txt 学生表 student.csv 001,彭于晏,1995-05-16,男 002,胡歌,1994-03-20,男 003,周杰伦,…...
Continuity” of stochastic integral wrt Brownian motion
See https://imathworks.com/math/math-continuity-of-stochastic-integral-wrt-brownian-motion/...
设置 wsl 桥接模式
一、环境要求 Win10/Win11 专业版,并已安装 Hyper-V 二、具体步骤 打开 Hyper-V 管理器 创建虚拟交换机 WSL Bridge 修改wsl配置文件 .wslconfig .wslconfig 文件所在路径如下: C:\Users\<UserName>\.wslconfig若 .wslconfig 文件不存在&am…...
[uni-app] uni.showToast 一闪而过问题/设定时间无效/1秒即逝
toast一闪就消失 1.猜测频繁点击导致 – 排除 2.猜测再定时器内导致-- 排除 3.和封装的接口调用一起导致 - 是改原因 深挖发现: axios封装中, 对loading/hindloading进行了配置, 看来是 showToast 与 loading等冲突导致的 wx.hideLoading(Object object) 解决办法 再封装的…...
7、信息打点——资产泄露CMS识别Git监控SVNDS_Store备份
知识点: CMS指纹识别、源码获取方式习惯&配置&特征等获取方式托管资产平台资源搜索监控 如何获取源码 直接识别CMS,根据CMS获取网站源码。CMS直接识别工具:云悉指纹识别平台。识别不了CMS,则通过以下方式获取源码&…...
【运维篇】5.6 Redis server 主从复制配置
文章目录 0. 前言1. 配置方式步骤1: 准备硬件和网络步骤2: 安装Redis步骤3: 配置主服务器的Redis步骤4: 配置从服务器的Redis步骤5: 测试复制功能步骤6: 监控复制状态 2. 参考文档 0. 前言 在Redis运维篇的第5.6章节中,将讨论Redis服务器的主从复制配置。在开始之前…...
Hive语法,函数--学习笔记
1,排序处理 1.1cluster by排序 ,在Hive中使用order by排序时是全表扫描,且仅使用一个Reduce完成。 在海量数据待排序查询处理时,可以采用【先分桶再排序】的策略提升效率。此时, 就可以使用cluster by语法。 cluster…...
LeetCode热题100——动态规划
动态规划 1. 爬楼梯2. 杨辉三角3. 打家劫舍 1. 爬楼梯 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? // 题解:每次都有两种选择,1或者2 int climbStairs(int n) {if (n …...
初识树(c语言)
树 定义:树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合。 有一个特殊的结点,称为根结点,根节点没有前驱结点 除根节点外,其余结点被分成M(M>0)个互不相交…...
听GPT 讲Rust源代码--src/librustdoc(2)
题图来自 Chromium项目将支持Rust编程语言[1] File: rust/src/librustdoc/html/render/search_index.rs 在Rust源代码中,rust/src/librustdoc/html/render/search_index.rs文件的作用是生成搜索索引,用于在Rust文档页面上进行关键字搜索。该文件实现了一…...
多目标应用:基于非支配排序的蜣螂优化算法NSDBO求解微电网多目标优化调度(MATLAB)
一、微网系统运行优化模型 微电网优化模型介绍: 微电网多目标优化调度模型简介_IT猿手的博客-CSDN博客 二、基于非支配排序的蜣螂优化算法NSDBO 基于非支配排序的蜣螂优化算法NSDBO简介: https://blog.csdn.net/weixin46204734/article/details/128…...
泉盛UV-K5/K6全功能中文固件
https://github.com/wu58430/uv-k5-firmware-chinese/releases 主要功能: 中文菜单 许多来自 OneOfEleven 的模块: AM 修复,显著提高接收质量长按按钮执行 F 操作的功能复制快速扫描菜单中的频道名称编辑频道名称 频率显示选项扫描列表分配…...
基于JPBC的无证书聚合签名方案实现
基于JPBC的无证书聚合签名方案实现 摘要 一开始签名方案是基于PKI的,无证书签名起源于 基于身份密码体制, 2009 年第一篇无证书签名方案1被提出,随后出现了一些列方案2,3;包括无配对的无证书聚合签名方案4,更多内容参考文献5. 暂时没有看见…...
FreeRTOS内存管理分析
目录 heap_1.c内存管理算法 heap_2.c内存管理算法 heap_3.c内存管理算法 heap_4.c内存管理算法 heap_5.c内存管理算法 内存管理对应用程序和操作系统来说非常重要,而内存对于嵌入式系统来说是寸土寸金的资源,FreeRTOS操作系统将内核与内存管理分开实…...
hashMap索引原理
平日里面经常使用map这种数据结构,令人称奇的是他的访问速度为什么那么快?为什么可以通过key以接近O(1)的速度查找? 一、基础数据结构特点分析 1.1数组 查找的时间复杂度为O(1) 插入时间复杂度为O(n) 1.2链表 查找的时间复杂度为O(n) 插…...
qcow2、raw、vmdk等镜像格式工具
如果没有qemu,可以从这里下载安装:https://qemu.weilnetz.de/w64/...
从零构建私有化智能语音助手:基于ESP32与开源后端的完整实践指南
1. 项目概述:从零构建你的智能语音助手后端如果你手头有一块ESP32开发板,并且已经体验过类似“小智”这样的智能语音助手项目,但总觉得依赖别人的云端服务不够自由、不够安全,或者想深度定制功能,那么今天这个内容就是…...
Cursor AI编程助手深度思考规则:从思维链到工程化实践
1. 项目概述:为AI编程助手注入深度思考的灵魂如果你和我一样,日常重度依赖Cursor这类AI编程助手来写代码、重构项目或者排查问题,那你肯定也遇到过类似的困扰:AI给出的答案有时看起来“很对”,但仔细一琢磨,…...
如何使用AI从文档中准确提取所有内容
如何使用AI从文档中准确提取所有内容 作者:AI拉呱(Errol Yan) 定位:AI领域深度内容与实战方法分享 TL;DR 文档解析器在处理现实文档中常见的复杂布局时面临困难,例如具有合并单元格的表格、跨页符号和错位的文本。此外,大量信息存在于图表或图形中,需要准确提取。本文将…...
CR52168BSJ-36W橱柜灯电源方案,输入170-264V输出12V,2.6A,低待机功耗,效率高。
CR52168BSJ-36W橱柜灯电源方案,输入170-264V输出12V,2.6A,低待机功耗,效率高。 在现在家庭装修中,橱柜灯、衣柜灯和镜子灯等都是家具照明的热门产品,但市场上种类选择多样化,竞争激烈。因而内置恒压恒流,高…...
周红伟SEO能力加强和客户转化的能力点
🧬 周红伟老师背景速览维度内容身份定位大数据与人工智能实战专家 / 企业培训讲师核心背书法国科学院数据算法博士、前阿里AI专家、前马上消费风控负责人、前猪八戒大数据科学家主要平台CSDN博客(AI周红伟)、讲师宝、企业管理咨询网、京城名师…...
【无人机通信】无人机自主巡航+5G 通信质量监测MATLAB仿真平台,模拟无人机飞 4 个基站,记录信号强度,带 3D 可视化、电子围栏、自动起降、自动返航
✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、程序设计科研仿真。 🍎完整代码获取 定制创新 论文复现点击:Matlab科研工作室 👇 关注我领取海量matlab电子书和数学建模资料 &…...
小米Agent岗二面:RAG知识库文档更新,不重建全量就搞不定?
👔面试官:你们 RAG 知识库上线之后,文档更新了怎么办?总不能每次改个文档就把整个知识库重建一遍吧。 🙋♂️我:可以直接找到变了的那个 chunk,更新它的向量就行了。 👔面试官&a…...
FPGA流水线FFT IP核生成器:dblclockfft配置与实战指南
1. 项目概述:一个高度可配置的流水线FFT IP核生成器最近在折腾一个FPGA上的信号处理项目,需要用到快速傅里叶变换(FFT)这个核心算法。大家都知道,FFT是数字信号处理的基石,从音频处理到通信解调,…...
使用gradient-cursor库为网页添加渐变动态光标效果
1. 项目概述:为你的网页注入灵魂光标 在网页设计的细节里,鼠标光标常常是被忽视的一环。默认的白色箭头或小手图标,虽然功能明确,但千篇一律,缺乏个性。你是否想过,当用户在你的个人作品集、创意网站或交互…...
LLM课程全解析:从基础原理到微调部署的实战指南
1. 课程概览与学习路径设计如果你对大型语言模型(LLM)感兴趣,想从“会用ChatGPT”进阶到“懂LLM原理”甚至“动手微调自己的模型”,那么你很可能已经淹没在海量的教程、论文和开源项目里了。信息过载,路径模糊…...

✨ 猪巴戒:个人主页✨