【算法】C程序超详细的qsort排序函数解释和模拟
C程序利用冒泡排序的思想模拟实现qsort排序函数
求个赞求个赞求个赞求个赞 谢谢
先赞后看好习惯 打字不容易,这都是很用心做的,希望得到支持你 大家的点赞和支持对于我来说是一种非常重要的动力 看完之后别忘记关注我哦!️️️
前言:作者:Yu
常用c程序编译器:vs2019**
qsort函数的使用
在我们模拟实现它之前,我们先搞清楚它的用法。
我们先来看qsort函数的原型
void qsort (void* base, size_t num, size_t size,int (*cmp)(const void*, const void*));
/base存放的是待排序数据中第一个对象的地址, void无具体类型,所以
什么类型都可以/
//num代表数据个数
//size指的是一个元素有几个字节,我们知道类型决定一次访问跳过多少字节
//因为此处是void,我们是不知道一个元素是多少个字节的
//cmp函数是用来排序数据中的两个元素的函数
//假设写一个冒泡排序函数,排序字符串
//我们发现,相比于整形排序
//循环语句是一样的
//只有比较部分很交换部分可能不一样
//所以我们要使用函数指针
//该函数指针指向的函数,返回int,如果大于0,就大于,如果小于0,就小于
//就是这样设计的
我们先看看整个运用代码是怎么写的
int cmp_int(const void* e1, const void* e2)
{
return *(int*)e1 - *(int*)e2;
}
void test1()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);//求出数组元素的个数
qsort(arr, sz, sizeof(arr[0]), cmp_int);
for (int i = 0; i < 10; i++)
{
printf("%d\t", arr[i]);
}
}
int main()
{
test1();//排序整型
return 0;
}
在这个代码中,我们来逐个分析qsort函数里面四个参数
1,void *base
这个指的是我们要排列元素的数组的首元素地址,所以上面我们直接把arr传过去就好了
为什么使用void *类型?
使用void *类型使得我们这个qsort函数可以排序任何的类型的数据
2,size_t num
这个指的是数组元素的个数
3,size_t size
这个指的是每个元素的大小
为什么需要这个参数?
我们知道指针解引用的时候,或者数组里面需要访问元素的时候,我们需要直到一个元素所占的字节的大小,char类型1个字节,int类型4个字节…,qsort函数的作者为了让我们可以排序任何类型数据,所以我们需要这个参数,告诉计算机,我们一个元素是几个字节的。
4,int (cmp)(const void , const void* );
此处,是qsort函数的精髓,一个函数指针,qsort函数的作者在编写qsort函数的时候,他并不知道我们将来要用这个函数来给什么类型的数据排序,因此,qsort本身并不知道怎么去比大小,他不知道比大小的规则是什么(他并不知道3,4哪个大,因为他不知道这是什么类型的数据),因此我们我们写一个cmp(compare)函数,告诉我们的计算机,怎么去比大小。
因此,作为一个使用者,我们必须给计算机写一个cmp函数,告诉计算机怎么比,并返回一个int,int (*cmp)(const void*e1 , const void* e2);,如果这个int类型的返回值大于0,则计算机认为,e1比e2大,他就可以进行后续的排序了,反之亦然。
所以我们写了一个cmp函数
int cmp_int(const void* e1, const void* e2)
{
return *(int*)e1 - *(int*)e2;
}
注意,这里cmp函数的类型,一定要和上面qsort函数要求的类型一一对应
int (*cmp)(const void*e1 , const void* e2)
进到这个对比函数里头,我们在比较之前,我们是肯定要解引用的,但是,void类型怎么解引用呢,所以,我们要把它强制转化成int类型,这样就可以解引用并返回一个整型了。
最后我们将上面的函数整体使用的结果打印出来就可以了

