当前位置: 首页 > news >正文

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

相关文章:

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

文章目录 &#x1f680;前言&#x1f680;void*类型指针&#x1f680;库函数qsort的使用&#x1f680;利用冒泡排序实现库函数qsort() &#x1f680;前言 今天阿辉将为大家介绍库函数qsort的使用&#xff0c;还包括利用冒泡排序模拟实现qsort以及void*类型的指针&#xff0c;关…...

mybatis和mybatisplus中对 同namespace 中id重复处理逻辑源码解析

一、背景 同事在同一个mapper.xml &#xff08;namespace相同&#xff09;&#xff0c;复制了一个sql没有修改id&#xff0c;正常启动项目。但是我以前使用mybatis的时候如果在namespace相同情况下&#xff0c;id重复&#xff0c;项目会报错无法正常启动&#xff0c;后来看代码…...

linux下部署frp客户端服务端-内网穿透

简介 部署在公司内部局域网虚拟机上的服务需要在外网能够访问到&#xff0c;这不就是内网穿透的需求吗&#xff0c;之前通过路由器实现过&#xff0c;现在公司这块路由器不具备这个功能了&#xff0c;目前市面上一些主流的内网穿透工具有&#xff1a;Ngrok&#xff0c;Natapp&…...

Markdown to write

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…...

ResNeXt(2017)

文章目录 Abstract1. Introductionformer workour work 2. Related Work多分支卷积网络分组卷积压缩卷积网络Ensembling 3. Method3.1. Template3.2. Revisiting Simple Neurons3.3. Aggregated Transformations3.4. Model Capacity 4. Experiment 原文地址 源代码 Abstract 我…...

DreamPlace 的下载安装与使用

DreamPlace 是一款芯片放置工具&#xff0c;用于宏单元&#xff08;macro&#xff09;和标准单元&#xff08;Standard Cell&#xff09;的放置以及布线&#xff0c;并计算 HPWL、Overlap 等用于衡量芯片性能的参数。 一、环境 1. 系统环境&#xff1a;Ubuntu 20.04 DreamPla…...

FPGA模块——SPI协议(读写FLASH)

FPGA模块——SPI协议&#xff08;读写FLASH&#xff09; &#xff08;1&#xff09;FLASH芯片 W25Q16BV&#xff08;2&#xff09;SPI协议&#xff08;3&#xff09;芯片部分命令1.Write Enable&#xff08;06h&#xff09;2.Chip Erase (C7h / 60h)3.写指令&#xff08;02h&am…...

SQL自学通之表达式条件语句与运算

目录 一、目标 二、表达式条件语句 1、表达式&#xff1a; 2、条件 2.1、WHERE 子句 三、运算 1、数值型运算: 1.1、加法() 1.2、减法 (-) 1.3、除法&#xff08;/&#xff09; 1.4、乘法 &#xff08;*&#xff09; 1.5、取模 &#xff08;%&#xff09; 优先级别…...

公网域名如何解析到内网IP服务器——快解析域名映射外网访问

在本地搭建主机应用后&#xff0c;由于没有公网IP或没有公网路由权限&#xff0c;在需要发布互联网时&#xff0c;就需要用到外网访问内网的一些方案。由于内网IP在外网不能直接访问&#xff0c;通常就用通过外网域名来访问内网的方法。那么&#xff0c;公网域名如何解析到内网…...

线程安全与并发区别

在并发编程中&#xff0c;"线程安全 "和 "并发 "是相关的概念&#xff0c;但它们有着不同的含义。 线程安全 如果一个类或方法可以同时被多个线程使用&#xff0c;而不会导致数据损坏或意外行为&#xff0c;那么这个类或方法就被认为是线程安全的。即使多…...

SEO优化是什么,如何进行SEO优化

SEO&#xff08;Search Engine Optimization&#xff09;是指通过对网站进行优化&#xff0c;提高其在搜索引擎中的排名&#xff0c;从而增加有机流量和改善用户体验的一系列技术和方法。 进行SEO优化可以帮助网站获得更多的有机搜索流量&#xff0c;并提升网站的曝光度和可见…...

nodejs发起http或https请求

前言&#xff1a;使用node内置模块http、https http请求 const express require(express) const http require(http)const app express()const loginConfig (token) > {return {hostname: api.test.com,port: 80,path: /test?access_token${token},method: GET} }app.…...

举例C#使用特性排除某些类成员不参与XML序列化和反序列化

在C#中&#xff0c;可以使用 [XmlIgnore] 特性来排除某些类成员不参与XML序列化和反序列化。这个特性告诉XML序列化器忽略被标记的成员。 以下是一个使用 [XmlIgnore] 特性的示例&#xff1a; using System; using System.IO; using System.Xml.Serialization;public class P…...

PHP基础 - 输入输出

在 PHP 中,有多种方法可以用来输出内容。下面是其中的几种: 1、echo: 这是最常见的输出语句之一,可以输出一个或多个字符串。它是一个语言结构,可以省略括号。使用示例如下: <?php // 使用 echo 语句输出一个字符串 echo "Hello, world!\n";// 可以使用…...

大创项目推荐 交通目标检测-行人车辆检测流量计数 - 大创项目推荐

文章目录 0 前言1\. 目标检测概况1.1 什么是目标检测&#xff1f;1.2 发展阶段 2\. 行人检测2.1 行人检测简介2.2 行人检测技术难点2.3 行人检测实现效果2.4 关键代码-训练过程 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 毕业设计…...

利用R语言heatmap.2函数进行聚类并画热图

数据聚类然后展示聚类热图是生物信息中组学数据分析的常用方法&#xff0c;在R语言中有很多函数可以实现&#xff0c;譬如heatmap,kmeans等&#xff0c;除此外还有一个用得比较多的就是heatmap.2。最近在网上看到一个笔记文章关于《一步一步学heatmap.2函数》&#xff0c;在此与…...

伦茨科技宣布ST17H6x芯片已通过Apple Find My「查找」认证

深圳市伦茨科技有限公司&#xff08;以下简称“伦茨科技”&#xff09;发布ST17H6x Soc平台。成为继Nordic之后全球第二家取得Apple Find My「查找」认证的芯片厂家&#xff0c;该平台提供可通过Apple Find My认证的Apple查找&#xff08;Find My&#xff09;功能集成解决方案。…...

nodejs微信小程序+python+PHP的游戏测评网站设计与实现-计算机毕业设计推荐

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…...

在 JavaScript 中导入和导出 Excel XLSX 文件:SpreadJS

在 JavaScript 中导入和导出 Excel XLSX 文件 2023 年 12 月 5 日 使用 MESCIUS 的 SpreadJS 将完整的 JavaScript 电子表格添加到您的企业应用程序中。 SpreadJS 是一个完整的企业 JavaScript 电子表格解决方案&#xff0c;用于创建财务报告和仪表板、预算和预测模型、科学、工…...

【Pytorch】Fizz Buzz

文章目录 1 数据编码2 网络搭建3 网络配置&#xff0c;训练4 结果预测5 翻车现场 学习参考来自&#xff1a; Fizz Buzz in Tensorflowhttps://github.com/wmn7/ML_Practice/tree/master/2019_06_10Fizz Buzz in Pytorch I need you to print the numbers from 1 to 100, excep…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...