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排序函数解释和模拟的更多相关文章

  1. Java web 简单的增删改查程序(超详细)

    就是简单的对数据进行增删改查.代码如下: 1.bean层:用来封装属性及其get set方法 toString方法,有参构造方法,无参构造方法等. public class Bean { privat ...

  2. 算法学习笔记(一)C++排序函数、映射技巧与字典树

    1.头文件algorithm中有函数sort()用于排序,参数为:排序起始地址,排序结束地址,排序规则(返回bool型)例如,要将array[] = {5,7,1,2,9}升序排列,则使用: bool ...

  3. 数据挖掘领域十大经典算法之—C4.5算法(超详细附代码)

    https://blog.csdn.net/fuqiuai/article/details/79456971 相关文章: 数据挖掘领域十大经典算法之—K-Means算法(超详细附代码)        ...

  4. 标准差分进化算法matlab程序实现(转载)

    标准差分进化算法matlab程序实现 自适应差分演化算法方面的Matlab和C++代码及论文 差分进化算法 DE-Differential Evolution matlab练习程序(差异演化DE) [ ...

  5. qsort中的函数指针,及函数解释

    函数指针有何用 函数指针的应用场景比较多,以库函数qsort排序函数为例,它的原型如下: void qsort(void *base,size_t nmemb,size_t size , int(*c ...

  6. 算法课上机实验(一个简单的GUI排序算法比较程序)

    (在家里的电脑上Linux Deepin截的图,屏幕大一点的话,deepin用着还挺不错的说) 这个应该是大二的算法课程上机实验时做的一个小程序,也是我的第一个GUI小程序,实现什么的都记不清了,只记 ...

  7. qsort排序算法

      七种qsort排序方法 <本文中排序都是采用的从小到大排序> 一.对int类型数组排序 int num[100]; Sample: int cmp ( const void *a ,  ...

  8. IT技术 | 让程序员抓狂的排序算法教学视频

    点击「箭头所指处」可快速关注传智特刊微信号:CZTEKAN 原文地址:http://mp.weixin.qq.com/s?__biz=MjM5OTM4NDMyMg==&mid=20056820 ...

  9. 超强、超详细Redis数据库入门教程

    这篇文章主要介绍了超强.超详细Redis入门教程,本文详细介绍了Redis数据库各个方面的知识,需要的朋友可以参考下 [本教程目录] 1.redis是什么2.redis的作者何许人也3.谁在使用red ...

  10. 超强、超详细Redis数据库入门教程(转载)

    这篇文章主要介绍了超强.超详细Redis入门教程,本文详细介绍了Redis数据库各个方面的知识,需要的朋友可以参考下   [本教程目录] 1.redis是什么 2.redis的作者何许人也 3.谁在使 ...

随机推荐

  1. HDU - 2897 邂逅明下 (简单博弈)

    题目链接: https://vjudge.net/problem/HDU-2897 题目大意: 就是现在一堆石子有n颗, 每次只能拿走p~q颗, 当剩余少于p颗的时候必须一次拿完 拿走最后一颗的人败 ...

  2. AtCoder | ABC 125 Person Editorial

    开始补AtCoder的数学题了,练下思维 AB两道都很简单,看懂题就OK. C,D稍微麻烦一些 Problem C: GCD On Blackboard 为了解决此问题,我们需要了解最大公约数(GCD ...

  3. SCA技术进阶系列(一):SBOM应用实践初探

    现代软件都是组装的而非纯自研.随着开源组件在数字化应用中的使用比例越来越高,混源开发已成为当前业内主流开发方式.开源组件的引入虽然加快了软件开发效率,但同时将开源安全问题引入了整个软件供应链.软件组成 ...

  4. 倾斜摄影技术构建图扑 WebGIS 智慧展馆

    前言 智慧展馆通过"云大物移智链"等技术将"物"(展品.设备.环境等)进行互联,并感知"人"(工作人员.观众等)的行为.结合 GIS.BIM ...

  5. 深度学习(三)——Transforms的使用

    一.Transforms的结构及用法 导入transforms from torchvision import transforms 作用:图片输入transforms后,可以得到一些预期的变换 1. ...

  6. Delete `␍`eslint(prettier/prettier)错误

    最佳实践: 现在VScode,Notepad++编辑器都能够自动识别文件的换行符是LF还是CRLF. 如果你用的是windows,文件编码是UTF-8且包含中文,最好全局将autocrlf设置为fal ...

  7. C++ Lambda 表达式递归写法

    今天看到一篇博客介绍使用 Lambda 表达式递归计算 n!.使用了 C++14 的 generic lambda,给 Lambda 表达式加了一个模板参数,在函数调用的时候将 Lambda 表达式作 ...

  8. 新建Maven工程没有src/main...目录?

    0.必看:详细的Maven项目介绍 1.问题 我新建的Maven项目的pom.xml为空,且无法被识别,同时项目目录没有src/main等等 2.解决 这里设置的JDK版本不对,我选用了JDK19 但 ...

  9. Vue- 绑定的图片不显示

    需要通过 require包裹 <template> <div> {{user.username}}: <img :src="user.avatar" ...

  10. js - body的滚动事件的坑

    文章来源 : https://www.cnblogs.com/Zting00/p/7497629.html 踩过些坑,得到的结论,不一定精确 1. body的滚动条,刷新页面的时候不会回到顶部.其他d ...