C语言-指针进阶-qsort函数的学习与模拟实现(9.3)

news2024/11/18 10:56:29

目录

思维导图:

回调函数

qsort函数介绍

模拟实现qsort

写在最后:


思维导图:

回调函数

什么是回调函数?

回调函数是一个通过函数指针调用的函数。

将一个函数指针作为参数传递给一个函数,当这个指针被用来调用所指向函数时,

我们就将此称为回调函数。

在举例之前,我们先学习一个C语言的库函数qsort。        

qsort函数介绍

qsort函数是一个排序函数,可以帮助我们排序。

我们为什么要学习这样一个函数呢?

我们对一个整形数组进行排序:

例:

#include <stdio.h>

void print(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

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;
			}
		}
	}
}

void test()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);//冒泡排序
	print(arr, sz);//打印
}

int main()
{
	test();//分装函数
	return 0;
}

输出:

输出:0 1 2 3 4 5 6 7 8 9

但是如果我们想对一个结构体进行排序,冒泡排序就承担不了这个任务了,

(不止结构体,像浮点数啊,字符数组啊,冒泡排序都无法工作)

这个时候,我们就能使用qsort函数帮我们排序。

我们可以通过cplusplus学习一下这个函数:

通过阅读介绍,我们得知qsort的功能:

对数组中由指针指向的元素进行排序,根据每个元素字节长度,使用函数确定顺序。

此函数使用的快速排序算法通过调用指定的函数来比较元素,并将指向它们的指针作为参数。

该函数不返回任何值,但通过重新排序数组的元素来修改指向的数组的内容。

以及使用该函数需要传递的参数:

int main()
{

	void qsort(void* base, size_t num, size_t size,
		int (*compar)(const void*, const void*));
	//一个指针,两个无符号整数,一个函数指针

	return 0;
}

 这个库函数需要调用的头文件是:<stdlib.h>

以及各个参数的不同意思:

#include <stdio.h>

int main()
{

	void qsort(void* base, 
		size_t num, 
		size_t size,
		int (*compar)(const void*, const void*));
	//void*base是指向要排序的数组的第一个对象的指针,转换为void*类型
	//size_t num是数组中的元素数
	//size_t size是数组中每个元素的大小(以字节为单位)
	//int (*compar)(const void*, const void*))是指向比较两个元素的函数的指针

	return 0;
}

 这样,我们就能使用qsort函数帮助我们排序了:

例:

#include <stdio.h>
#include <stdlib.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;
	//如果e1 > e2则返回>O的数
	//如果e1 = e2则返回0
	//如果e1 < e2则返回<0的数
}

void print(struct Stu* s, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d岁\n", (&s[i])->name,(&s[i])->age);
	}
}

void test()
{
	struct Stu s[3] = { {"张三",20}, {"李四", 50}, {"王五", 33} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);//排序
	print(s, sz);//打印函数
}

int main()
{
	test();//分装函数
	return 0;
}

输出:

输出:
张三 20岁
王五 33岁
李四 50岁

利用qsort函数,我们成功给结构体排序了。

模拟实现qsort

在模拟实现qsort时,我们就要用到回调函数的思想:

例:

#include <stdio.h>
#include <stdlib.h>

int cmp_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
	//如果e1 > e2则返回>O的数
	//如果e1 = e2则返回0
	//如果e1 < e2则返回<0的数
}

//通过交换每个字节的形式,以达成交换两个数的值的目的
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++;
	}
}
                                                      //这里将cmp_int函数的指针传参
void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* e1, const void* e2))
{
	//趟数
	size_t i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		//一趟冒泡排序的过程
		size_t j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{       //这里运用了回调函数,在冒泡排序函数里调用cmp_int函数,并判断
			    //这里判断函数返回的值大于零就进入语句,排序后是升序数组
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				//交换
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}

void print(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

void test()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
	print(arr, sz);//打印函数
}

int main()
{
	test();//分装函数
	return 0;
}

输出:

输出:0 1 2 3 4 5 6 7 8 9

再用它来排序一下结构体数组也是可以的:

例:

#include <stdio.h>
#include <stdlib.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;
	//如果e1 > e2则返回>O的数
	//如果e1 = e2则返回0
	//如果e1 < e2则返回<0的数
}

//通过交换每个字节的形式,以达成交换两个数的值的目的
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++;
	}
}
                                                      //这里将cmp_int函数的指针传参
