qsort函数用法 + 模拟实现qsort函数

👦个人主页:@Weraphael

✍🏻作者简介:目前是C语言学习者

✈️专栏:【C/C++】算法
🐋 希望大家多多支持,咱一起进步!😁
如果文章对你有帮助的话
欢迎 评论💬  点赞👍🏻 收藏 📂 加关注😍


前言:

往期我们学习了二分查找、归并排序、快速排序和冒泡排序。今天我们学习qsort函数,qsort函数是C语言库中实现的快速排序算法。并且qsort要求提供一个自己定义的比较函数。比较函数使得qsort通用性更好,qsort函数可以实现对数组、字符串、结构体等结构进行升序或降序排序。闲言少叙,开快车🚝🚝

目录

一、qsort函数简介

二、qsort函数的使用

                1、对int类型数组排序

                2、对char类型排序

                3、对浮点型排序

                4、对结构体类型排序

三、模拟实现qsort函数

                1、代码详解

                2、 代码实现之整型排序

                3、代码实现之结构体类型排序

四、总结


一、qsort函数简介

对于陌生的库函数,可通过cplusplus网站来了解它

【qsort参数介绍】

【比较函数的返回值】

​ 

 所以,qsort函数大致的模板为

int compare(const void* p1, const void* p2) //
{return p1 - p2; //返回的是升序return p2 - p1; //返回的是降序   //注:p1和p2的类型根据实际情况写
}int main()
{int arr[] = { 1,3,4,6,7,2,10,8,5,9 };int sz = sizeof(arr) / sizeof(arr[0]);//计算数组元素个数 40 / 4 = 10qsort(arr, sz, sizeof(arr[0]), compare);//arr - 指向要排序的数组的第一个元素的指针。//sz -  由 arr 指向的数组中元素的个数//sizeof(arr[0]) - 数组中每个元素的大小,以字节为单位。//compar - 用来比较两个元素的函数。return 0;
}

Q:为什么compare的形参的两个参数是void*类型?

因为qsort函数可以实现对数组(int)、字符串(char)、结构体(stuct)等类型进行升序或降序排序,而void*是不介意类型的,就像一个“垃圾桶”,任意的类型的地址都能往void*塞,但就是不能对其直接使用(解引用操作,++,--等等)。若想使用,只要进行强制类型转化即可。

二、qsort函数的使用

1、对int类型数组排序

【升序情况】

//升序的情况
#include <stdlib.h>  //使用qsort需要包含头文件
#include <stdio.h>  
int compare_int(const void* p1, const void* p2) 
{return *(int*)p1 - *(int*)p2; //强制类型转化并解引用
}int main()
{int arr[] = { 1,3,4,6,7,2,10,8,5,9 };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), compare_int);for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}

【程序结果】

【降序情况】

//降序的情况
#include <stdlib.h>  //使用qsort需要包含头文件
#include <stdio.h>  
int compare_int(const void* p1, const void* p2) 
{return *(int*)p2 - *(int*)p1; //强制类型转化并解引用
}int main()
{int arr[] = { 1,3,4,6,7,2,10,8,5,9 };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), compare_int);for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}

2、对char类型排序

//升序的情况
#include <stdio.h>
#include <stdlib.h>int compare_char(const void* p1, const void* p2) 
{return *(char*)p1 - *(char*)p2; //强制类型转化并解引用
}int main()
{char arr[] = { 'f', 'b','e','a','d','c'};int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), compare_char);for (int i = 0; i < sz; i++){printf("%c ", arr[i]);}return 0;
}

 【程序结果】

3、对浮点型排序

#include <stdio.h>
#include <stdlib.h>int compare_double(const void* p1, const void* p2) 
{return (*(double*)p1 > *(double*)p2 ? 1 : -1); //三目操作符
}int main()
{double arr[] = { 3.14,2.6,2.3,1.7};int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), compare_double);for (int i = 0; i < sz; i++){printf("%lf ", arr[i]);}return 0;
}

注意

用qsort对浮点型的一定要用三目运算符,由于浮点数的精度问题,如果是两个很接近的数相减,则可能返回一个接近0的小数,而compare_double的返回值是int型,因此会将这个小数返回0。

4、对结构体类型排序

