C语言学习系列-->【关于qsort函数的详解以及它的模拟实现】

文章目录
- 一、概述
- 二、qsort函数参数介绍
- 三、qsort实现排序
- 3.1 qsort实现整型数组排序
- 3.2 qsort实现结构体数组排序
- 四、模拟实现qsort函数
一、概述
对数组的元素进行排序
对数组中由 指向的元素进行排序,每个元素字节长,使用该函数确定顺序。
此函数使用的排序算法通过调用指定的函数来比较元素对,并将指向它们的指针作为参数。
官方解释:

声明:
void qsort (void* base, size_t num, size_t size,int (*compar)(const void*,const void*));
qsort函数的参数
void* base
size_t num
size_t size
int( * compar )( const void * ,const void *)
二、qsort函数参数介绍
void qsort(void* base, //待排序数据的起始位置size_t num, //待排序数据的元素个数size_t size,//待排序数据的每个元素的大小int (*compar)(const void*p1, const void*p2));//函数指针 - 指针指向的函数是用来比较待排序数据中两个元素大小关系的
关于void * 的介绍:
void * 是一个无具体指向的指针类型
任何类型的指针变量都i可以存放在void中
void * 不能解引用
其中两个void*类型的参数 p1 和 p2 用来存放数组中待比较的两个元素的地址。如果compar函数的返回值小于0,会把p1指向的元素排到p2指向的元素前面;如果返回值等于0,不会改变p1和p2指向的元素位置;如果返回值大于0,会把p1指向的元素排到p2指向的元素后面。
三、qsort实现排序
3.1 qsort实现整型数组排序
# define _CRT_SECURE_NO_WARNINGS#include<stdio.h>
#include<stdlib.h>int comper(const void* e1, const void* e2)
{//通过强制类型转换,比较e1,e2.return *(int*)e1 - *(int*)e2;//void* 不能解引用
}int main()
{int arr[] = { 5,3,6,7,8,1,9,4,2,0 };int sz = sizeof(arr) / sizeof(arr[0]);//传入参数qsort(arr, sz, sizeof(arr[0]), comper);//打印排序后的数组int i = 0;for (i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}

3.2 qsort实现结构体数组排序
按照年龄大小的方式进行排序
# define _CRT_SECURE_NO_WARNINGS#include<stdio.h>
#include<stdlib.h>struct Stu
{char name[20];int age;
};int comper_by_age(const void* e1, const void* e2)
{return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age; //结构体指针不需要解引用
}int main()
{struct Stu s[] = { {"zhangsan",20},{"lisi",30},{"wangwu",25} };int sz = sizeof(s) / sizeof(s[0]);qsort(s, sz, sizeof(s[0]), comper_by_age);int i = 0;for (i = 0; i < sz; i++){printf("%s %d\n", s[i].name, s[i].age);}return 0;
}
运行结果:
zhangsan 20
wangwu 25
lisi 30
按照名字进行排序
# define _CRT_SECURE_NO_WARNINGS#include<stdio.h>
#include<stdlib.h>
#include<string.h>struct Stu
{char name[20];int age;
};int comper_by_name(const void* e1, const void* e2)
{return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e1)->name);//名字是字符串,通过strcmp函数来比较
}int main()
{struct Stu s[] = { {"zhangsan",20},{"lisi",30},{"wangwu",25} };int sz = sizeof(s) / sizeof(s[0]);qsort(s, sz, sizeof(s[0]), comper_by_name);int i = 0;for (i = 0; i < sz; i++){printf("%s %d\n", s[i].name, s[i].age);}return 0;
}
运行结果:
lisi 30
wangwu 25
zhangsan 20