void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* e1, const void* e2))
{
	//趟数
	size_t i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		//一趟冒泡排序的过程
		size_t j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{       //这里运用了回调函数,在冒泡排序函数里调用cmp_int函数,并判断
			    //这里判断函数返回的值大于零就进入语句,排序后是升序数组
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				//交换
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}

void print(struct Stu* s, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d岁\n", (&s[i])->name,(&s[i])->age);
	}
}

void test()
{
	struct Stu s[3] = { {"张三",20}, {"李四", 50}, {"王五", 33} };
	int sz = sizeof(s) / sizeof(s[0]);
	bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_age);
	print(s, sz);//打印函数
}

int main()
{
	test();//分装函数
	return 0;
}

输出:

输出:
张三 20岁
王五 33岁
李四 50岁

写在最后:

以上就是本篇文章的内容了,感谢你的阅读。

如果喜欢本文的话,欢迎点赞和评论,写下你的见解。

如果想和我一起学习编程,不妨点个关注,我们一起学习,一同成长。

之后我还会输出更多高质量内容,欢迎收看。

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

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

相关文章

57、JDBC和连接池

目录 一、JDBC基本介绍 二、JDBC快速入门 三、JDBC API 1、ResultSet [结果集] 2、Statement 3、PreparedStatement 4、DriverManager 四、封闭JDBCUtils 五、事务 六、批处理 七、数据库连接池 4、数据库连接池种类 &#xff08;1&#xff09; c3p0数据库连接池&…

MacBookPro 遇到pip: command not found问题的解决

学习Pyhton的时候&#xff0c;需要安装第三方插件pyecharts,执行以下命令&#xff1a; pip install pyecharts总是报错 pip: command not found 我很郁闷&#xff0c;于是上网搜索尝试各种命令&#xff0c; 命令1:curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py 命…

Codeforces Round 507(div. 1) C(分类讨论,并查集)

题目链接&#xff1a; Problem - C - Codeforceshttps://codeforces.com/contest/1039/problem/C 题意&#xff1a; 计算机网络由个服务器组成&#xff0c;每个服务器有到范围内的加密秘钥。设是分配给第i台服务器的加密密钥。对服务器通过数据通信通道直接连接。由于加密算…

高性能分布式缓存Redis-第二篇章

高性能分布式缓存Redis-第二篇章一、持久化原理1.1、持久化流程&#xff08;落盘&#xff09;1.2、RDB详解1.2.1、介绍1.2.2、触发&原理1.2.3、实现1.2.4、RDB总结1.3、AOF详解1.3.1、概念1.3.2、AOF 持久化的实现1.3.2、开启1.3.4、命令追加1.3.5、文件写入和同步&#xf…

SQL 别名

通过使用 SQL&#xff0c;可以为表名称或列名称指定别名。 SQL 别名 通过使用 SQL&#xff0c;可以为表名称或列名称指定别名。 基本上&#xff0c;创建别名是为了让列名称的可读性更强。 列的 SQL 别名语法 SELECT column_name AS alias_name FROM table_name; 表的 SQL …

dubbo学习笔记4(小d课堂)

dubbo高级特性 服务分组及其配置 我们再来创建一个实现类&#xff1a; 接下来我们在xml中去进行配置&#xff1a; 现在我们去运行看是否会有错误呢&#xff1f; 我们有两个服务实现类&#xff0c;那运行的时候到底执行哪个呢&#xff1f; 但是我们想的是可以指定执行哪个实现…

设计模式——访问者模式

访问者模式一、基本思想二、结构图一、基本思想 将作用于某种数据结构中的各元素的操作分离出来封装成独立的类&#xff0c;使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作&#xff0c;为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进…

【安全硬件】Chap.7 对实体芯片采取物理手段破解;芯片IC逆向工程和拆分制造;物理上对芯片的攻击分类;侧信道攻击;Kocher针对RSA的计时攻击

【安全硬件】Chap.7 对实体芯片采取物理手段破解&#xff1b;芯片IC逆向工程和拆分制造&#xff1b;物理上对芯片的攻击分类&#xff1b;侧信道攻击&#xff1b;Kocher针对RSA的计时攻击前言1. 逆向工程Reverse Engineering逆向工程识别芯片上2输入NAND门逆向工程技术Decapulat…

CSS 实例系列

