c语言进阶部分详解(经典回调函数qsort()详解及模拟实现)
大家好!上篇文章(c语言进阶部分详解(指针进阶2)_总之就是非常唔姆的博客-CSDN博客)我已经对回调函数进行了初步的讲解和一个简单的使用事例,鉴于篇幅有限没有进行更加详细的解释,今天便来补上。
目录
一.回调函数的含义
二.qsort()函数
1.讲解
2.实例
三.利用冒泡排序来模拟qsort()
1.main函数
2.bubble_qsort()
3.cmp()
4.swap()
总代码:
一.回调函数的含义
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应
二.qsort()函数
1.讲解
根据cplusplus网址给出的:
翻译这就来了:
qsort函数是C语言标准库中的一个函数,用于对数组进行快速排序。它的完整声明如下:
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
qsort函数接受四个参数:
base
:指向要排序数组的首元素的指针。nmemb
:表示数组中元素的个数。size
:表示每个元素的大小(以字节为单位)。compar
:指向一个用于比较两个元素的回调函数的指针回调函数
compar
用于比较两个元素的大小关系。它接受两个参数,分别是指向要比较的元素的指针。回调函数应该返回一个整数值,表示两个元素的大小关系。如果返回负数,则表示第一个元素小于第二个元素;如果返回正数,则表示第一个元素大于第二个元素;如果返回零,则表示两个元素相等。
一般这个回调函数是需要我们自己来写的:
//升序排序 针对整型的排序:
int compare (const void * a, const void * b){return ( *(int*)a - *(int*)b );}//降序排列int compare (const void * a, const void * b){return ( *(int*)b - *(int*)a );}
2.实例
对整型数组排序
int compare(const void *a, const void *b) {return (*(int*)a - *(int*)b);
}int main() {int arr[] = {5, 3, 8, 2, 1, 4};int size = sizeof(arr) / sizeof(arr[0]);qsort(arr, size, sizeof(int), compare);for (int i = 0; i < size; i++) {printf("%d ", arr[i]);}return 0;
}
同时我们也可以对其他数据类型进行排序,下面便是对结构体进行排序
struct Student{char name[20];int score;
} ;int compare(const void* a, const void* b) {return ((struct Student*)a)->score - ((struct Student*)b)->score;
}int main() {struct Student students[] = {{"Alice", 85},{"Bob", 92},{"Charlie", 78},{"David", 80},{"Eva", 88}};int size = sizeof(students) / sizeof(students[0]);qsort(students, size, sizeof(struct Student), compare);printf("按照成绩排序后的学生列表:\n");for (int i = 0; i < size; i++) {printf("姓名:%s,成绩:%d\n", students[i].name, students[i].score);}return 0;
}
三.利用冒泡排序来模拟qsort()
1.main函数
这里main只是进行了最为基本的一些处理,接下来进入bubble_qsort()函数
int main()
{int arr[] = { 10,9,8,7,6,5,4,3,2,1 }; //定义整型数组并初始化int sz = sizeof(arr) / sizeof(arr[0]); //计算数组长度int i = 0;bubble_sort(arr, sz, sizeof(arr[0]), cmp); //模拟qsort函数实现冒泡排序for (i = 0; i < sz; i++) {printf("%d ", arr[i]); //排序完后对数组进行打印,验证排序是否成功}
}
2.bubble_qsort()
冒泡排序函数bubble_sort
,它接受四个参数:要排序的数组arr
、数组的长度sz
、每个元素的大小width
和比较函数cmp
。冒泡排序函数使用两层循环来实现冒泡排序的过程。外层循环控制冒泡排序的趟数,内层循环遍历每一趟需要比较的元素对。在每一趟冒泡排序中,如果比较函数返回的结果大于0,则交换相邻的两个元素,将较大的元素向后移动
- 我们可以看到形参的类型是 void* arr ,此类型可接受任何类型指针
- 我们会把需要比较的参数传递给比较函数cmp():
第一个是:(char*)arr + (j * width) 我们先把void*强转为char*,再加上j*width,width是每个元素的大小,j*width就是需要加上的字节数,所以(char*)arr + (j * width)就是第j个元素的第一个字节的地址
void bubble_sort(void* arr, int sz, int width, int(*cmp)(void* e1, void* e2))
{int i = 0;int j = 0;for (i = 0; i < sz - 1; i++){//冒泡排序趟数for (j = 0; j < sz - 1 - i; j++) //每一趟冒泡排序{if (cmp((char*)arr + (j * width), (char*)arr + (j + 1) * width)>0){//符合条件进行交换swap((char*)arr + (j * width), (char*)arr + (j + 1) * width,width);}}}
}
3.cmp()
虽然传递过来的是char*类型的指针但是我们经过强制转换之后访问的还是四个字节
int cmp(void* e1, void* e2) //所选择的比较方法
{return *((int*)e1) - *((int*)e2);
}
4.swap()
函数的参数包括两个指针p1
和p2
,分别指向需要交换的两个元素,以及一个整数width
,表示每个元素的大小。
在函数内部,我们使用一个临时变量t
来保存交换过程中的临时值。然后使用一个循环,遍历每个字节,将两个元素逐个字节地交换位置
void swap(char* p1, char* p2, int width) //实现数组元素的交换
{int t = 0;int i = 0;for (i = 0; i < width; i++){t = *p1;*p1 = *p2;*p2 = t;p1++;p2++;}
}
原码:
#include<stdio.h>//仿qsort函数重写冒泡排序
int cmp(void* e1, void* e2) //所选择的比较方法
{return *((int*)e1) - *((int*)e2);
}
void swap(char* p1, char* p2, int width) //实现数组元素的交换
{int t = 0;int i = 0;for (i = 0; i < width; i++){t = *p1;*p1 = *p2;*p2 = t;p1++;p2++;}
}
void bubble_sort(void* arr, int sz, int width, int(*cmp)(void* e1, void* e2))
{int i = 0;int j = 0;for (i = 0; i < sz - 1; i++){//冒泡排序趟数for (j = 0; j < sz - 1 - i; j++) //每一趟冒泡排序{if (cmp((char*)arr + (j * width), (char*)arr + (j + 1) * width)>0){//符合条件进行交换swap((char*)arr + (j * width), (char*)arr + (j + 1) * width,width);}}}
}
int main()
{int arr[] = { 10,9,8,7,6,5,4,3,2,1 }; //定义整型数组并初始化int sz = sizeof(arr) / sizeof(arr[0]); //计算数组长度int i = 0;bubble_sort(arr, sz, sizeof(arr[0]), cmp); //模拟qsort函数实现冒泡排序for (i = 0; i < sz; i++) {printf("%d ", arr[i]); //排序完后对数组进行打印,验证排序是否成功}
}
当然,此模拟方法依然有很多缺点:
- 冒泡排序虽然简单,但是效率低
- 逐个字节地交换位置适用于任意类型的元素,不受元素类型和大小的限制。但是,它的缺点是效率较低
以后希望我在学到新知识后能进行相应改善。
相关文章:
c语言进阶部分详解(经典回调函数qsort()详解及模拟实现)
大家好!上篇文章(c语言进阶部分详解(指针进阶2)_总之就是非常唔姆的博客-CSDN博客)我已经对回调函数进行了初步的讲解和一个简单的使用事例,鉴于篇幅有限没有进行更加详细的解释,今天便来补上。…...
win下 lvgl模拟器codeblocks配置
链接: 官方lvgl的codeblocks官方例子 下载慢的话,可能需要点工具。 需要下载的东西 https://github.com/lvgl/lv_port_win_codeblocks https://github.com/lvgl/lv_drivers/tree/4f98fddd2522b2bd661aeec3ba0caede0e56f96b https://github.com/lvgl/lvgl/tree/7a23…...
Quartus出租车计价器VHDL计费器
名称:出租车计价器VHDL计费器 软件:Quartus 语言:VHDL 要求: 启动键start表示汽车启动,起步价7元,同时路程开始计数,停止键stop表示熄火,车费和路程均为0,当暂停键pa…...
浅谈单元测试:测试和自动化中的利用
【软件测试面试突击班】如何逼自己一周刷完软件测试八股文教程,刷完面试就稳了,你也可以当高薪软件测试工程师(自动化测试) 浅谈单元测试是一件棘手的事情。我很确定测试人员在某个时候会抱怨开发人员没有正确地进行单元测试&…...
深度详解Java序列化
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...
Linux下的网络编程——B/S模型HTTP(四)
前言: HTTP是基于B/S架构进行通信的,而HTTP的服务器端实现程序有httpd、nginx等,其客户端的实现程序主要是Web浏览器,例如Firefox、Internet Explorer、Google Chrome、Safari、Opera等,此外,客户端的命令…...
Go语言入门篇
目录 一、基础数据类型 1.1 变量的定义方式 1.2 用%T输出变量的类型 二、复合数据类型 2.1 数组 2.1.2、数组的遍历 2.1.3 数组传参 2.2. 切片slice 2.2.1. 初始化切片 2.2.2. append向切片中追加元素 2.2.3. 切片的截取 2.3. map 2.3.1. map初始化 2.3.2. 添加和…...
基于springboot+vue的青年公寓服务平台
博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…...
Spring-ImportSelector接口功能介绍
ImportSelector接口是至spring中导入内部类或者外部类的核心接口,只需要其定义的方法内返回需要创建bean的class字符串就好了,比如:当我们引入一个外部share包,我们拿到里面的Class返回出去,就能得到这个bean,是多么神…...
YOLOv5如何训练自己的数据集
文章目录 前言1、数据标注说明2、定义自己模型文件3、训练模型4、参考文献 前言 本文主要介绍如何利用YOLOv5训练自己的数据集 1、数据标注说明 以生活垃圾数据集为例子 生活垃圾数据集(YOLO版)点击这里直接下载本文生活垃圾数据集 生活垃圾数据集组成&…...
李航老师《统计学习方法》第1章阅读笔记
1.1 统计学习 统计学习的特点 统计学习:计算机基于数据构建概率统计模型并运用模型对数据进行预测与分析 现在人们提及机器学习时,往往指统计机器学习,所以可以认为本书介绍的是机器学习方法 统计学习的对象 统计学习研究的对象是数据(data)…...
基于微信小程序的背单词学习激励系统设计与实现(源码+lw+部署文档+讲解等)
文章目录 前言用户微信端的主要功能有:管理员的主要功能有:具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding)有保障的售后福利 代码参考源码获取 前言 💗博主介绍:✌全网粉…...
VScode调试复杂C/C++项目
以前都是用的VScode调试c/cpp的单个文件的编译和执行, 但是一遇到大型项目一般就用gdb了, gdb的调试效率和VScode差距还是比较大的, 但最近发现VScode其实也能调试复杂的cpp项目, 所以记录一下. 首先明确一下几点: 首先cpp文件需要经过编译, 生成可执行文件, 然后通过运行/调…...
【Hash表】字母异位词分组-力扣 49 题
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…...
展示日志log4.properties
log4.properties 1.log4.properties 此时文件主要用于展示日志的输出的级别的信息。 # Set root category priority to INFO and its only appender to CONSOLE. #log4j.rootCategoryINFO, CONSOLE debug info warn error fatal log4j.rootCategoryinfo, CONSO…...
基于PLE结合卡尔曼滤波的RSSI定位算法matlab仿真
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022a 3.部分核心程序 ............................................................... for Num_xb Num_xb2Num_…...
uniapp项目实践总结(十九)版本更新和热更新实现方法
导语:当一个 APP 应用开发完成以后,就要上架应用商店,但有时候修改一些小问题或者推出一些活动,又不想频繁地提交应用商店审核,那么就可以使用应用内更新功能来进行应用的版本升级更新或热更新,下面就介绍一下实现的方法。 目录 准备工作原理分析实战演练案例展示准备工作…...
一起学数据结构(8)——二叉树中堆的代码实现
在上篇文章中提到,提到了二叉树中一种特殊的结构——完全二叉树。对于完全二叉树,在存储时,适合使用顺序存储。对于非完全二叉树,适合用链式存储。本文将给出完全二叉树的顺序结构以及相关的代码实现: 1. 二叉树的结构…...
Linux环境变量配置说明(配置jdk为例-摘录自尚硅谷技术文档)
配置环境变量的不同方法 Linux的环境变量可在多个文件中配置,如/etc/profile,/etc/profile.d/.sh,~/.bashrc,~/.bash_profile等,下面说明上述几个文件之间的关系和区别。 bash的运行模式可分为login shell和non-login shell。 例…...
idea常用插件笔记
文章目录 Free Mybatis Toollombok插件idea插件导出导入 idea提供了很多好用的插件,之前都装了的,但是换了下电脑,什么都没了,所以记录下方便以后用。 Free Mybatis Tool mybatis跳转插件,再也不用费力的找xml了。 l…...
搜索二叉树【C++】
文章目录 二叉搜索树二叉搜索树的模拟实现构造函数拷贝构造函数赋值运算符重载函数析构函数Insert循环递归 Erase循环递归 Find循环递归 二叉搜索树的应用K模型KV模型 完整代码普通版本递归版本 二叉搜索树 二叉搜索树又称为二叉排序树,它或者是一棵空树࿰…...
华为云云耀云服务器L实例评测|认识redis未授权访问漏洞 漏洞的部分复现 设置连接密码 redis其他命令学习
前言 最近华为云云耀云服务器L实例上新,也搞了一台来玩,期间遇到过MySQL数据库被攻击的情况,数据丢失,还好我有几份备份,没有造成太大的损失。昨天收到华为云的邮箱提醒,我的redis数据库没有设置密码&…...
快速安装NGINX
快速安装NGINX #安装依赖包 yum -y install gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel#下载NGINX curl -O https://nginx.org/download/nginx-1.21.6.tar.gz#解压NGINX tar -zxvf nginx-1.21.6.tar.gz cd nginx-1.21.6.tar.gz#配置 ./configure --prefix/…...
一台电脑远程内网的另外一台电脑,禁止远程的电脑连接外网,只允许内网连接
一台电脑远程内网的另外一台电脑,禁止远程的电脑连接外网,只允许内网连接 1.找到右下角网卡图标,右键图标选择“打开网络和共享中心”。 3、点击“更改适配器设置”。 4、右键正在使用的网卡“本地连接”打开属性 5、找到“internet协…...
山西电力市场日前价格预测【2023-09-24】
日前价格预测 预测说明: 如上图所示,预测明日(2023-09-24)山西电力市场全天平均日前电价为496.09元/MWh。其中,最高日前电价为705.54元/MWh,预计出现在14: 30。最低日前电价为333.70元/MWh,预计…...
MQ---第二篇
系列文章目录 文章目录 系列文章目录一、RabbitMQ事务消息二、RabbitMQ死信队列、延时队列一、RabbitMQ事务消息 通过对信道的设置实现 channel.txSelect();通知服务器开启事务模式;服务端会返回Tx.Select-Okchannel.basicPublish;发送消息,可以是多条,可以是消费消息提交…...
C++ 创建文件并写入内容
文章目录 1.问题2.filesystem3.示例参考文献 1.问题 C 如何向指定路径的文件写入内容呢? 这里有几点要求: 如果目录不存在需要自动创建。如果文件不存在需要自动创建。以覆盖的方式写入内容。 2.filesystem C17 带来了一个新的库:filesy…...
微信小程序rich-text里面写多行溢出显示省略号在ios中不显示的问题
问题:微信小程序rich-text里面写多行溢出显示省略号在ios中不显示的问题 解决方法:需要给一个默认的div标签,在div写行内样式 overflow : hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-o…...
解决Win11/10中Edge浏览器页面加载不出来、打不开问题|有网但是打不开,加载不了
问题症状 edge浏览器打不开,有网络能正常上网,但是edge浏览器无法浏览。网络质量很高,但是页面就是加载不出来,详情如下: (我是在科学上网后造成这样子的原因,现在将我的方法分享一下ÿ…...
【DRAM存储器五】DRAM存储器的架构演进-part2
👉个人主页:highman110 👉作者简介:一名硬件工程师,持续学习,不断记录,保持思考,输出干货内容 参考书籍:《Memory Systems - Cache, DRAM, Disk》 目录 以提升吞吐…...
双井做网站的公司/搜索推广竞价托管哪家好
给div设置overflow-y:scroll;内容滚动时,移动端会出现卡顿现象, -webkit-overflow-scrolling: touch;可以加速设备,WebKit私有的属性“-webkit-overflow-scrolling: touch”(允许独立的滚动区域和触摸回弹) <!DOCTY…...
做游戏排行榜的网站模板/怎么在网上销售
本文实例讲述了Python实现的拟合二元一次函数功能。分享给大家供大家参考,具体如下:背景:使用scipy拟合一元二次函数。参考:HYRY Studio-《用Python做科学计算》代码:# -*- coding:utf-8 -*-#! python3import numpy as…...
wordpress默认登陆地址/余姚网站如何进行优化
【单选题】决定微机性能的主要是().【单选题】急、慢性骨髓炎患者最好选用:【单选题】计算机中对数据进行加工与处理的部件,通常称为().【单选题】西米替丁治疗十二指肠溃疡的机制为:【单选题】计算机系统的内部总线,主要可以分为()、数据总线和地址总线.【单选题】计算机的软件…...
冷库网站建设毕业论文/广州权威发布
实战需求 vlookup如何实现三变量查找,三个条件字段查询数据? 文章目录 《示例 1 – 查找 Brad 的数学分数》《示例 2 – 双向查找》《示例 3 – 使用下拉列表作为查找值》《示例 4 – 三向查找》什么是三向查找? 在示例 2 中,我们使用了一个查找表,其中包含不同科目学…...
wordpress使用技巧/网销是什么工作好做吗
据悉,2022国际人工智能大会SAIL奖TOP30榜单近来正式出炉。作为国际人工智能大会的最高奖项,SAIL奖(Superior AI Leader,卓越人工智能引领者)坚持“追求卓越、引领未来”的理念,从全球规模发掘在人工智能范畴…...
网站的发展前景/旺道seo优化
Win异常: 除了chrome浏览器外,所有安装的软件都连不上网参考文章: (1)Win异常: 除了chrome浏览器外,所有安装的软件都连不上网 (2)https://www.cnblogs.com/mylove-pro…...