库函数qsort的使用及利用冒泡排序模拟实现qsort

请添加图片描述

文章目录

  • 🚀前言
  • 🚀void*类型指针
  • 🚀库函数qsort的使用
  • 🚀利用冒泡排序实现库函数qsort()

🚀前言

今天阿辉将为大家介绍库函数qsort的使用,还包括利用冒泡排序模拟实现qsort以及void*类型的指针,关注阿辉不迷路哦 😘 ,内容干货满满😋,接下来就跟着阿辉一起学习吧👊

🚀void*类型指针

铁子们都知道一种指针只能接收同类型的地址,否则编译器就会报错,那有没有可以接收任意类型地址的指针呢?答案是有的,就是void*类型的指针
例如:

int a = 10;
char c = 'c';
float f = 1.2f;
void*p = NULL;
p = &a;
p = &c;
p = &f;

void*类型指针可以接受任何类型的变量的地址,它就像一个“垃圾桶”一样,任何的地址都可以往里面“扔”,所以他也被称为泛型指针,但是void*类型的指针也有它的局限性,因为void*无具体类型,SOvoid*类型的指针无法进行指针运算也无法进行解引用操作
既然如此,那void*类型的指针有何应用场景,铁子们别急我们接着看👇

🚀库函数qsort的使用

铁子们,咱们今天的重点来了,qsort()是C语言标准库提供的专门用来给数组排序的一个库函数
qsort()函数的声明

void qsort(void* base, size_t num, size_t size, 
	int (*compar)(const void* p1, const void* p2));
	
库函数qsort()有四个参数,	不返回
void* base 这个参数是指向数组首元素的指针
size_t num这个参数指的是数组中的元素个数
size_t size这个参数是数组中每个元素的大小,以字节为单位			

对于库函数qsort()的第四个参数int (*compar)(const void* ,const void*),是一个函数指针,要使用qsort()得我们自己定义一个返回值为int类型有两个const修饰的void*类型的指针的参数,并且返回值遵循如下规则的函数:

返回值< 0 第一个参数应在第二个参数前,无需交换
返回值> 0 第二个参数应在第一个参数前,需要交换
返回值= 0 谁在前无所谓,无去交换

qsort()函数最厉害的就是它可以给任何数据排序,并且可以根据我们提供的比较函数实现升序或是降序,铁子们,我们来看看qsort()是如何使用的👇

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct Stu
{
	int age;//年龄
	char name[20];//名字
};
//以结构体Stu成员age的数字大小排升序
int StuAgecomp(const void* p1, const void* p2)
{
	return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}
//以结构体Stu成员name利用库函数strcmp()给字符串排序
int StuNamecomp(const void* p1, const void* p2)
{
	return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}
//打印函数,打印排序后内容
void print(struct Stu arr[],int size)
{
	for (int i = 0; i < size; i++)
	{
		printf("%d %s	", arr[i].age, arr[i].name);
	}
	printf("\n");
}

int main()
{
	struct Stu arr[] = { {19,"tangminghui"},{12,"tanzihao"},{30,"zenghongsen"} };
	int size = sizeof(arr[0]);//数组每个元素的大小,单位字节
	int num = sizeof(arr) / size;//数组的元素个数
	qsort(arr, num, size, StuAgecomp);
	print(arr,num);
	qsort(arr, num, size, StuNamecomp);
	print(arr,num);
	return 0;
}

输出:
在这里插入图片描述

🚀利用冒泡排序实现库函数qsort()

相信铁子们对冒泡排序并不感冒,库函数qsort()的内核其实就是快排不过阿辉实力有限暂时还不会 😭,这里阿辉利用冒泡函数给大家徒手干一个
函数名就叫UpgradeBubbleSort升级版冒泡排序 😜(以下简称冒泡函数)
我们的冒泡函数的参数与库函数qsort一样,排序就是冒泡排序的皮,主要的问题是泛型参数如何交换,这里我们定义一个交换函数swp来实现
下面是冒泡函数的具体实现,代码以及详解注释:

void UpgradeBubbleSort(void* base, size_t num, size_t size, int (*cmp)(const void* p1, const void* p2))
{
	
	for (int i = 0; i < num - 1; i++)
	{
		int flag = 0;//记录一趟下来是否发生交换
		for (int j = 0; j < num - i - 1; j++)
		{
			//数据的大小这时就有用了,找到后一个数据的起始地址
			char* p = (char*)base + j * size;//利用一个变量简化代码
			//像下面注释这么写太挫了
			//if (cmp((char*)base + j * size, (char*)base + (j + 1) * size))
			//冒泡排序的思想嘛,前一个数据和后一个比
			if (cmp(p, p + size) > 0)
			{
				swp(p, size);
				flag = 1;
			}
		}
		if (flag == 0)//没有交换说明已有序无须继续,跳出循环
		{
			break;
		}
	}
}