Hello 小伙伴们早上、中午、下午、晚上和深夜好&#xff0c;这里是 jsliang~本 CSS 系列文章&#xff1a;主推学以致用。结合面试题和工作实例&#xff0c;让小伙伴们深入体验 61 个工作常见的 CSS 属性和各种 CSS 知识。主推纯 CSS。尽可能使用 HTML CSS 完成学习目的&#x…

nohup命令详解

nohup命令详解一、背景说明&#xff1a;启动服务的时候&#xff0c;如果使用如下命令&#xff0c;则会在start.sh脚本所在的目录下&#xff0c;产生一个名为 nohup.out 的输出文件nohup ./startup.sh &可以看到下面这个例子&#xff0c;一开始当前目录是没有nohup.out文件的…

RocketMQ 多语言 SDK 开源贡献召集令

作者&#xff1a;艾阳坤 目前 Apache RocketMQ 5.0 SDK [ 1] 正在社区开源&#xff0c;开发与迭代也在火热进行中&#xff0c;欢迎广大社区的朋友们能够参与其中。我们欢迎任何形式的贡献&#xff0c;包括但不限于新 feature、bugfix、代码优化、生态集成、测试工作、文档撰写…

我与 CSDN 的 2022 年终总结

&#x1f482; 个人网站:【海拥】【摸鱼游戏】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 想寻找共同学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 转眼间2023年已经过去…

《后端技术面试 38 讲》学习笔记 Day 02

《后端技术面试 38 讲》学习笔记 Day 02 08丨软件设计的方法论&#xff1a;软件为什么要建模&#xff1f; 原文摘抄 所谓软件建模&#xff0c;就是为要开发的软件建造模型。模型是对客观存在的抽象&#xff0c;我们常说的数学建模&#xff0c;就是用数学公式作为模型&#xf…

flask + Pandas + echarts 使用饼状图等将二手房数据进行分析+可视化

目录 一、实战场景 二、知识点 python 基础语法 python 文件读写 pandas 数据处理 flask web 框架 echarts 图表 bootstrap jinja 模版 三、菜鸟实战 初始化 Flask 框架&#xff0c;设置路由 各行政区房屋数量柱状图分析 区域二手房房源朝向分布情况 二手房单价最…

Higress Kruise Rollout: 渐进式交付为应用发布保驾护航

作者&#xff1a;扬少 前言 在业务高速发展过程中&#xff0c;如何最大化保障功能迭代过程中业务流量无损一直是开发者比较关心的问题。通常在应用发布新功能阶段&#xff0c;我们会采用灰度发布的思想对新版本进行小流量验证&#xff0c;在符合预期之后再进行全量发布&#…

11、JS笔记-内置对象

1.内置对象 js中对象分为三种&#xff1a; 自定义对象、内置对象、浏览器对象&#xff08;js独有&#xff09; 内置对象&#xff1a; js语言自带的对象&#xff0c;供开发者使用&#xff0c;提供一些常用或基本的功能&#xff08;属性和方法&#xff09; 2.Math对象 Math中所…

【云原生】k8s配置资源管理

内容预知 1.Secret的资源配置 1.1 Secret配置的相关说明 1.2 陈述式创建Secret配置 1.3 声明式base64编码创建Secret 1.4 将secret以volume形式挂载到pod中 1.5 将Secret导入到pod中&#xff0c;充当环境变量 1.6 实战运用&#xff1a;使用secret配置免密交互拉取habor…

Qt之对话框

文章目录一、对话框的概念二、与QWidget的区别三、对话框2种显示方法四、对话框返回值的概念本节示例提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、对话框的概念 对话框是和用户简短交互的一种窗口。如&#xff1a;登录界面&#xff0c;关于界面…

知识付费图文音视频课程公众号系统开发

知识付费图文音视频课程公众号系统开发 功能特性;为你介绍音视频课程点播系统的功能特性。 微信H5;目前只支持微信公众号H5访问。 课程管理;后台可上传多个课程分类与课程。 名师推荐;后台可以维护教师列表&#xff0c;并推荐到首页显示。 分享海报;可以自定义多个分享海报。 …

Maven在项目里的具体使用方式,很简单

大家好&#xff0c;今天给大家分享一下Maven在项目里的*具体使用方式* 有关于maven这个东西&#xff0c;要知道&#xff0c;它的作用是帮助开发人员&#xff08;也就是我们&#xff09;批量的管理jar包 所谓对jar包批量管理&#xff0c;有一个很重要的点&#xff0c; 就是对于…