【按姓名排序】

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Stu
{char name[20];int age;
};int compare_name(const void* p1, const void* p2)
{return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}int main()
{struct Stu s[3] = { {"张三",10},{"李四",30},{"王五",21} };int sz = sizeof(s) / sizeof(s[0]);qsort(s, sz, sizeof(s[0]), compare_name);for (int i = 0; i < sz; i++){printf("%s %d\n", s[i].name, s[i].age);}return 0;
}

【程序结果】

注意

姓名是字符串,比较的是字典序大小,要用strcmp

比较年龄和比较整型一样,这里就不为大家展示了 

 三、模拟实现qsort函数

模拟实现qsort函数是要基于冒泡排序实现的    (冒泡排序讲解)

【冒泡排序的实现】

#include <stdio.h>
void Sort(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]){int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}}
}
int main()
{int arr[] = { 2,6,8,7,6,0,1,5,9,3 };int sz = sizeof(arr) / sizeof(arr[0]);Sort(arr, sz);for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}

现要求改造冒泡排序,使整个函数可以排序任意类型的数组

以整型数组为例

【主函数部分】

#include <stdio.h>
int cmp_int(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;
}int main()
{ int arr[] = { 2,6,8,7,6,0,1,5,9,3 };int sz = sizeof(arr) / sizeof(arr[0]);Sort(arr, sz, sizeof(arr[0]), cmp_int); for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}

【Sort函数部分】

参考qsort函数的参数

void Swap(char* x1, char* x2, int width)
{//因为不知道是什么类型,要一个字节一个字节交换for (int i = 0; i < width; i++){char tmp = *x1;*x1 = *x2;*x2 = tmp;x1++;x2++;}
}//void* base - 要求排序不同类型的数组,void*恰好能接收任意类型
//int sz - 元素个数
//int width - 一个元素的大小
//int (*p)(const void*, const void*)  函数传参函数指针接收
//size_t - 无符号整型void Sort(void* base, size_t sz, size_t width, int (*p)(const void*, const void*))
{for (size_t i = 0; i < sz - 1; i++){for (size_t j = 0; j < sz - 1 - i; j++){//通过函数指针p调用的函数cmp_int,所以这是个回调函数if (p((char*)base + j * width,(char*)base + (j + 1) * width) > 0){//写一个Swap函数来交换Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);}}}
}

【代码详解】

 【代码实现之整型排序】

int cmp_int(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;
}void Swap(char* x1, char* x2, int width)
{for (int i = 0; i < width; i++){char tmp = *x1;*x1 = *x2;*x2 = tmp;x1++;x2++;}
}void Sort(void* base, size_t sz, size_t width, int (*p)(const void*, const void*))
{for (size_t i = 0; i < sz - 1; i++){for (size_t j = 0; j < sz - 1 - i; j++){if (p((char*)base + j * width,(char*)base + (j + 1) * width) > 0){Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);}}}
}int main()
{ int arr[] = { 2,6,8,7,6,0,1,5,9,3 };int sz = sizeof(arr) / sizeof(arr[0]);Sort(arr, sz, sizeof(arr[0]), cmp_int); for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}

【程序结果】

【代码实现之结构体类型排序】 

以排列姓名为例

struct Stu
{char name[20];int age;
};
int compare_name(const void* p1, const void* p2)
{return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}void Swap(char* x1, char* x2, int width)
{for (int i = 0; i < width; i++){char tmp = *x1;*x1 = *x2;*x2 = tmp;x1++;x2++;}
}void Sort(void* base, size_t sz, size_t width, int (*p)(const void*, const void*))
{for (size_t i = 0; i < sz - 1; i++){for (size_t j = 0; j < sz - 1 - i; j++){if (p((char*)base + j * width,(char*)base + (j + 1) * width) > 0){Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);}}}
}int main()
{ struct Stu s[3] = { {"张三",10},{"李四",30},{"王五",21} };int sz = sizeof(s) / sizeof(s[0]);Sort(s, sz, sizeof(s[0]), compare_name);for (int i = 0; i < sz; i++){printf("%s %d\n", s[i].name,s[i].age);}return 0;
}

【程序结果】

四、总结 

