C程序利用冒泡排序的思想模拟实现qsort排序函数

求个赞求个赞求个赞求个赞 谢谢

先赞后看好习惯 打字不容易,这都是很用心做的,希望得到支持你 大家的点赞和支持对于我来说是一种非常重要的动力 看完之后别忘记关注我哦!️️️
前言:作者:Yu
常用c程序编译器:vs2019**

qsort函数的使用

在我们模拟实现它之前,我们先搞清楚它的用法。
我们先来看qsort函数的原型

  1. 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,就小于
//就是这样设计的

我们先看看整个运用代码是怎么写的

  1. int cmp_int(const void* e1, const void* e2)
  2. {
  3. return *(int*)e1 - *(int*)e2;
  4. }
  5. void test1()
  6. {
  7. int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
  8. int sz = sizeof(arr) / sizeof(arr[0]);//求出数组元素的个数
  9. qsort(arr, sz, sizeof(arr[0]), cmp_int);
  10. for (int i = 0; i < 10; i++)
  11. {
  12. printf("%d\t", arr[i]);
  13. }
  14. }
  15. int main()
  16. {
  17. test1();//排序整型
  18. return 0;
  19. }

在这个代码中,我们来逐个分析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函数

  1. int cmp_int(const void* e1, const void* e2)
  2. {
  3. return *(int*)e1 - *(int*)e2;
  4. }

注意,这里cmp函数的类型,一定要和上面qsort函数要求的类型一一对应

  1. int (*cmp)(const void*e1 , const void* e2)

进到这个对比函数里头,我们在比较之前,我们是肯定要解引用的,但是,void类型怎么解引用呢,所以,我们要把它强制转化成int类型,这样就可以解引用并返回一个整型了。
最后我们将上面的函数整体使用的结果打印出来就可以了

以上便是我们qsort函数的使用

接下来,让我们一起来模拟它

我们使用的是冒泡排序的双循环的方法进行实现
我们先看一下普通冒泡排序的代码

  1. void bubble_sort(int* arr, int sz)
  2. {
  3. int i = 0;
  4. int j = 0;
  5. for (i = 0; i < sz - 1; i++)
  6. {
  7. for (j = 0; j < sz - 1 - i; j++)
  8. {
  9. if (arr[j] > arr[j + 1])
  10. {
  11. int tmp = arr[j];
  12. arr[j] = arr[j + 1];
  13. arr[j + 1] = tmp;
  14. }
  15. }
  16. }
  17. }
  18. int main()
  19. {
  20. int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
  21. int sz = sizeof(arr) / sizeof(arr[0]);
  22. bubble_sort(arr, sz);
  23. for (int i = 0; i < sz; i++)
  24. {
  25. printf("%d\t", arr[i]);
  26. }
  27. return 0;
  28. }

我们准备使用的正是这种思想。
我们先来看完整代码

  1. void swap(char* bulf1, char* bulf2, int width)
  2. {
  3. int i = 0;
  4. for (i = 0; i < width; i++)
  5. {
  6. char tmp = *bulf1;
  7. *bulf1 = *bulf2;
  8. *bulf2 = tmp;
  9. bulf1++;
  10. bulf2++;
  11. }
  12. }
  13. void qsort_by_bubble(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
  14. {
  15. int i = 0;
  16. for (i = 0; i < sz - 1; i++)
  17. {
  18. int j = 0;
  19. for (j = 0; j < sz - 1 - i; j++)
  20. {
  21. if (cmp((char*)base+j*width,(char*)base+(j+1)*width)>0)
  22. {//由于我们不知道base里面数据是什么类型的
  23. //因此我们找arr[j]和arr[j+1]的时候就遇到了麻烦
  24. //因此,我们要把base强制转换成char*类型的,再利用j*width和(j+1)*width来找到各个元素
  25. swap((char*)base + j * width, (char*)base + (j + 1) * width,width);
  26. }
  27. }
  28. }
  29. }

以上就是本期博客的全部内容了,谢谢各位的耐心观看,在划走之前点个赞支持下吧!!!

【算法】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. <vue 基础知识 5、事件监听>

    代码结构 一.     v-on基本使用 1.效果 按钮点击一下数字增加1 2.代码 01-v-on基本使用.html <!DOCTYPE html> <html lang=&quo ...

  2. 五、mycat水平分库

    系列导航 一.Mycat实战---为什么要用mycat 二.Mycat安装 三.mycat实验数据 四.mycat垂直分库 五.mycat水平分库 六.mycat全局自增 七.mycat-ER分片 一 ...

  3. Springboot+ELK实现日志系统简单搭建

    前面简单介绍了ELK三剑客中的其中两个Elasticsearch和Kibana的简单使用,如果对这两个不了解,可以看下下面的 Centos7安装Elasticsearch和Kibana 搜索引擎基础- ...

  4. 解决刷新页面丢失vuex数据

  5. vue.js从输入中的contenteditable元素获取innerhtml

    <div class="actual-score" :contenteditable="$route.params.mode === 'edit'" v- ...

  6. poj 1426 深搜

    ***可能有多个答案,DFS一下找出一个答案即可*** #include<stdio.h> #include<string.h> #include<stdlib.h> ...

  7. kafka 集群环境搭建

    本文为博主原创,未经允许不得转载: 如果搭建单机节点 kafka 可看我的这篇博客: 搭建 kafka 集群环境,只需要在搭建单机 kafka 环境的基础上,多增加几个kafka 服务实例即可. 多增 ...

  8. [转帖]TiDB损坏多副本之有损恢复处理方法

    https://tidb.net/blog/b1ae4ee7   TiDB分布式数据库采用多副本机制,数据副本通过 Multi-Raft 协议同步事务日志,确保数据强一致性且少数副本发生故障时不影响数 ...

  9. [转帖]CentOS7使用Chrony实现时间同步

    学习安装部署 ceph 时 ,在添加 mon 时报错了,搜索原因后发现是 时间同步问题.于是学习一下时间同步工具. 一般CentOS6 使用的时间同步工具是ntp.现在还有不少开源软件文档建议安装的时 ...

  10. [转帖]Pepper-Box - Kafka Load Generator

    https://github.com/GSLabDev/pepper-box Pepper-Box is kafka load generator plugin for jmeter. It allo ...