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

news2024/11/29 4:40:45

请添加图片描述

文章目录

  • 🚀前言
  • 🚀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()的分享就结束了,希望这篇博客能让大家有所收获, 如果觉得阿辉写得不错的话,记得给个赞呗,你们的支持是我创作的最大动力🌹
请添加图片描述

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

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

相关文章

云祺副本容灾机制讲解

副本&#xff0c;顾名思义就是一份数据的拷贝。 在系统中&#xff0c;将数据的目的分为了三种&#xff1a;备份、副本和归档。 其中备份数据&#xff0c;通常是存放在备份系统本地&#xff0c;或数据中心本地&#xff1b;副本数据通过是存放在异地的备份系统中&#xff0c;或…

【C语言】【堆排序实现TOPK问题】写一个堆排序,并且在一百万个数中找出最大的前K个

1.堆排序的实现&#xff1a; 如果要升序输出&#xff0c;则实现大堆 如果要降序输出&#xff0c;则实现小堆 逻辑&#xff1a;&#xff08;升序输出&#xff09; 将堆顶的元素和最后一个元素交换位置&#xff0c;此时左子树和右子树分别仍是大堆的顺序&#xff0c;交换位置后…

车企数据治理实践案例,实现数据生产、消费的闭环链路 | 数字化标杆

随着业务飞速发展&#xff0c;某汽车制造企业业务系统数量、复杂度和数据量都在呈几何级数的上涨&#xff0c;这就对于企业IT能力和IT架构模式的要求越来越高。加之企业大力发展数字化营销、新能源车等业务&#xff0c;希望通过持续优化客户体验&#xff0c;创造可持续发展的数…

leetcode:统计感冒序列的数目【数学题:组合数含逆元模版】

1. 题目截图 2.题目分析 需要把其分为多个段进行填充 长为k的段&#xff0c;从两端往中间填充的方案数有2 ** (k - 1)种 组合数就是选哪几个数填哪几个段即可 3.组合数含逆元模版 MOD 1_000_000_007 MX 100_000# 组合数模板 fac [0] * MX fac[0] 1 for i in range(1, MX…

一个完整的转录组分析流程

本期的教程代码&#xff08;部分&#xff09; #!/bin/bash # # 使用fastq-dump解压sra数据 # 本数据集为双端数据 # 解压格式为fq.gz for i in SRR6929571 SRR6929572 SRR6929573 SRR6929574 SRR6929577 SRR6929578; do pfastq-dump --split-files --threads 20 --gzip -s 00_…

综合指南:如何创建有效的知识地图?

知识地图是知识管理中的重要工具&#xff0c;使企业能够有效地利用其资产。它促进了解决问题、新人整合和组织学习。此外&#xff0c;它还提高了生产力&#xff0c;实现了数据驱动的决策&#xff0c;并优化了流程。通过捕获和组织有价值的知识资产&#xff0c;它确保了专业知识…

如何通过nvm安装多版本nodejs?如果nodejs安装成功,但npm安装失败怎么办?

我们在开发项目的时候&#xff0c;最开始&#xff0c;是只有一个老的项目&#xff0c;老项目单独安装了node版本4.4.7&#xff0c;后来有了新项目&#xff0c;由于有两个项目&#xff0c;但是一个需要老一些版本的node&#xff0c;一个需要新版本的node&#xff0c;因此需要在两…

签名应用APP分发平台的微服务化部署是什么?其有哪些优势?

在信息技术的世界里&#xff0c;软件开发和部署的模式不断演进。从单体架构到服务化&#xff0c;再到今日备受瞩目的微服务架构。微服务化部署作为一种新兴的软件架构风格&#xff0c;正被越来越多的企业采用。它使得应用可以被分解成一套相互独立的最小服务单元。而“分发平台…

数据结构与算法编程题39

数组A[]中有 n 个整数&#xff0c;没有次序&#xff0c;数组从下标1开始存储&#xff0c;请写出顺序查找任一元素k的算法 &#xff0c;若查找成功&#xff0c;则返回元素在数组中的位置&#xff1b;若查找不成功&#xff0c;则返回 0。 /*数组A[]中有 n 个整数&#xff0c;没有…

Citrix 退出中国市场!华为云以三大优势继续称霸桌面云江湖

