qsort函数详解以及模拟实现

  • 一.qsort函数是什么
  • 二.具体的使用
    • 1.参数4(参数3在模拟实现时解释)
    • 2.例子
      • 1.排序整形
      • 2.排序结构体
  • 三.模拟实现qsort
    • 1.参数3
    • 2.模拟排序
      • 1.排整形
      • 2.排结构体

一.qsort函数是什么

这里会使用到函数指针,如果还不太了解的话可以看看这篇博客指针进阶

qsort全称为quick_sort(快速排序),为什么这么称呼呢?因为它实现的内核就是依靠快排来实现的。但与单纯的快排不同的是,它是库函数并且可以排序任意类型的数据(整数,字符,结构体,字符串…)。

接下来再MSDN里详细看看它的全貌

可以看到它的头文件是stdlib.h,并且参数很多接下来会详细解析。

base

第一个参数是base,在MSDN里的解释是Start of target array。也就是目标数组的开始。

第一个参数传目标数组的起始位置。

num

第二个参数是num,在MSDN里的解释是Array size in elements。也就是数组的大小。

第二个参数传数组的大小。

第三个参数是width,在MSDN里的解释是Element size in bytes。也就是每个成员的大小。

第三个参数是每个元素占的字节大小。

第四个参数是一个函数指针指向compare。在MSDN里的解释是Comparison function。也就是比较功能。

第四个参数传一个函数指针,它所指向的函数要具备比较功能。

二.具体的使用

1.参数4(参数3在模拟实现时解释)

关于函数的参数,参数1,2自然不必多说(要排序自然得知道起始位置和数组大小)。对于参数4,如果我们只需要比较整形,我们自然可以只是向上面的冒泡排序一样直接使用大于比较,但如果是一个字符串呢?如果是一个结构体呢?那么我们当然不能简单的用大于小于这些符号来比较,我们需要自己写一个判断规则,这就是参数4的意义。明确判断规则。也是qsort能排序任意类型数据的关键。

详细说明参数4需要的参数

1.e1是你需要比较元素的第一个元素的地址,e2是另一个元素的地址。
2.两个参数的类型都是const void *
3.const是为了防止参数在函数内部被改变
4.void*是无具体类型的指针(下面重点说明一下)

但对于这个函数来说肯定是需要接收不同类型的指针的,各。void*是通用指针。好处是可以接收各种指针,坏处是不能直接解引用,因为连它自己都不知道自己是什么类型。


2.例子

1.排序整形

上面说到void*不能直接解引用,所以需要我们进行强制转换。这样才能够使用。ps:由于参数4是函数指针,所以我们应该传函数地址,函数名就表示函数地址。

这个函数总得有返回值吧,来看看MSDN。

如果第一个元素小于第二个元素,返回一个小于0的数。如果相等则返回0;如果大于,则返回大于0的数。那么我们就按照它的要求书写。

来看看结果。

当然以上是升序,如果想要降序的话直接调个方向就可以了。

2.排序结构体

首先按照年龄排成升序

可以看到确实按照年龄的升序来排列的。

按照名字来排列

名字是字符串不能直接使用减号,需要用到strcmp。它是按照对应位置字符大小来比较的。

我们知道该函数需要返回数字,而恰好strcmp满足这个要求。所以我们只需要直接返回strcmp就可以了(注意头文件是string.h)。


由于l<w<z,所以排序应该是lisi,wangwu,zhangsan,也可以看到确实是这样排序的。

总结:需要排列什么数据取决于参数4所指向的函数如何判断。

三.模拟实现qsort

上文提到qsort是依托快排实现的,但由于快排有些复杂,这里就使用冒泡排序作为内核。(如果还有些不明白的可以看看这篇博客 冒泡排序)

这是一个简易的冒泡排序,它也能够排列数据。但与qsort不同的是,它只能排列整数。所以接下来我要改造它,使它能够排列任意数据。(ps:这里目前不考虑时间,空间,稳定性之类的)。

上文说过,qsort能排列任意数据,关键在于你写的判断函数,也就是参数4。所以我们也应当对冒泡排序的判断条件进行修改。将它封装为一个函数。

既然我们要模拟qsort,那么参数也应当于qsort保持一致。ps:为什么要传这些参数,开头已经说过,但参数3还未说过,接下来讲解为什么要传每个元素的宽度。

1.参数3

1.首先我们第一个参数是void * ,也就是我们根本不知道到底传递的是什么类型,我们需要参数3来确定是哪种类型。
2.方便我们找到每个元素(具体使用请看模拟过程)

2.模拟排序

再次说明参数4是函数指针,它所指向的函数就是我们所写的判断规则,再根据cmp的返回值,如果大于0我们就交换两个数据。接下来的关键是我们如何给cmp传参,也就是我们如何精确的找到这两个元素,然后进行判断。

冒泡排序的内核是相邻两个元素两两进行比较,所以我们com里也应该两两相邻元素进行比较。由于我们根本不知道数据类型,不能使用下标来算,需要用地址来间接寻找,这也体现出了参数3的作用。

接下来是如何交换,由于类型不明,我们肯定不能直接交换。但是无论什么元素它的单位都是字节,那么我们可以一个字节一个字节的交换,写一个交换函数挨个交换它们的字节。

以上就是模拟实现的qsort,任意数据都可以排序,接下来来验证一下。

1.排整形

2.排结构体

按年龄

按名字

总结:由于qsort需要适合各种类型,所以我们传参除了部分明确的外都是void。qsort如何精确的找到两个数依赖于数据的地址。不同类型数据的比较方法是不同的,所以需要我们自己写判断规则。

以下是判断结构体学生名字的全部代码