以上便是我们qsort函数的使用
接下来,让我们一起来模拟它
我们使用的是冒泡排序的双循环的方法进行实现
我们先看一下普通冒泡排序的代码
void bubble_sort(int* arr, int sz)
{
int i = 0;
int 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] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz);
for (int i = 0; i < sz; i++)
{
printf("%d\t", arr[i]);
}
return 0;
}
我们准备使用的正是这种思想。
我们先来看完整代码
void swap(char* bulf1, char* bulf2, int width)
{
int i = 0;
for (i = 0; i < width; i++)
{
char tmp = *bulf1;
*bulf1 = *bulf2;
*bulf2 = tmp;
bulf1++;
bulf2++;
}
}
void qsort_by_bubble(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
{
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
for (j = 0; j < sz - 1 - i; j++)
{
if (cmp((char*)base+j*width,(char*)base+(j+1)*width)>0)
{//由于我们不知道base里面数据是什么类型的
//因此我们找arr[j]和arr[j+1]的时候就遇到了麻烦
//因此,我们要把base强制转换成char*类型的,再利用j*width和(j+1)*width来找到各个元素
swap((char*)base + j * width, (char*)base + (j + 1) * width,width);
}
}
}
}
以上就是本期博客的全部内容了,谢谢各位的耐心观看,在划走之前点个赞支持下吧!!!
【算法】C程序超详细的qsort排序函数解释和模拟的更多相关文章
- Java web 简单的增删改查程序(超详细)
就是简单的对数据进行增删改查.代码如下: 1.bean层:用来封装属性及其get set方法 toString方法,有参构造方法,无参构造方法等. public class Bean { privat ...
- 算法学习笔记(一)C++排序函数、映射技巧与字典树
1.头文件algorithm中有函数sort()用于排序,参数为:排序起始地址,排序结束地址,排序规则(返回bool型)例如,要将array[] = {5,7,1,2,9}升序排列,则使用: bool ...
- 数据挖掘领域十大经典算法之—C4.5算法(超详细附代码)
https://blog.csdn.net/fuqiuai/article/details/79456971 相关文章: 数据挖掘领域十大经典算法之—K-Means算法(超详细附代码) ...
- 标准差分进化算法matlab程序实现(转载)
标准差分进化算法matlab程序实现 自适应差分演化算法方面的Matlab和C++代码及论文 差分进化算法 DE-Differential Evolution matlab练习程序(差异演化DE) [ ...
- qsort中的函数指针,及函数解释
函数指针有何用 函数指针的应用场景比较多,以库函数qsort排序函数为例,它的原型如下: void qsort(void *base,size_t nmemb,size_t size , int(*c ...
- 算法课上机实验(一个简单的GUI排序算法比较程序)
(在家里的电脑上Linux Deepin截的图,屏幕大一点的话,deepin用着还挺不错的说) 这个应该是大二的算法课程上机实验时做的一个小程序,也是我的第一个GUI小程序,实现什么的都记不清了,只记 ...
- qsort排序算法
七种qsort排序方法 <本文中排序都是采用的从小到大排序> 一.对int类型数组排序 int num[100]; Sample: int cmp ( const void *a , ...
- IT技术 | 让程序员抓狂的排序算法教学视频
点击「箭头所指处」可快速关注传智特刊微信号:CZTEKAN 原文地址:http://mp.weixin.qq.com/s?__biz=MjM5OTM4NDMyMg==&mid=20056820 ...
- 超强、超详细Redis数据库入门教程
这篇文章主要介绍了超强.超详细Redis入门教程,本文详细介绍了Redis数据库各个方面的知识,需要的朋友可以参考下 [本教程目录] 1.redis是什么2.redis的作者何许人也3.谁在使用red ...
- 超强、超详细Redis数据库入门教程(转载)
这篇文章主要介绍了超强.超详细Redis入门教程,本文详细介绍了Redis数据库各个方面的知识,需要的朋友可以参考下 [本教程目录] 1.redis是什么 2.redis的作者何许人也 3.谁在使 ...
随机推荐
- L1-048 矩阵A乘以B (15分)
给定两个矩阵A和B,要求你计算它们的乘积矩阵 \(AB\).需要注意的是,只有规模匹配的矩阵才可以相乘.即若A有 \(R_a\) 行.\(C_a\) 列,B有 \(R_b\) 行.\(C_b\) 列, ...
- L1-020 帅到没朋友 (20分)
当芸芸众生忙着在朋友圈中发照片的时候,总有一些人因为太帅而没有朋友.本题就要求你找出那些帅到没有朋友的人. 输入格式: 输入第一行给出一个正整数N(≤100),是已知朋友圈的个数:随后N行,每行首先给 ...
- linux安装pyarmor踩坑记录
现有环境 centos 7.8 python 3.7.6 pip 20.0 找度娘学习安装pyarmor pip install pyarmor 然后查看版本 pyarmor --version 进入 ...
- Android Emulator 画面闪烁
Android 虚拟机经常会出现画面闪烁,可以通过修改设置解决. 打开虚拟机之后,点击 "..." 按钮.按照下图改为 "D3D11",冷重启虚拟机就好了.
- context 从入门到深入了解
1. 前言 在 Go 语言中,上下文 context.Context 用来设置截止日期,同步信号,传递值的功能,它与 goroutine 关系密切,被用来解决 goroutine 之间 退出通知,元数 ...
- springboot启动流程 (1) 流程概览
本文将通过阅读源码方式分析SpringBoot应用的启动流程,不涉及Spring启动部分(有相应的文章介绍). 本文不会对各个流程做展开分析,后续会有文章介绍详细流程. SpringApplicati ...
- SD-Host控制器设计架构
SD Host功能列表 SD Host挂接在SoC中,与外部的SD card进行交互 有控制寄存器和状态寄存器,SoC往往有CPU,通过CPU进行配置寄存器,有些SoC没有CPU,需要使用I2C或者S ...
- 【mysql】 解决 auto_increment 字段 Column count doesn't match value count at row 1
1, 表结构 man +-------+-------------+------+-----+---------+----------------+| id | int(11) | NO | PR ...
- [转帖]TiDB 最佳实践
https://docs.pingcap.com/zh/tidb/stable/tidb-best-practices 本文档总结使用 TiDB 时的一些最佳实践,主要涉及 SQL 使用和 OLAP/ ...
- [转帖]Nginx应用调优案例
https://bbs.huaweicloud.com/blogs/146367 [摘要] 1 问题背景nginx的应用程序移植到TaiShan服务器上,发现业务吞吐量没有达到硬件预期,需要做相应调优 ...