qsort使用举例和qsort函数的模拟实现
qsort使用举例
qsort是C语言中的一个标准库函数,用于对数组或者其他数据结构中的元素进行排序。它的原型如下:
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
我们可以去官网搜来看一看:
那么对于其中的参数,下面也有相应的英文解释:
- base:指向要排序的数组或数据结构的第一个元素的指针。
- nmemb:要排序的元素的数量。
- size:每个元素的大小(以字节为单位)。
- compar:指向用于比较两个元素的函数的指针。
compar函数用于比较两个元素的大小关系,返回值为整数,表示两个元素的大小关系。具体返回值的含义如下:
- 若返回值小于0,则表示第一个元素小于第二个元素。
- 若返回值等于0,则表示两个元素相等。
- 若返回值大于0,则表示第一个元素大于第二个元素。
qsort函数根据compar函数的返回值对数组或数据结构中的元素进行排序,可以按照升序或降序进行排序。
那么知道以上这些,下面我们就来使用这个库函数,首先我们以排序整型数组为例:
int arr[10] = { 4,5,7,6,3,2,8,9,1,10 };
假设我们要排列以上的10个元素,那么我们根据上面对于库函数qsort的认识,需要向它传入四个参数,那么第一个为- base:指向要排序的数组或数据结构的第一个元素的指针,那么就是我们的arr 了,第二个为- nmemb:要排序的元素的数量,这是我们就要计算里面有多少个元素了,我们可以这样算:
int sz = sizeof(arr) / sizeof(arr[0]);
使用第二个参数我们可以写为 sz ,第三个为- size:每个元素的大小,那么我们计算出数组中第一个元素有多少个字节就可以了 sizeof(arr[0]),最后一个为- compar:指向用于比较两个元素的函数的指针,这里我们就需要我们自己写一个函数了,告诉这个库函数qsort我们要比较什么类型的数据:
qsort(arr, sz, sizeof(arr[0]), cop_int);
那么接下来就是这个cop_int函数怎么写了,因为我们不知道会传什么样的数据,所以我们可以使用void*进行接收,返回类型为int型,因为下面是根据大于或小于或等于来排序的,而且不希望改我们所要排序的数值,所以我们这样写到:
int cop_int(const void* p1, const void* p2)
上面传来了void*类型的数据,而void*的数据不能够直接进行运算操作,所以下面我们要进行强制类型转换,作差看看两数的情况:
return *(int*)p1 - *(int*)p2;
下面就来看看我们整体的代码:
#include <stdlib.h>//头文件void Print_arr(int arr[], int sz)
{for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}
}int cop_int(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;
}int main()
{int arr[10] = { 4,5,7,6,3,2,8,9,1,10 };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cop_int);Print_arr(arr, sz);return 0;
}
看看我们的运行效果:
下面我们给结构体进行排序:
我们先随便写一个结构体:
struct Stu
{char name[20];int age;int score;
};//定义一个学生的名字,岁数,分数
我们只需要改我们的- compar:指向用于比较两个元素的函数的指针,我们先以学生的名字进行排序,那么结构体我们只需要转换成结构体指针就可以进行比较了,名字我们strcmp进行比较:
#include <stdlib.h>//qsort的头文件
#include <string.h>//strcmp的头文件
struct Stu
{char name[20];int age;int score;
};
int cop_Stu_by_name(const void* p1, const void* p2)
{return strcmp(((struct Stu*)p1)->name , ((struct Stu*)p2)->name);
}
int main()
{struct Stu arr[] = { {"zhangsan",18,76},{"lisi",28,65},{"wangmazi",25,79}};int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cop_Stu_by_name);for (int i = 0; i < sz; i++){printf("%s %d %d\n", arr[i].name, arr[i].age,arr[i].score);}return 0;
}
看看运行的结果:
是正确的哦!我们还可以以年龄进行比较还有分数啊,这里我就不排了,我们下面用冒泡排序来qsort函数的模拟实现!
qsort函数的模拟实现(采用冒泡排序法)
对于冒泡排序,我在前面也写到过,还不太清楚的小伙伴可以看看哦。
void BubbleSort(int arr[], int sz)
{for (int i = 0; i < sz - 1; i++)//趟数{for (int j = 0; j < sz - 1 - i; j++)//一趟冒泡排序{if (arr[j] > arr[j + 1])//需要进行改造的地方 1{int tmp = arr[j];// 需要进行改造的地方 2arr[j] = arr[j + 1];arr[j + 1] = tmp;}}}
}int main()
{int arr[] = { 5,7,9,4,3,6,8,1 };//5 7 9 4 3 6 8 1int sz = sizeof(arr) / sizeof(arr[0]);//计算有多少个元素BubbleSort(arr, sz);for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}
首先我们先来想一想,那些地方需要我们改造,对于循环那些我们是不是就不用改了,那不会有影响。我们将会排序到不同的数据类型,所以我们对于 if (arr[j] > arr[j + 1])的比较,是不是需要我们进行改造呢,还有下面的交换变量,也是我们需要改的,既然上面的类型都被改了,下面也肯定是需要改的。
我们以结构体的年龄为例,那么函数的参数还是我们上面的那样,只是要改一下第四个参数:
bubble_sort2(arr, sz, sizeof(arr[0]), cop_Stu_by_age);
接下来就是对于bubble_sort2函数的定义了,下面传了四个参数,那我们也要用四个参数进行接收了,因为我们不知道传来的是什么类型的,所以在设置类型上,我们要考虑考虑,第一个为地址,我们用void*进行接受吧,void*都装的了,哈哈。第二个和第三个就用size_t了,最后一个像我们上面考虑的那个样:int (*cmp)(const void* p1, const void* p2)。
void bubble_sort2(void* base,size_t sz,size_t width, int (*cmp)(const void* p1, const void* p2))
{for (int i = 0; i < sz-1; i++){for (int 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;}}}
}
接着就是对于比较的改造了,我们这里构造一个新的函数进行比较,这样我们根据下面传来的类型去调用相应的,那么我们怎样找到我们的对应的元素进行比较呢?下面给给了我们首元素的地址,和每个元素的大小,我们是不是可以用起来呢,我们根据j的变化去找到元素。但是还要想到我们要用它来不同数据类型的排序,所以我们也要进行强制类型转换。我们强制转换成什么类型的数据呢?是不是char*最为合适呢,不管是什么类型,我们都可以一个一个的去进行交换:
if(cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
下面我们进行对于交换的改造:上面改成了那样,所以接收时也改成相应的就行了,我们以前进行交换的时候是创建了第三个变量进行交换,现在我们不知什么类型,就需要改进了。强制转换成什么类型比较合适呢?假设我们结构体的为7个字节大小,那我们是不是用char类型就可以了,不管你如何,我一个一个的进行交换就都可以实现,既然我们以这样的方式进行实现,那我们是不是应该把它每个元素的大小传进来呢:
void swap(char* a, char* b, size_t width)
{for (int i = 0; i < width; i++){char tmp = *a;*a = *b;*b = tmp;a++;b++;}
}
接下来我们就看看整体的代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>struct Stu
{char name[20];int age;
};int cop_Stu_by_age(const void* p1, const void* p2)
{return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}int cop_int(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;
}void PrintArr(int arr[], int sz)
{for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}
}void swap(char* a, char* b, size_t width)
{for (int i = 0; i < width; i++){char tmp = *a;*a = *b;*b = tmp;a++;b++;}
}//冒泡排序
void bubble_sort2(void* base,size_t sz,size_t width, int (*cmp)(const void* p1, const void* p2))
{for (int i = 0; i < sz-1; i++){for (int j = 0; j < sz-1-i; j++){//if (arr[j] > arr[j + 1])if(cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0){swap((char*)base + j * width, (char*)base + (j + 1) * width,width);/*int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;*/}}}
}int main()
{struct Stu arr[] = { {"aihua",18},{"zhanghong",21},{"kiki",15} };int sz = sizeof(arr) / sizeof(arr[0]);//年龄bubble_sort2(arr, sz, sizeof(arr[0]), cop_Stu_by_age);for (int i = 0; i < sz; i++){printf("%s %d\n", arr[i].name, arr[i].age);}return 0;
}
看看运行结果:
那么也是可以的哟,我这里就是用其他类型进行排序了,感兴趣的话,可以去试试哦,本来还想着画图给你们梳理一下,可那个画图工具不给力😢😢😢!
愿你们冬不寒!❤❤❤
相关文章:
qsort使用举例和qsort函数的模拟实现
qsort使用举例 qsort是C语言中的一个标准库函数,用于对数组或者其他数据结构中的元素进行排序。它的原型如下: void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); 我们可以去官网搜来看一看:…...
AttributeError: module ‘gradio‘ has no attribute ‘ClearButton‘解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...
Kafka 集群如何实现数据同步?
哈喽大家好,我是咸鱼 最近这段时间比较忙,将近一周没更新文章,再不更新我那为数不多的粉丝量就要库库往下掉了 T﹏T 刚好最近在学 Kafka,于是决定写篇跟 Kafka 相关的文章(文中有不对的地方欢迎大家指出)…...
一本了解生成式人工智能
上周,发了一篇关于大语言模型图数据库技术相结合的文章,引起了很多朋友的兴趣。当然了,这项技术本身就让俺们很兴奋,比如我就是从事图研发的,当然会非常关注它在图领域的应用与相互促就啦。 纵观人类文明历史ÿ…...
git 相关指令总结(持续更新中......)
文章目录 一、git clone 相关指令1.1 clone 指定分支的代码 一、git clone 相关指令 1.1 clone 指定分支的代码 git clone -b 分支名 仓库地址...
windows 安装 Oracle Database 19c
目录 什么是 Oracle 数据库 下载 Oracle 数据库 解压文件 运行安装程序 测试连接 什么是 Oracle 数据库 Oracle数据库是由美国Oracle Corporation(甲骨文公司)开发和提供的一种关系型数据库管理系统,它是一种强大的关系型数据库管理系统…...
【数据结构】图的存储结构(邻接矩阵)
一.邻接矩阵 1.图的特点 任何两个顶点之间都可能存在边,无法通过存储位置表示这种任意的逻辑关系。 图无法采用顺序存储结构。 2.如何存储图? 将顶点与边分开存储。 3.邻接矩阵(数组表示法) 基本思想: 用一个一维数…...
kubernetes--Pod控制器详解
目录 一、Pod控制器及其功用: 二、pod控制器的多种类型: 1、ReplicaSet: 1.1 ReplicaSet主要三个组件组成: 2、Deployment: 3、DaemonSet: 4、StatefulSet: 5、Job: 6、Cronjob: …...
九、Linux用户管理
1.基本介绍 Linux系统是一个多用户多任务的操作系统,任何一个要使用系统资源的用户,都必须首先向系统管理员申请一个账号,让后以这个账号的身份进入系统 2.添加用户 基本语法 useradd 用户名 应用案例 案例1:添加一个用户 m…...
springboot项目中没有识别到yml文件解决办法
springboot项目中没有识别到yml文件解决办法 ![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传] 1、这个意思就是没有配置数据库的数据源路径。所以需要配置数据源,比如mysql的驱动和路径。检查是否在properties或者yml文件中是否已经配置好。…...
[管理与领导-125]:一个IT人的思考:职场中、人际交往中,不要为他人的不良行为和言语买单,不要让自己的情绪被外界影响或掌控。
目录 前言: 一、是什么What 二、为什么Why? 三、怎么办How? 前言: 无论是职场中,还是人际交往中,我们的难免受到他人的影响,有积极正面的情绪影响,有消极负面的情绪影响。为什么我们自身的情绪会受到…...
【FPGA】IP核
一.IP核是什么 IP:知识产权,半导体产业中:在ASIC和FPGA中定义为预先设计好的电路功能模块。 在使用的时候其他用户可以直接调用IP核心。 二. 为什么要是有IP核 提高开发效率,减小设计和调试的时间,加速开发进程&am…...
吾爱破解置顶的“太极”,太好用了吧!
日常工作和娱乐,都需要用到不同类型的软件,哪怕软件体积不大,也必须安装,否则到用时找不到就非常麻烦了。 其实,很多软件不一定一样不剩地全部安装一遍,一方面原因是用的不多,另一方面多少有点…...
Postman接收列表、数组参数@RequestParam List<String> ids
示例如下: 接口定义如下: GetMapping(value "/queryNewMoviePath")public List<Map<String, Object>> queryNewMoviePath(RequestParam List<String> ids ) {return service.queryNewMoviePath(ids);}postman中测试如下: http://loc…...
qemu + busybox + 内核实验环境搭建(2023-11)
主要是参考网上的例子,网上的一些例子可能用的busybox 老旧,编译各种问题,以及rootfs hda的方式或者ramfs的方式。可能有些概念还是不清楚,以下是最终完成测试成功的案例。 下载kernel https://cdn.kernel.org/pub/linux/kernel…...
JavaScript管理HTMLDOM元素(增删改查)
本文主要讲解JavaScript如何通过管理HTML上的DOM元素,其中包括如何查询、创建、修改以及删除具体功能和源码讲解。 增加 首先我们准备一个HTML框架和简单CSS样式,我对其中元素作用和关系进行一个简单说明。 <!DOCTYPE html> <html><he…...
RE2文本匹配实战
引言 今天我们来实现RE2进行文本匹配,模型实现参考了官方代码https://github.com/alibaba-edu/simple-effective-text-matching-pytorch。 模型实现 RE2模型架构如上图所示。它的输入是两个文本片段,所有组件参数除了预测层和对齐层外都是共享的。上图…...
实在智能携手中国电信翼支付,全球首款Agent智能体亮相2023数字科技生态大会
11月10日-13日,中国电信与广东省人民政府联合主办的“2023数字科技生态大会”在广州隆重举行。本届大会以“数字科技焕新启航”为主题,邀请众多生态合作伙伴全方位展示数字科技新成果,包括数字新消费、产业数字化、智能电子、人工智能大模型等…...
安全框架springSecurity+Jwt+Vue-1(vue环境搭建、动态路由、动态标签页)
一、安装vue环境,并新建Vue项目 ①:安装node.js 官网(https://nodejs.org/zh-cn/) 2.安装完成之后检查下版本信息: ②:创建vue项目 1.接下来,我们安装vue的环境 # 安装淘宝npm npm install -g cnpm --registryhttps:/…...
React整理总结(三)
1.props和state的更新 父组件重新render时,所有的子组件也会调用render()函数。shouldComponentUpdate(nextProp, nextState) shouldComponentUpdate(nextProps, nextState) {if (equal(nextProps, this.props) && equa…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
uniapp 小程序 学习(一)
利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 :开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置,将微信开发者工具放入到Hbuilder中, 打开后出现 如下 bug 解…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...
TCP/IP 网络编程 | 服务端 客户端的封装
设计模式 文章目录 设计模式一、socket.h 接口(interface)二、socket.cpp 实现(implementation)三、server.cpp 使用封装(main 函数)四、client.cpp 使用封装(main 函数)五、退出方法…...



