qsort函数的应用以及模拟实现
前言
🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨
🐻推荐专栏: 🍔🍟🌯 c语言进阶
🔑个人信条: 🌵知行合一
🍉本篇简介:>:介绍库函数qsort函数的模拟实现和应用
金句分享:
✨追光的人,终会光芒万丈.✨
目录
- 前言
- 一、qsort函数介绍
- 二、qsort函数的应用
- 1.整形数组排序
- 2.浮点型数组排序
- 3.字符型排序
- 4.结构体数组排序
- 三、qsort模拟实现(采用冒泡排序模拟)
- 第一步:冒泡函数的参数
- 第二步:比较元素的的方法
- 第三步:交换函数
一、qsort函数介绍
库函数查询网站(建议使用旧版本查询)
头文件:<stdlib.h>
功能介绍:
使用函数确定顺序,对指向的数组的元素进行排序,每个元素的长度以字节为单位。
此函数使用的排序算法通过调用指定的函数(要自己定义元素比较方式函数传给qsort)并将指向元素的指针作为参数来比较元素.
该函数不返回任何值,而是通过按定义重新排序数组元素来修改指向的数组的内容。
参数介绍:
参数1(void* base) | 要排序的数组首地址 |
---|---|
参数2(size_t num) | 数组中的元素个数。 |
参数3(size_t size) | 数组中每个元素的大小(以字节为单位)。 |
参数4 ( int (compar)(const void,const void*)) | 指向数组中元素比较方式的函数指针 |
二、qsort函数的应用
1.整形数组排序
#include <stdio.h>
#include <stdlib.h>
//注意,由于qsort排序时,并不知道要排序的元素是何种类型,
//所以自定义比较函数的参数都暂时是void*要强制类型转化为对应类型才可以使用.
int int_sort(const void* e1, const void* e2)//自定义整形元素比较方式函数
{return *(int*)e1 - *(int*)e2;
}
int main()
{int arr1[10] = { 4,6,1,7,8,2,9,10,3,5 };int sz1 = sizeof(arr1) / sizeof(arr1[0]);//计算元素个数qsort(arr1, sz1, sizeof(arr1[0]), int_sort);//整形排序int i = 0;for (i = 0; i < sz1; i++)//整形打印{printf("%d ", arr1[i]);}return 0;
}
运行结果:
1 2 3 4 5 6 7 8 9 10
2.浮点型数组排序
//浮点型数组排序
#include <stdio.h>
#include <stdlib.h>
int double_sort(const void* e1, const void* e2)//浮点型比较
{
//注意要强制转化为相对于的类型,然后解引用比较.int ret = 0;if ((*(double*)e1) - (*(double*)e2) > 0){ret = 1;//前面的数比后面大时返回整数}else ret = -1;//后面数大返回负数;return ret;//两个数相等返回0;
}
int main()
{double arr2[6] = {3.41, 9.45, 4.78, 3.67, 2.9, 7.36 };int sz2 = sizeof(arr2) / sizeof(arr2[0]);//计算数组元素个数qsort(arr2, sz2, sizeof(arr2[0]), double_sort);int i = 0;for (i = 0; i < sz2; i++)//浮点型数组打印{printf("%5.2lf ", arr2[i]);}return 0;
}
运行结果:
2.90 3.41 3.67 4.78 7.36 9.45
3.字符型排序
//字符型数组排序
#include <stdio.h>
#include <stdlib.h>
int char_sort(const void* e1, const void* e2)//字符型比较
{return (*(char*)e1) - (*(char*)e2);
}
int main()
{char arr3[10] = { 'd','g','b','a','e','i','h','c','j','f' };int sz3 = sizeof(arr3) / sizeof(arr3[0]);//计算元素个数qsort(arr3, sz3, sizeof(arr3[0]), char_sort);int i = 0;for (i = 0; i < sz3; i++)//字符型打印{printf("%c ", arr3[i]);}
}
运行结果:
a b c d e f g h i j
4.结构体数组排序
strcmp函数用于比较字符串的,它的比较方式是比较字符的ASCII码值,并不是长度,后续在库函数模拟篇会讲到.
//结构体排序
#include <stdio.h>
#include <stdlib.h>
struct student//创建结构体类型
{char name[15];char sex[3];int age;float stature;
};
typedef struct student sc;//对结构体类型重命名
int sort_age(const void* e1, const void* e2)//按年龄排序
{return (((sc*)e1)->age - ((sc*)e2)->age);
}
int sort_name(const void* e1, const void* e2)//按姓名排序
{return strcmp(((sc*)e1)->name, ((sc*)e2)->name);
}
int main()
{sc arr4[5] = { {"chu jie niu","男",20,1.73f},{"xiao wang","男",19,1.68f},{"qing niao","女",21,1.59f},{"wao shu li","男",16,1.83f},{"peng hu wan","男",15,1.81f} };int sz4 = sizeof(arr4) / sizeof(arr4[0]);//qsort(arr4, sz4, sizeof(arr4[0]), sort_age);qsort(arr4, sz4, sizeof(arr4[0]), sort_name);int i = 0;printf("姓名 性别 年龄 身高\n");for (i = 0; i < sz4; i++){printf("%-12s %-5s %-5d %-5.2fm\n", arr4[i].name, arr4[i].sex, arr4[i].age, arr4[i].stature);}return 0;
}
运行结果:
姓名 性别 年龄 身高
chu jie niu 男 20 1.73 m
peng hu wan 男 15 1.81 m
qing niao 女 21 1.59 m
wao shu li 男 16 1.83 m
xiao wang 男 19 1.68 m
三、qsort模拟实现(采用冒泡排序模拟)
复习一下冒泡排序吧!
void bubble_sort(int* arr, int sz)//冒泡排序
{int i = 0, j = 0;for (i = 0; i < sz - 1; i++){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;}}}
}
int main()
{int arr[10] = { 4,7,1,8,2,3,9,10,5,6 };int sz = sizeof(arr) / sizeof(arr[0]);//计算元素个数bubble_sort(arr, sz);for (int i = 0; i < sz; i++)//数组打印{printf("%d ",arr[i]);}return 0;
}
qsort模拟实现(采用冒泡排序模拟实现)
第一步:冒泡函数的参数
首先,要修改的是冒泡排序函数的参数.
void bubble_sort(void * arr, size_t num, size_t width, int (cmp)(const void, const void*))
这四个参数的含义上面介绍qsort参数时有介绍.
需要注意的是,qsort函数事先并不知道要传过来的数组是何种类型,所以先用void*接收.
补充知识:
void*可以接收任何类型的变量,但是并不能直接使用,要强制类型转化为对应类型使用.
第二步:比较元素的的方法
if (arr[j] > arr[j + 1])
语句中的arr[j]和arr[j+1]有两点需要注意.
由于事先不知道类型
1.要先将arr强制类型转化为char*,因为一个字节是类型的最小单位,这时width就发挥作用了.
arr[j]转化为 (char*)arr + j * width
arr[j+1]转化为 (char*)arr + (j + 1) * width
2.元素的比较方式不再是单一的相减就可以,这里就用到了自定义函数,元素的比较方式函数.
if (cmp((char*)arr + j * width, (char*)arr + (j + 1) * width) > 0)
第三步:交换函数
对于这样只能实现整形的交换方式,肯定是不行的.
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
修改为:用char*类型修改交换
swap(char* e1, char* e2, size_t sz)//交换函数
{//由于qsort函数事先不知道要比较的元素是何种类型,所以用最小单位一个字节来交换.//sz代表元素的所占字节大小int i = 0;char p = 0;for (i = 0; i < sz; i++){p = *(e1 + i);*(e1 + i) = *(e2 + i);*(e2 + i) = p;}
}
最后展示全部代码:
#include <stdio.h>
#include <stdlib.h>
struct student//创建结构体类型
{char name[15];char sex[3];int age;float stature;
};
typedef struct student sc;//对结构体类型重命名
int sort_age(const void* e1, const void* e2)//按年龄排序
{return (((sc*)e1)->age - ((sc*)e2)->age);
}
int sort_name(const void* e1, const void* e2)//按姓名排序
{return strcmp(((sc*)e1)->name, ((sc*)e2)->name);
}
int int_sort(const void* e1, const void* e2)//整形比较
{return *(int*)e1 - *(int*)e2;
}
swap(char* e1, char* e2, size_t sz)//交换函数
{//由于qsort函数事先不知道要比较的元素是何种类型,所以用最小单位一个字节来交换.//sz代表元素的所占字节大小int i = 0;char p = 0;for (i = 0; i < sz; i++){p = *(e1 + i);*(e1 + i) = *(e2 + i);*(e2 + i) = p;}
}
//最后一个参数是函数指针,指向两个元素的比较方法这个函数
void bubble_sort(void * arr, size_t num, size_t width, int (*cmp)(const void*, const void*))
{int i = 0, j = 0;for (i = 0; i < num-1; i++){for (j = 0; j < num - 1 - i; j++){if (cmp((char*)arr + j * width, (char*)arr + (j + 1) * width) > 0){swap((char*)arr + j * width , (char*)arr + (j + 1) * width,width);}}}
}int main()
{int arr[10] = { 4,7,1,8,2,3,9,10,5,6 };int sz = sizeof(arr) / sizeof(arr[0]);//计算元素个数bubble_sort(arr,sz,sizeof(arr[0]),int_sort);for (int i = 0; i < sz; i++)//数组打印{printf("%d ",arr[i]);}printf("\n");sc arr4[5] = { {"chu jie niu","男",20,1.73f},{"xiao wang","男",19,1.68f},{"qing niao","女",21,1.59f},{"wao shu li","男",16,1.83f},{"peng hu wan","男",15,1.81f} };int sz4 = sizeof(arr4) / sizeof(arr4[0]);qsort(arr4, sz4, sizeof(arr4[0]), sort_age);//qsort(arr4, sz4, sizeof(arr4[0]), sort_name);int i = 0;printf("姓名 性别 年龄 身高\n");for (i = 0; i < sz4; i++){printf("%-12s %-5s %-5d %-5.2fm\n", arr4[i].name, arr4[i].sex, arr4[i].age, arr4[i].stature);}return 0;
}
运行结果:
1 2 3 4 5 6 7 8 9 10
姓名 性别 年龄 身高
peng hu wan 男 15 1.81 m
wao shu li 男 16 1.83 m
xiao wang 男 19 1.68 m
chu jie niu 男 20 1.73 m
qing niao 女 21 1.59 m
qsort函数用冒泡排序的模拟实现,就讲到这里了,如果文章有错误或者不理解的地方,欢迎私信牛牛,互相交流,互相学习.
最后,如果文章对大家有帮助的话,求一波三连吧!
💗💗💗886
相关文章:

qsort函数的应用以及模拟实现
前言 🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻推荐专栏: 🍔🍟🌯 c语言进阶 🔑个人信条: 🌵知行合一 🍉本篇简介:>:介绍库函数qsort函数的模拟实现和应用 金句分享: ✨追…...

【iobit 软件】家族系列 - 正版激活码
装机必备iobit系列软件 - 激活码获取看最后 第一款、Advanced SystemCare 16 您需要的人工智能驱动的PC优化器,以释放磁盘空间,加速PC并保护在线隐私。 功能特点: 1. 系统清理与优化:通过清除系统垃圾文件、注册表信息、无用文…...

ACM-大一训练第三周(Floyd算法+并查集算法专题训练)
🚀write in front🚀 📝个人主页:认真写博客的夏目浅石.CSDN 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝 📣系列专栏:ACM周训练题目合集.CSDN 💬总结:…...

taobao.item.sku.update( 更新SKU信息 )
¥开放平台免费API必须用户授权 *更新一个sku的数据 *需要更新的sku通过属性properties进行匹配查找 *商品的数量和价格必须大于等于0 *sku记录会更新到指定的num_iid对应的商品中 *num_iid对应的商品必须属于当前的会话用户 公共参数 请求地址: HTTP地址 http://gw.…...

ros2创建一个工程
第一步:创建src目录 $ mkdir ros2-demo $ cd ros2-demo/ $ mkdir src $ cd src/第二步:创建功能包cd src$ ros2 pkg create --build-type ament_cmake ros2_demo --dependencies rclcpp std_msgsros2 pkg create --build-type ament_python learning_pkg…...