为什么要把void*指针强制转化为char*类型,第一点,因为方便根据数据大小找到数据,char*加减整数跳过该整数倍数的字节空间和数据大小size结合使用,就能找到数据中每个元素;第二点,因为交换数据时把对应位置上的一个字节大小空间中的内容交换,即可交换两个数据的内容
给铁子们上图:
请添加图片描述

swp函数的具体实现,代码以及详解注释:

//交换函数
void swp(char* p, int sz)
{
	//有几个字节交换几次
	//p+sz表示下一个数据
	for (int i = 0; i < sz; i++)
	{
		//俩个数据对应位置的字节交换位置,完成交换
		char tmp = *(p + i);
		*(p + i) = *(p + sz + i);
		*(p + sz + i) = tmp;
	}
}

下面是完整的升级版冒泡排序函数 😘

//交换函数
void swp(char* p, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		//俩个数据对应位置的字节交换位置,完成交换
		char tmp = *(p + i);
		*(p + i) = *(p + sz + i);
		*(p + sz + i) = tmp;
	}
}

//套着标准冒泡排序的皮
void UpgradeBubbleSort(void* base, size_t num, size_t size, int (*cmp)(const void* p1, const void* p2))
{
	
	for (int i = 0; i < num - 1; i++)
	{
		int flag = 0;//记录一趟下来是否发生交换
		for (int j = 0; j < num - i - 1; j++)
		{
			char* p = (char*)base + j * size;//利用一个变量简化代码
			//像下面注释这么写太挫了
			//if (cmp((char*)base + j * size, (char*)base + (j + 1) * size))
			if (cmp(p, p + size) > 0)
			{
				swp(p, size);
				flag = 1;
			}
		}
		if (flag == 0)//没有交换说明已有序无须继续,跳出循环
		{
			break;
		}
	}
}

到这里,阿辉今天对于C语言中库函数qsort()的分享就结束了,希望这篇博客能让大家有所收获, 如果觉得阿辉写得不错的话,记得给个赞呗,你们的支持是我创作的最大动力🌹
请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【发布小程序配置服务器域名,不配置发布之后访问就会报错request:fail url not in domain list】

小程序在本地开发的时候大家通常会在微信开发者工具中设置“不校验合法域名、web-view (业务域名)、TLS 版本以及HTTPS证书”&#xff0c;久而久之可能会忘掉这个操作&#xff0c;然后打包直接上线发布&#xff0c;结果发现访问会报错request:fail url not in domain list&…

3d家居产品虚拟三维展示提升企业的品牌竞争力

2D展示逐渐难以满足消费者需求&#xff0c;因此基于3D三维展示制作平台将产品或服务以三维形式呈现的3D三维展示更受客户和企业青睐&#xff0c;也大幅提升企业的营销推广效果。那么3D三维展示制作平台如何赋能企业营销推广呢? 首先&#xff0c;3D三维展示制作平台能够提供更加…

【数电笔记】07-基本和复合逻辑运算

目录 说明&#xff1a; 基本逻辑运算 1. 与运算 &#xff08;and gate&#xff09; 2. 或运算 &#xff08;or gate&#xff09; 3. 非运算 &#xff08;not gate &#xff09; 复合逻辑运算 1. 与非运算&#xff08;nand&#xff09; 2. 或非运算&#xff08;nor&…

分享66个在线客服JS特效,总有一款适合您

分享66个在线客服JS特效&#xff0c;总有一款适合您 66个在线客服JS特效下载 链接&#xff1a;https://pan.baidu.com/s/1VqM6ASgKRFdQ8RyzbsX4uA?pwd6666 提取码&#xff1a;6666 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0…

1、设计模式简介(7大原则,3大类)

设计模式有7个原则&#xff1a;单一职责原则、开闭原则、里氏代换原则、依赖倒转原则、接口隔离原则、合成/聚合复用原则、迪米特法则 1&#xff0e;单一职责原则 单一职责原则又称单一功能原则&#xff0c;它规定一个类只有一个职责。如果有多个职责&#xff08;功能&#x…

【Java Web学习笔记】4 - DOM文档对象模型

项目代码 https://github.com/yinhai1114/JavaWeb_LearningCode/tree/main/javascript 零、在线文档 JavaScript HTML DOM 一、HTML DOM基本介绍 1. DOM全称是Document Object Model文档对象模型 文档<---映射--->对象 2.就是把文档中的标签&#xff0c;属性&#xf…

正式发布! 加速科技ST2500A飙速赶来!

在新场景、新应用海量增长的驱动下&#xff0c;芯片测试需求也在日益多元化和快速扩展。加速科技始终致力于以客户的实际需求为导向&#xff0c;基于领先的半导体测试技术为千行百业提供全场景的测试解决方案&#xff0c;推出新一代ST2500A数模混合信号测试机。 ST2500A是基于…

