【C语言】模拟实现库函数qsort

qsort的头文件是stdlib.h

他的四个参数分别是要进行排序的数组base的首地址,base数组的元素个数,每个元素的大小,以及一个函数指针,这个函数指针指向了一个函数,这个函数的参数是两个void*类型的指针,返回类型是int,要求这个函数能够比较参数(这个函数的参数是两个指针)指向的两个元素的大小,规定如果elem1指向的元素比elem2指向的元素大,那这个函数就返回一个大于零的数,反之就返回一个小于零的数,如果elem1和elem2指向的元素一样大,就返回0。

void*类型的指针可以接收任何类型的地址,但是不能直接解引用,由于我们不知道未来要比较的两个函数是什么类型的,那就只能写成void*类型,就可以接收任何类型了,在解引用之前强制类型转换即可。

qsort默认是以升序排列的(如果要降序排列,只需要比较大小的函数返回值上用相反的逻辑即可,比如elem1指向的元素如果比elem2大,就返回一个小于零的数),并且可以排列任何类型的数组。来看一个例子

下面我们将使用回调函数模拟实现qsort,由于目前没有学习快速排序,因此使用冒泡排序代替。

模拟实现,我们就把参数设置成和库函数qsort一样,最后一个函数指针指向的是一个能比较两个元素大小的函数,需要使用者自己编写。

我们排序使用的是冒泡排序的思想,就是比较相邻的两个元素,如果前面比后面大,就交换,那现在的问题是当时冒泡排序是针对整形数组的,比较就是直接base[j]和base[j+1]进行比较即可,但是现在我们想要这个my_sort类型能够对任意类型的数据进行排序,就不能简单的写成base[j]和base[j+1],因为我们连base的类型都不知道,当然也不知道+1会跳过几个字节,也就不知道+1是不是拿到了和base[j]相邻的元素。那么我们干脆一个字节一个字节的操作,因为不管什么类型,大小至少也是一个字节,那如何操作一个字节?很简单,使用char类型的指针即可。因此不管base代表什么类型的数组,我们都先把base强制类型转换成char*类型,那么base[j]其实就是(char*)base+j*size,与他相邻的元素就是(char*)base+(j+1)*size。

这样我们就拿到了要比较的两个元素,但是这两个元素如何比较?直接使用大于号显然是不合理的,这时候就用到了我们的第四个参数,cmp函数,我们需要自己写一个能够比较两个元素大小的函数,并且规定如果前者大,就返回一个大于0的数,反之就返回一个小于0的数,如果二者相等,就返回0。

通过判断cmp函数的返回值,我们就知道了需不需要交换这两个元素。那问题又来了,如何交换?直接创建临时变量吗?那临时变量是什么类型的呢?但是要交换的数据是什么类型,他们最小也有一个字节,那么我们直接一个字节一个字节的交换就行,什么时候才算交换结束呢?当然是交换完size个字节后,就结束了。如图是swap函数的交换

这样我们的my_sort函数就可以正常使用了,比如我们要排序的是一个整形数组,我们就要去写一个能够比较两个整形数据的函数,比如这样写

如果我们要比较两个结构体类型的数据呢?

假如结构体类型是这样的

如何比较两个struct stu类型变量的大小?

由于上面的结构体类型含有两个成员变量,那么要比较struct sut类型变量的大小,就可以按照name的大小来进行比较,也可以按照age的大小进行比较,当然如果按照name的大小来进行比较,就不能直接相减了,因为字符串的比较是用库函数strcmp,这个库函数的返回值逻辑与我们的cmp函数一致,也是前者大就返回大于零的数,后者大就返回小于零的数,一样大就返回0,因此我们如果按照name的大小来比较的话,直接返回strcmp的值就可以,如图

注:由于空指针是无法进行解引用操作的,因此我们在写cmp函数的时候都需要进行强制类型转换,要比较的是什么类型的,就强制类型转换成对应的指针。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

容斥原理基础