四、模拟实现qsort函数
程序员A:写一个bubble_sort()函数,可以让别人直接拿来调用
于是程序员A想要利用冒泡排序的方式,来模拟实现qsort()函数排序
qsort的底层是通过快速排序来实现的
为了能对任意数组进行排序,程序员A对冒泡排序进行了一定的更改
和qsort函数一样,bubble_sort也需要传入四个参数:
void* arr //接收首元素地址
size_t sz //接收元素个数
size_t width //接收元素宽度
int(*comper)(const void*e1,const void*e2)
于是,
void bubble_sort(void*arr,size_t sz,size_t width,int(*comper)(const void*e1,const void*e2))
现在需要完成bubble_sort内部,也就是实现排序
void bubble_sort(void* arr, size_t sz, size_t width, int(*comper)(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++){/*............................ */}}
}
在冒泡排序中,运用下面代码,使得相邻两个元素进行交换:
//每一轮冒泡要进行多少次两两比较if (arr[j] > arr[j + 1]){int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}
但是,这只适用于整型,不通用
那么,如何去比较呢?如何去交换两个元素呢?
for (j = 0; j < sz-1-i; j++){if (comper((char*)arr+j*width,(char*)arr+(j+1)*width)>0)//把arr强转为char*,arr就可以正常使用//char类型指针+1只会跳过一个字节//+j*width表示跳过j个元素{//交换//由于这里的数组名已经被转为char类型的指针//所以要交换数组中的元素,就只能一个字节一个字节进行交换Swap((char*)arr + j * width, (char*)arr + (j + 1) * width,width);//前两个参数是待交换元素的地址,第三个参数是元素的宽度}}
这样,就把交换条件普适化了,不只是能用在整型类型中
那么…交换呢?
根据以前的经验,我们知道使得两个元素交换,可以引入一个新的变量来暂时存一下,从而去交换,但是这有限制。
解决方案:一个字节一个字节地交换
我们将交换地函数,封装在这里面:
Swap((char*)arr + j * width, (char*)arr + (j + 1) * width,width)
对Swap函数进行加工:
void Swap(char* ele1, char* ele2,int width)
{int i = 0;for (i = 0; i < width; i++){char tmp = *ele1;*ele1 = *ele2;*ele2 = tmp;ele1++;ele2++;}
}
这样,程序员A就将 bubble_sort()函数完成了
程序员B要想是使用该函数,直接引入 bubble_sort函数,自己写一个比较函数就可以了。

相关文章:
C语言学习系列-->【关于qsort函数的详解以及它的模拟实现】
文章目录 一、概述二、qsort函数参数介绍三、qsort实现排序3.1 qsort实现整型数组排序3.2 qsort实现结构体数组排序 四、模拟实现qsort函数 一、概述 对数组的元素进行排序 对数组中由 指向的元素进行排序,每个元素字节长,使用该函数确定顺序。 此函数使…...
Linux系统安全:NAT(SNAT、DNAT)
目录 一.NAT 二.SNAT 三.DNAT 一.NAT NAT: network address translation,支持PREROUTING,INPUT,OUTPUT,POSTROUTING四个链 请求报文:修改源/目标IP, 响应报文:修改源/目标IP,根据…...
【数据库】MySQL存储过程:提升数据库性能和操作效率的利器
在数据库管理系统中,存储过程是一种重要的数据库对象,它允许将一组复杂的SQL语句组合起来,形成一个独立的单元进行重复使用。存储过程可以极大地提高数据库的性能和操作效率,降低网络流量,减轻系统负载。本文将深入探讨…...
rust写一个多线程和协程的例子
当涉及到多线程和协程时,Rust提供了一些非常强大的工具,其中最常用的库之一是tokio,它用于异步编程和协程。下面我将为你展示一个简单的Rust程序,演示如何使用多线程和协程。 首先,你需要在你的项目的Cargo.toml文件中…...
react18+antd5.x(1):Notification组件的二次封装
antdesign已经给我们提供了很好的组件使用体验,但是我们还需要根据自己的项目业务进行更好的封装,减少我们的代码量,提升开发体验 效果展示 开起来和官网的使用没什么区别,但是我们在使用的时候,进行了二次封装,更利于我们进行开发 MyNotification.jsx,是我们的业务页面…...
jenkins运行pytest测试用例脚本报错:没有权限,无法写日志PermissionError:[Error 13]Permission denied
报错信息: PermissionError:[Error 13]Permission denied:‘/var/jenkins_home/workspace/deleverySystem/Delivery_System/out_files/logs/waimai_20230823.log’ 解决方法: 在jenkins容器内部输入 chmod -R 777 /var/jenkins_home/works…...
数据结构 day1
1>x.mind 2>间接定义结构体数组,进行4种方式的定义和初始化 3>定义结构体存储10辆车(车的信息:品牌、单价、颜色) 1.定义函数,实现循环输入 2.定义函数,实现排序 3.定义函数,计算红色车…...
湖北咸宁农业三维扫描数字化农业3d打印制造应用-CASAIM中科广电
农业是人类衣食之源、生存之本,是一切生产的首要条件,CASAIM在农业三维扫描和3d打印应用上有丰富经验。 1.三维扫描技术在农业领域的应用 CASAIM三维扫描是集光学、机电和计算机技术于一体的高新无损检测技术,能够对实物的空间外形、结构乃…...
Jenkins的定时任务配置
jenkins配置定时任务位置(点击日程表的问好可查看语法配置) jenkins的定时任务的参数 # 定时任务参数(每个参数之间使用tab键或空格分隔)MINUTE HOUR DOM MONTH DOW 参数解释取值范围 MINUTE 分钟0-59HOUR小时0-23DOM一月的天数1-31MONTH月份1-12DOW 一周的天数0…...
THINKPHP 微联云投票系统源码独立版 + 支持刷礼物
THINKPHP 微联云投票系统源码独立版 支持刷礼物 nginxphp7.2以上 mysql5.6以上 简单测试后台基本没什么问题,暂时发现H5前端有bug,自行修复。...
Mongodb两种启动方法
一、命令行启动 1.修改存放数据库的位置 说明:E:\data\mongodb;我在E盘创建的文件夹mongodb mongod --dbpathE:\data\mongodb 2.成功启动 说明:默认端口27017,代表已经启动成功 ,并在mongodb自动创建文件 二、配置项…...
Python:列表的浅拷贝与深拷贝
在python语言中,因为其面向对象的特性,在进行列表拷贝时可能会出现一些意想不到的结果,涉及到列表的浅拷贝和深拷贝相关问题,本文将对其进行总结。 首先我们来看以下代码。 my_list [1, 2, 3] your_list my_list your_list[0] …...
OnePlus Open可折叠手机:规格、价格、发布日期等详细信息汇总!
我们知道OnePlus可折叠手机即将问世,无论它是否被命名为OnePlus Open。我们迫不及待地想让它到来,为该公司再添一根弦,为最好的可折叠手机增添一个新的竞争对手。 OnePlus以前没有生产过任何可折叠产品,但它确实拥有合作伙伴公司Oppo的丰富知识,并可以向三星、摩托罗拉和…...
SQL 数据库
安装配置 【1】 MySQL安装配置教程(超级详细、保姆级) 【2】 MySQLNavicat安装配置教程(超级详细、保姆级) 学习资料 【戴师兄】SQL入门免费教程 刷题链接:https://share.mubu.com/doc/4BHMMbbvIMb 学习笔记…...
【算法系列篇】滑动窗口
文章目录 前言什么是滑动窗口1.长度最小的子数组1.1 题目要求1.2 做题思路 1.3 Java代码实现2.无重复字符的最长子串2.1 题目要求2.2 做题思路2.3 Java代码实现 3.最大连续1的个数 III3.1 题目要求3.2 做题思路3.3 Java代码实现 4.将x减到0的最小操作数4.1 题目要求4.2 做题思路…...
多维时序 | MATLAB实现BiTCN-BiGRU-Attention多变量时间序列预测
多维时序 | MATLAB实现SABO-CNN-GRU-Attention多变量时间序列预测 目录 多维时序 | MATLAB实现SABO-CNN-GRU-Attention多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 多维时序 | MATLAB实现BiTCN-BiGRU-Attention多变量时间序列预测。 模型描…...
Docker容器与虚拟化技术:Docker compose部署LNMP
目录 一、理论 1.LNMP架构 2.背景 3.Dockerfile部署LNMP 3.准备Nginx镜像 4.准备MySQL容器 5.准备PHP镜像 6.上传wordpress软件包 7.编写docker-compose.yml 8.构建与运行docker-compose 9.启动 wordpress 服务 10.浏览器访问 11.将运行中的 docker容器保存为 doc…...
高性能服务器Nodejs操作Mysql数据库
目录 1 Node 操作 mysql1.2 操作 mysql 数据库 2 Web 开发模式2.1 服务端渲染2.2 前后端分离2.3 如何选择 3 身份认证3.1 Session 认证机制3.2 JWT 认证机制 1 Node 操作 mysql 数据库和身份认证 配置 mysql 模块 安装 mysql 模块 npm install mysql建立连接 const mysql …...
ffmpeg将rtsp流转成mp4
命令行版本 ffmpeg -y -i "rtsp://你的rtsp地址" -vcodec copy -f mp4 d:/1.mp4中间的rtsp网址一定要加上双引号,避免出现url有特殊字符的问题 java代码版本 如果不支持tcp协议,去掉下面两个参数即可,加上这两个参数是因为ffmpeg默认使用ud…...
第十四天|层序遍历、226.翻转二叉树 (优先掌握递归)、101. 对称二叉树 (优先掌握递归)
层序遍历 题目链接:102. 二叉树的层序遍历 - 力扣(LeetCode) /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(n…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
【深度学习新浪潮】什么是credit assignment problem?
Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...
Java数组Arrays操作全攻略
Arrays类的概述 Java中的Arrays类位于java.util包中,提供了一系列静态方法用于操作数组(如排序、搜索、填充、比较等)。这些方法适用于基本类型数组和对象数组。 常用成员方法及代码示例 排序(sort) 对数组进行升序…...
qt+vs Generated File下的moc_和ui_文件丢失导致 error LNK2001
qt 5.9.7 vs2013 qt add-in 2.3.2 起因是添加一个新的控件类,直接把源文件拖进VS的项目里,然后VS卡住十秒,然后编译就报一堆 error LNK2001 一看项目的Generated Files下的moc_和ui_文件丢失了一部分,导致编译的时候找不到了。因…...
大模型智能体核心技术:CoT与ReAct深度解析
**导读:**在当今AI技术快速发展的背景下,大模型的推理能力和可解释性成为业界关注的焦点。本文深入解析了两项核心技术:CoT(思维链)和ReAct(推理与行动),这两种方法正在重新定义大模…...
【向量库】Weaviate 搜索与索引技术:从基础概念到性能优化
文章目录 零、概述一、搜索技术分类1. 向量搜索:捕捉语义的智能检索2. 关键字搜索:精确匹配的传统方案3. 混合搜索:语义与精确的双重保障 二、向量检索技术分类1. HNSW索引:大规模数据的高效引擎2. Flat索引:小规模数据…...