本章重点讲解qsort函数用法以及如何模拟实现qsort函数,如果这篇博客对你有帮助,别忘了评论、点赞 、收藏、关注哟😘

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

C语言qsort函数用法

qsort函数简介 排序方法有很多种&#xff1a;选择排序&#xff0c;冒泡排序&#xff0c;归并排序&#xff0c;快速排序等。 看名字都知道快速排序是目前公认的一种比较好的排序算法。因为他速度很快&#xff0c;所以系统也在库里实现这个算法&#xff0c;便于我们的使用。 这就…

qsort函数讲解

qsort函数的作用是将所有数据排序&#xff0c;那么它和普通的冒泡排序或者选择排序有什么区别呢&#xff1f;它不仅仅可以排序数组中的数字&#xff0c;还可以排序结构体。当然升序和降序它都支持&#xff0c;不过输入参数的顺序会有所不同&#xff0c;下面我们来详细讲解一下这…

【C语言】qsort函数的使用和模拟实现

本篇文章我们来了解一下回C语言中qsort函数的使用方法和模拟实现。这是一个通用性很强而且非常方便的库函数&#xff0c;通过这篇文章希望能让你了解sort函数。 目录 一、qsort的介绍&#xff1a; 二、qsort函数的使用 1.qsort排序整形 2.qsort排序字符串 3.qsort排序结…

C语言之——快速排序qsort库函数的讲解

qsort函数C语言编译器函数库自带的排序函数&#xff0c;也叫快速排序函数。之前我写过一篇关于冒泡排序的代码讲解&#xff0c;大家感兴趣的话可以先看一看我对于冒泡排序的讲解。 相比较于冒泡排序&#xff0c;快速排序可以用更加快捷的速度去排列升降序&#xff0c;它的时间复…

C语言qsort函数使用方法大全

文章目录 一、qsort函数简介二、qsort函数常用实例1.比较整型数组2.比较char数组3.比较double数组4.比较字符串4.1按首字母排序4.2按长度排序4,3按字典顺序 5.结构体排序5.1 多级排序 三、qsort深度剖析 一、qsort函数简介 排序方法有很多种&#xff1a;选择排序&#xff0c;冒…

C语言-qsort函数详解

目录 一.qsort函数是什么 二.使用qsort排序-以升序为例 关于void*型指针&#xff1a; 1.整形数组排序 2.字符数组排序 3.字符指针数组排序 4.结构体数组排序 5.浮点型数组排序 三.使用冒泡排序思想模拟实现qsort函数 1.什么是冒泡排序&#xff1a; 2.冒泡排序代码 3. …

C语言qsort()函数的使用(详解)

目录 1.参数含义 1.首元素地址base 2.元素个数num 3.元素大小size 4.自定义比较函数compar 2.使用方式 1.头文件 2.compar的实现 3.整体代码 qsort&#xff08;&#xff09;函数&#xff08;quick sort&#xff09;是八大排序算法中的快速排序&#xff0c;能够排序任意…

虚幻4地形怎么增加层_虚幻周报20200407 | 在家也要好好工作呀~

官方知乎号&#xff1a;虚幻引擎 搜集日期&#xff1a;20200330-20200405 整理编辑&#xff1a; 大钊&#xff0c;小辉辉&#xff0c;马古斯&#xff0c;小帅帅 声明&#xff1a;文档搜集来自网上&#xff0c;难免遗漏&#xff0c;请联系我们投稿和添加关注。该文档版权归整理…

2020年笔记本电脑选购指南

**本文首发微信公众号陈蛋蛋碎碎念&#xff0c;获取更多软件、教程、模板资源&#xff0c;请关注公众号。 最近在群里有小伙伴问关于选购电脑的事&#xff0c;毕竟开学季又要到了。刚好蛋蛋现在又在3C公司工作&#xff0c;所以平时也需要了解这方面的知识&#xff0c;于是就准…

[转]Warzone 2100(战争地带2100)

发行公司&#xff1a;Eidos Interactive 开发公司&#xff1a;Pumpkin Studios 游戏类型&#xff1a;即时战略 游戏语言&#xff1a;英文 发行日期&#xff1a;1999 年4月 系统操作&#xff1a;Win95以上 伴随着这部来自英国开发公司Pumpkin Studios的作品&#xff0c;1999年…