文 | 智能相对论 作者 | 沈浪 又一家美国科技企业败走中国市场&#xff01; 前不久&#xff0c;美国虚拟化巨头思杰系统&#xff08;Citrix System&#xff09;公司发布公告&#xff0c;“已决定停止在中国市场&#xff08;包括香港地区和澳门地区&#xff09;的所有新的商业…

JS小技巧,如何去重对象数组?

关于数组对象去重的业务场景&#xff0c;想必大家都遇到过类似的需求吧&#xff0c;这对这样的需求你是怎么做的呢。下面我就先和大家分享下如果是基于对象的1个属性是怎么去重实现的。 方法一&#xff1a;使用 .filter() 和 .findIndex() 相结合的方法 使用 Array.prototype.…

友菜友饭携手分众传媒,打造私厨到家生活新风尚

友菜友饭携手分众传媒 11月29日&#xff0c;友菜友饭与分众传媒签署战略合作协议&#xff0c;在全国重点城市全面引爆品牌力&#xff0c;携手打造全国领先的互联网数字化私厨平台&#xff0c;为中国5亿城市家庭解锁私厨到家服务新体验。 友菜友饭是全国领先的私厨到家平台&…

uniapp到底用什么ui框架最合适-关于uni-app的ui库、ui框架、ui组件

文章目录 直接看答案关于uni-app的ui库、ui框架、ui组件组件的概念扩展组件的选择uni ui如何使用uni ui 综上&#xff0c;官方对组件的使用建议是&#xff1a;附录&#xff1a;其他全端兼容ui库参考文章&#xff1a; 直接看答案 如果想自己纯手写&#xff0c;直接用内置组件。…

客户案例:SMC2威胁感知升级,保障金融行业邮件安全

客户背景 某基金公司是一家在业界享有广泛声誉的综合型资产管理公司&#xff0c;总部位于广州&#xff0c;在北京、上海、香港等地区均设有公司&#xff0c;业务范围遍布全球&#xff0c;凭借其卓越的投资业绩和专业的基金管理服务&#xff0c;赢得了广大投资者的高度认可。 该…

文献速递:多模态影像组学文献分享(基于多模式超声的临床放射学诺莫图,用于预测实质性低回声乳腺病变的恶性风险)

文献速递&#xff1a;多模态影像组学文献分享:(基于多模式超声的临床放射学诺莫图&#xff0c;用于预测实质性低回声乳腺病变的恶性风险) 01 文献速递介绍 作为世界上最常见的癌症&#xff0c;乳腺癌对人们的健康和生存构成了严重威胁&#xff08;1&#xff09;。鉴于其高转…

智慧物联可视化大屏赋能设备管理和城市运行

在智慧物联的时代&#xff0c;万物互联的网络正在构筑起一个智能化的世界。无论是家居设备、汽车、还是工业设备&#xff0c;都能通过互联网实现智能化管理和控制。随着物联网技术的发展&#xff0c;我们迅速步入了一个千姿百态的智慧时代。智慧物联逐渐渗透进我们的日常生活&a…

【银行测试】第三方支付功能测试点+贷款常问面试题(详细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、第三方支付功能…

Linux快速配置拨号

在Linux上进行ADSL拨号配置&#xff0c;通常需要使用pppoeconf命令进行设置。pppoeconf是一个用于配置pppoe连接的工具&#xff0c;它可以帮助用户快速设置pppoe连接并生成配置文件。下面是一个详细的步骤指南&#xff0c;以帮助您在Linux上进行ADSL拨号配置。 步骤1&#xff…

windows下安装配置kafka

一、安装zookeeper 在使用Kafka之前&#xff0c;通常需要先安装和配置ZooKeeper。ZooKeeper是Kafka的依赖项之一&#xff0c;它用于协调和管理Kafka集群的状态。 ZooKeeper是一个开源的分布式协调服务&#xff0c;它提供了可靠的数据存储和协调机制&#xff0c;用于协调分布式…

java easyPOI导出一对多数据,设置边框,字体,字体大小

java easyPOI导出一对多数据&#xff0c;设置边框&#xff0c;字体&#xff0c;字体大小 需求总是千奇百怪&#xff0c;解决的方式也可以是多种多样。 今天碰到导出excel是一对多结构的&#xff0c;以往导出的数据都是一条一条的&#xff0c;所以采用的是比较方便简单的方法eas…