通达信KDJ多周期共振指标选股公式,日周月金叉共振

KDJ多周期共振指标基于多个时间周期之间的共振关系来判断股票价格的变化趋势&#xff0c;在不同的周期上&#xff0c;KDJ会呈现出类似的波动形态&#xff0c;当这些波动形态在不同周期上发生共振时&#xff0c;可能会产生较为明显的价格趋势。 具体来说&#xff0c;多周期共振…

MySQL数据库,多表查询

多表查询&#xff0c;也称为关联查询&#xff0c;指两个或多个表一起完成查询操作。 前提条件&#xff1a;这些一起查询的表之间是有关系的&#xff08;一对一&#xff0c;一对多&#xff09;&#xff0c;它们之间一定是有关联字段&#xff0c;这个关联字段可能建立了外键&…

介绍一款在线文件格式转换工具

原因: 今天要将一个pdf格式的文件转为docx格式,结果我用破解版的WPS无法再不登录的情况下转换,所以就搜索了一款在线工具实现功能。 网站地址: Convertio — 文件转换器 使用流程: 1)选择要转换的文件 2)选择要转换的格式 3)点击转换 4)等待上传 5)等待转换 6)下载到本地

银行测试:什么是银行数据治理?如何进行有效的银行领域的实际应用?

在数字化时代&#xff0c;数据已经成为银行的重要资产&#xff0c;而数据治理则是确保数据质量、安全性和可用性的关键。那么&#xff0c;什么是银行数据治理&#xff1f;为什么我们需要银行数据治理&#xff1f;又如何进行有效的银行数据治理呢&#xff1f;又有哪些数据治理技…

互联网医院系统|互联网医院打开线上医疗新方向

我们的互联网医院系统采用了最先进的互联网开发技术&#xff0c;包括云计算、大数据、人工智能等。通过这些技术的应用&#xff0c;我们能够为患者和医疗机构提供更加高效、便捷、安全的在线医疗服务。同时&#xff0c;我们的系统还采用了最先进的网络安全技术&#xff0c;保障…

centos 7.9 二进制部署 kubernetes v1.27.7

文章目录 1. 预备条件2. 基础配置2.1 配置root远程登录2.2 配置主机名2.3 安装 ansible2.4 配置互信2.5 配置hosts文件2.6 关闭防firewalld火墙2.7 关闭 selinux2.8 关闭交换分区swap2.9 修改内核参数2.10 安装iptables2.11 开启ipvs2.12 配置limits参数2.13 配置 yum2.14 配置…

Facebook引流怎么做?写个脚本就好!

在当今的数字化时代&#xff0c;流量对于任何一个网站或应用程序来说都至关重要&#xff0c;Facebook&#xff0c;作为全球最大的社交网络平台&#xff0c;无疑是一个获取流量的绝佳场所&#xff0c;但是&#xff0c;如何有效地从Facebook引流呢?写个脚本就好了! 在本文中&am…

java开发之个微机器人的开发

简要描述&#xff1a; 初始化通讯录列表 请求URL&#xff1a; http://域名地址/initAddressList 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必选…

12月5日作业

以下是一个简单的比喻&#xff0c;将多态概念与生活中的实际情况相联系&#xff1a; 比喻&#xff1a;动物园的讲解员和动物表演 想象一下你去了一家动物园&#xff0c;看到了许多不同种类的动物&#xff0c;如狮子、大象、猴子等。现在&#xff0c;动物园里有一位讲解员&…

【Element-ui】Layout与Container组件

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Layout 布局1.1 基础布局1.2 分栏间隔1.3 混合布局1.4 分栏偏移1.5 对齐方式1.6 响应式布局1.7 el-col中的 push和pull 二、Container 布局容器2.1 Contain…

CETN03 - The Evolution of Computers

文章目录 I. IntroductionII. First Modern Digital Computer: ENIAC (1946)III. First Generation ComputerIV. Second Generation ComputerV. Third Generation ComputerVI. Fourth Generation ComputerVII. ConclusionI. 引言II. 第一台现代数字计算机&#xff1a;ENIAC&…

Mybatis 的操作(要结合上个博客一起)续集

Mybatis 是一款优秀的 持久性 框架,用于简化 JDBC 的开发 持久层 : 指的就是持久化操作的层,通常指数据访问层(dao),是用来操作数据库的 简单来说 Mybatis 是更简单完成程序和数据库交互的框架 Mybatis 的写法有两种 : 1.xml 2.注解 这两者各有利弊,后面进行总结 Mybati…

预测算法|高斯过程回归GPR算法原理及其优化实现

目前&#xff0c;常用的机器学习方法主要有支持向量机&#xff08;support vector machine&#xff0c;SVM)、反向传播神经网络&#xff08;backpropagation neural network&#xff0c;BPNN)等非概率方法以及高斯过程回归(gaussian process regression&#xff0c;GPR)等概率方…