显卡优化软件测试面试,是吹嘘还是真有用?NV游戏优化软件测试

1前言&#xff1a;NVIDIA游戏优化软件试用 英伟达真实热衷为用户提供出色的游戏方案&#xff0c;日前发布了一款GeForce Experience的新软件&#xff0c;本质上是一个基于云端的服务&#xff0c;旨在分析你的硬件并自动调整显示分辨率和游戏设置&#xff0c;以提供更好更优化的…

【转】为什么中国不会有3A游戏

编&#xff1a;王妙一&#xff0c;游戏开发者&#xff0c;代表作《WILL&#xff1a;美好世界》&#xff0c;曾获第二届PlayStation开发者大赛冠军。王妙一大学时就读于清华软件学院图形研究所&#xff0c;本文将从游戏图形技术的发展变迁开始&#xff0c;谈谈3A游戏在现今&…

FPS游戏

FPS 求助编辑百科名片 FPS FPS是第一人称射击类游戏的简称&#xff08;游戏专有名词&#xff09;。 FPS&#xff08;First-Person Shooter Game&#xff09;&#xff1a;第一人称射击游戏 严格来说FPS属于ACT类游戏的一个分支&#xff0c;但和RTS类游戏一样&#xff0c;由于其在…

Centos6.5环境Nginx 1.16.1升级到1.24.0版本

一、背景 2023年4月11日&#xff0c;官方发布了Nginx最新稳定版&#xff0c;版本号为 1.24.0。该版本是基于1.23.x&#xff08;1.23.0 - 1.23.4&#xff09;开发版的Bug修复&#xff0c;以及一些新特性的加入&#xff0c;而形成的稳定版。安全部门扫描后&#xff0c;发现现场不…

C++11 -- 包装器

文章目录 function包装器function包装器的概念function的运用function实例化使用function解决逆波兰表达式 bind包装器bind包装器相关介绍bind绑定函数固定参数 function包装器 function包装器的概念 function包装器,也叫做适配器,它的本质是一个类模板. 例如: 1 template&l…

chatgpt赋能python:Python中撤销的快捷键

Python中撤销的快捷键 在编程中&#xff0c;我们经常需要进行调试&#xff0c;不可避免地会出现一些错误&#xff0c;这时候撤销 (Undo) 功能就显得尤为重要。在 Python 中&#xff0c;我们可以使用一些快捷键来快速撤销&#xff0c;本文将会介绍这些快捷键的使用以及使用它们…

chatgpt赋能python:Python中的构造函数

Python 中的构造函数 Python 是一门广泛应用于各种应用领域的高级编程语言&#xff0c;它支持不同的编程范式&#xff0c;包括面向对象编程。在面向对象编程中&#xff0c;构造函数是一个重要的概念。本文将介绍 Python 中的构造函数&#xff0c;并介绍如何使用它们来创建对象…

淘宝店铺老店标识怎么显示 怎么淘宝老店标识申请

我们在很多时候都喜欢去一个淘宝开的时间比较长的店铺去购买商品&#xff0c;因为这样的店铺可能在信誉度这一块会更加能够让人信服&#xff0c;因为一个店铺能开这么久&#xff0c;肯定还是证明这个店铺拥有一定的实力。淘宝店铺老店标识怎么显示 怎么淘宝老店标识申请 在回答…

22-0001 淘宝店铺搜索界面

淘宝店铺搜索界面 1.元素2.过程2.1 搜索界面的网页源码2.2 通过Chrome控制台获取sellerid2.3 搜索链接2.4 控制台 3.总结 1.元素 获取店铺搜索界面每个店铺的’sellerid’ 备注&#xff1a;通过sellerid可以在下面链接中获取买家秀的图片&#xff0c;也可以使用相关软件进行下…

淘宝开店指南——店铺设置篇

目录 店铺基本设置店铺装修手机店铺装修PC 店铺装修 保证金管理客服&#xff08;子账号&#xff09;管理创建子账号修改子账号权限 店铺基本设置 通过千牛主账号工作台左侧点击【店铺】->选择【店铺信息进入】。 设置链接&#xff1a;点击访问 可设置内容&#xff1a; 个…