void Swap(char* buf1, char* buf2, int width)//由于我们已经强转为char*了,这里就已经明确类型了
{for (int i = 0; i < width; i++){char tmp = *buf1;*buf1 = *buf2;*buf2 = tmp;buf1++;buf2++;}
}void bubble_sort(void*base,size_t sz,size_t width,int(*cmp)(const void*e1,const void*e2))
{size_t i = 0;size_t j = 0;size_t tmp = 0;for (i = 0; i < sz - 1; i++){                                        for (j = 0; j < sz - 1 - i; j++){if (cmp((char*)base+j*width,(char*)base+(j+1)*width)>0){                                                      Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);//要交换字节,除了两个元素外肯定还得知道它们的大小}}}
}struct stu
{char name[20];int age;
};
int cmp_stu_name(const void* e1, const void* e2)
{return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}int main()
{struct stu s[3] = { {"zhangsan",20},{"lisi",40},{"wangwu",33} };bubble_sort(s, 3, sizeof(s[0]), cmp_stu_name);return 0;
}

qsort函数详解以及模拟实现相关推荐

  1. 冒泡排序和qsort函数详解以及如何模拟实现qsort函数

    一.冒泡排序 冒泡排序是一种常见的排序方式,它可以把数组元素有序或无序的数组进行重新排序,并使得数组中的元素从大到小或从小到大进行排序(就像泡泡一样). 冒泡排序原理: 每次比较数组中的相邻的两个元素 ...

  2. 【C库函数】qsort函数详解

    目录 qsort ​ 函数基本原型 参数解读 函数详解 比较函数实现并解读 qsort函数排序代码实现并展示结果 1.排序整型数组 2.排序结构体 qsort 函数是基于快速排序算法实现的一个排序函数 ...

  3. 【C进阶】qsort函数详解

    ⭐博客主页:️CS semi主页 ⭐欢迎关注:点赞收藏+留言 ⭐系列专栏:C语言进阶 ⭐代码仓库:C Advanced 家人们更新不易,你们的点赞和关注对我而言十分重要,友友们麻烦多多点赞+关注,你们 ...

  4. C语言-qsort函数详解

    目录 一.qsort函数是什么 二.使用qsort排序-以升序为例 关于void*型指针: 1.整形数组排序 2.字符数组排序 3.字符指针数组排序 4.结构体数组排序 5.浮点型数组排序 三.使用冒 ...

  5. C语言qsort函数详解

    目录 一.qsort函数的使用 二.qsort函数的模拟 一.qsort函数的使用 快排函数qsort是C的库函数,它可以对输入的任何类型的数组排序,通过该函数的函数声明我们可以看出它的使用方法: 举 ...

  6. qsort()函数详解

    一.写在开头 1.1 本节内容 学习C语言中的qsort()函数. 二.qsort() 2.1 函数原型 void qsort(void *base,size_t nmemb,size_t size, ...

  7. C语言-qsort函数详解及使用例

    q s o r t ( ) qsort() qsort() 函数是C语言 srdlib.h 库中的排序函数.此函数使用快速排序算法,时间复杂度一般在 O ( l g ( n ) ) O(lg(n)) ...

  8. C语言 qsort()函数详解 (笔记)

    qsort函数,其声明在stdlib.h文件中,时间复杂度为n*log(n). 功能:使用快速排序例程进行排序 用法: void qsort(void *base, size_t nitems, si ...

  9. C语言 快速排序——qsort函数详解

    我们在使用冒泡排序法做题的时候,经常会遇到运算次数过多程序超时的情况,而且冒泡排序法只能对整形数组进行排序. 为了解决这些问题!就使用qsort函数吧! 目录 一.qsort函数使用方法 二.qsor ...

最新文章

  1. 选择排序算法实现思想个人理解
  2. valgrind的说明使用和原理
  3. javascript封装与多态的体现
  4. 教程Xcode 4下编译发布与提交App到AppStore
  5. comparator 多个条件控制_JUnit5学习之四:按条件执行
  6. QML工作笔记-使用QML中的Date将时间戳和指定格式时间互转
  7. php ci base url,CodeIgniter中base_url问题
  8. 无法安装Sql Server 2000时的解决方法.
  9. 关于equals和==的几个注意点
  10. VS2019 调用大漠插件免注册方法引发异常 0x00000000 处(位于 DMSPACE1.exe 中)引发的异常: 0xC0000005: 执行位置 0x00000000 时发生访问冲突。
  11. 硬盘检测重映射扇区计数失败
  12. linux格式化fat的命令,Linux磁盘格式化命令详解
  13. jQuery TreeGrid
  14. MD2中用于随机置换的S盒是如何生成的?
  15. python 作物识别_20行Python代码开发植物识别 app
  16. ORBSLAM2论文翻译
  17. php怎么截取中文第一个字符串,php中怎么截取中文字符串
  18. 每日刷题记录(十六)
  19. stata统计分析及行业应用案例分析_描述性统计分析的应用——基于描述性统计分析识别优质股票...
  20. 使用U盘+iso镜像文件安装windows10操作系统详细步骤

热门文章

  1. 使用loading动画让你的条件渲染页面更高级
  2. 搜索卫士保驾护航,开源轮子不裸奔
  3. 如何解决anaconda里面新建环境里打不开jupyter notebook
  4. 教程篇:《基础模块3》金蝶K3WISE15.0-账套管理;账套新增 删除 备份详细步骤
  5. 1h-8学习(1):1h-8适配之int8直接量化+转.cambricon格式
  6. 如何打印CAD图纸中的一部分?CAD图纸打印教程分享
  7. 交朋友这事,我觉得算是我们能自己控制的改变命运的方法之一
  8. Linux——安装mysql数据库
  9. 如何把U盘设置为电脑锁
  10. ios开发学习笔记(这里一定有你想要的东西,全部免费)