【力扣】stack容器的探索之有效的括号
作者:狮子也疯狂 专栏:《算法详解》 愿你生如夏花之绚烂,幸运永远与你相伴,疯狂常在。 目录一. 🦁 Stack容器的来历1.1 操作栈的方法二. 🦁 Stack的使用2.1 题目2.2 分析2.3 详细算法实现2.4 力扣AC截图三…...
【Elsevier出版社】中科院2区,SCIEEI 双检,已有发表案例,3个月左右录用
1区智能传感器类SCIE&EI 【期刊简介】IF:5.0-6.0,JCR1区,中科院2区,SCI&EI 双检,正刊 【参考周期】3个月左右录用 【截稿日期】2023.5.30 【征稿领域】有关人工智能与传感器的相关研究均可 包括但不限于&#…...

基于明道云平台重建医院管理流程
一、龙华区医疗信息化建设情况 首先,给大家介绍一下龙华区医疗信息化建设的情况,龙华区位于深圳市的中部,目前下属3家公立医院,2家公共卫生机构。2017年,龙华区提出了建设智慧龙华总体框架方案,龙华区卫生…...

【蓝桥杯嵌入式】STM32定时器的配置,解析预分频系数和重装载值与时钟频率的关系
🎊【蓝桥杯嵌入式】专题正在持续更新中,原理图解析✨,各模块分析✨以及历年真题讲解✨都在这儿哦,欢迎大家前往订阅本专题,获取更多详细信息哦🎏🎏🎏 🪔本系列专栏 - 蓝…...