文章目录 容斥原理的引入从集合的角度考虑推广例子不被2、3、5整除的数错排问题求不定方程的解Devu和鲜花 容斥原理的引入 从一个小学奥数问题引入: 一个班级有50人 喜欢语文的人有20人 喜欢数学的人有30人 同时喜欢语文数学的人有10人。 问题: 两门都不…

nodeJS 的 npm 设置国内高速镜像之淘宝镜像的方法

1、我们知道 nodeJS 是老外搞出来的,服务器放在了国外,国内的小朋友访问起来会比较慢,阿里巴巴的淘宝给出了有力支持,现在我们就将 nodeJS 的镜像地址切换为国内的淘宝镜像。 2、查看当前的镜像地址: npm get registr…

百家cms代审

环境搭建 源码链接如下所示 https://gitee.com/openbaijia/baijiacms 安装至本地后 直接解压到phpstudy的www目录下即可 接下来去创建一个数据库用于存储CMS信息。(在Mysql命令行中执行) 接下来访问CMS,会默认跳转至安装界面 数据库名称和…

基于 Python 的漏洞扫描系统,附源码

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…

学习笔记——ENM模拟

学习笔记——ENM模拟 文章目录 前言一、文献一1. 材料与方法1.1. 大致概念1.2. 生态模型的构建1.2.1. 数据来源:1.2.2. 数据处理:1.2.3. 模型参数优化: 1.3. 适生情况预测1.3.1. 预测模型构建1.3.2. 适生区划分 1.4. 模型的评估与验证 2. 结果…

Redis事务和Redis管道

文章目录 1.Redis事务1.1 Redis事务是什么,能干嘛?1.2 Redis事务和数据库事务的差异1.3 Redis事务的相关命令 2.Redis管道2.1 Redis管道是什么2.2 管道与原生批量命令对比2.3 管道与事务对比2.4 使用管道注意事项 1.Redis事务 1.1 Redis事务是什么&…

Kubernetes基础(十四)-Cluster Autoscaler

Kubernetes 给出的解决方案就是:自动伸缩(auto-scaling),通过自动伸缩组件之间的配合,可以 7*24 小时的监控着k8s集群,动态变化负载,以适应用户需求。 1 自动伸缩组件 1.1 自动伸缩类型 1.1.…

构建中国人自己的私人GPT—支持中文

上一篇已经讲解了如何构建自己的私人GPT,这一篇主要讲如何让GPT支持中文。 privateGPT 本地部署目前只支持基于llama.cpp 的 gguf格式模型,GGUF 是 llama.cpp 团队于 2023 年 8 月 21 日推出的一种新格式。它是 GGML 的替代品,llama.cpp 不再…

Octave实现位置式PID算法

由于Matlab不让用,只能“你不让爷用,爷就用别的”,选择开源的Octave以及scilab进行相关领域的学习。Octave的代码和Matlab几乎是100%相同的,只有一些专用的包的函数,可能有些还没来得及写,或者有些差异。但…

测试管理_利用python连接禅道数据库并自动统计bug数据到钉钉群

测试管理_利用python连接禅道数据库并统计bug数据到钉钉 这篇不多赘述,直接上代码文件。 另文章基础参考博文:参考博文 加以我自己的需求优化而成。 统计的前提 以下代码统计的前提是禅道的提bug流程应规范化 bug未解决不删除bug未关闭不删除 db_…

【开源】SpringBoot框架开发校园电商物流云平台

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 商品数据模块2.3 快递公司模块2.4 物流订单模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 商品表3.2.2 快递公司表3.2.3 物流订单表 四、系统展示五、核心代码5.1 查询商品5.2 查询快递公司5.3 查…

5.1 灯光色彩与视觉

5.1 灯光色彩与视觉 视觉成像 灯光与物体的反应:吸收,反射和折射 色彩:光照到物体上,物体吸收其他光源色,只反射该颜色光,所以物体 表面呈现该颜色 视觉:该颜色光进入人眼刺激感光细胞,并在视网膜上形成影像. ABSORBTION 一、基础灯光 1.环境光(Ambient Light…