ChatGPT API 低价上线,开发者可以人手一个了?
千呼万唤,ChatGPT API来了! 不仅首发,价格居然还有惊喜,0.002美元/每1000 token,并将价格降低90%,直接打了1折。OpenAI官方还表示,gpt-3.5-turbo目前的版本代号是gpt-3.5-turbo-0301࿰…...
品牌营销策略 | 科学经营合作伙伴关系的5个要素
在管理众多的合作伙伴项目时,企业会遇到很多的问题,比如,数据信息分散凌乱、手动操作繁琐重复和处理环节粗放等。这将耗费公司大量的人力物力,严重影响大数据的综合分析和利用。因此,企业要科学管理好企业的合作伙伴关…...
【剑指offer-C++】JZ20:表示数值的字符串
【剑指offer-C】JZ20:表示数值的字符串题目描述解题思路题目描述 描述:请实现一个函数用来判断字符串str是否表示数值(包括科学计数法的数字,小数和整数)。 科学计数法的数字(按顺序)可以分成以下几个部分…...

【NLP相关】深度学习领域不同编程IDE对比
❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博…...
定制ubuntu的docker镜像
ssh登录jdkmavenvimpingcurlFROM ubuntu:22.04RUN apt-get updateRUN apt-get install -y \vim \inetutils-ping \openssh-server \curl \openjdk-8-jdk \mavenRUN mkdir /var/run/sshdRUN echo root:root |chpasswdRUN sed -ri s/^#?PermitRootLogin\s.*/PermitRootLogin yes…...

我的 System Verilog 学习记录(8)
引言 本文简单介绍 SystemVerilog 的接口。 前文链接: 我的 System Verilog 学习记录(1) 我的 System Verilog 学习记录(2) 我的 System Verilog 学习记录(3) 我的 System Verilog 学习记…...

详解JAVA字节码
目录 1.概述 2.字节码文件构成 2.1.魔数 2.2.版本号 2.3.常量池 2.4.访问标志 2.5.索引 2.6.字段表 2.7.方法表 3.字节码指令 3.1.概述 3.2.指令分类 3.2.1.加载存储指令 3.2.2.运算指令 3.2.3.其他指令 3.3.完整指令工作流程 4.字节码保护 1.概述 以往的编程…...

前端利用emailjs发送邮件
最近有一个需求,前端发送一个form表单到一个邮箱,找了一圈发现emailjs还不错就使用他了。首先emailjs官网注册一个账号注册完之后创建一个邮件服务(我这里使用的是谷歌邮箱)链接谷歌邮箱账户 然后创建服务接下来就要创建一个邮件的…...

16 Nacos服务端服务注册源码分析
Nacos服务端服务注册源码分析 服务端调用接口 我们已经知道客户端在注册服务的时候实际上是调用的NamingService.registerInstance这个方法来完成实例的注册,而且在最后我们也告诉了大家实际上从本质上讲服务注册就是调用的对应接口nacos/v1/ns/instanceÿ…...
Spring Boot2中如何优雅地个性化定制Jackson
概述 本文的编写初衷,是想了解一下Spring Boot2中,具体是怎么序列化和反序列化JSR 310日期时间体系的,Spring MVC应用场景有如下两个: 使用RequestBody来获取JSON参数并封装成实体对象;使用ResponseBody来把返回给前…...
2023年全国最新食品安全管理员精选真题及答案11
百分百题库提供食品安全管理员考试试题、食品安全员考试预测题、食品安全管理员考试真题、食品安全员证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 101.婴幼儿配方乳粉的产品配方应当经()部门注册。…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...

认识CMake并使用CMake构建自己的第一个项目
1.CMake的作用和优势 跨平台支持:CMake支持多种操作系统和编译器,使用同一份构建配置可以在不同的环境中使用 简化配置:通过CMakeLists.txt文件,用户可以定义项目结构、依赖项、编译选项等,无需手动编写复杂的构建脚本…...
comfyui 工作流中 图生视频 如何增加视频的长度到5秒
comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...