好用的库函数,qsort函数大详解(干货满满!)(进阶)

前言:

  小编在上一篇文章说了这一篇将要写qsort函数的模拟实现,那么废话不多说,现在开始进入今天的代码之旅喽!


目录:

1.qsort函数的模拟实现的逻辑和思路

2.qsort函数模拟实现的代码实现

3.代码展示


1.qsort函数的模拟实现的逻辑和思路

  读者朋友们是否还记得小编之前说过的一个排序的算法:冒泡排序,今天我们就是用它来模拟实现qsort函数的,如果有读者朋友略微忘记的话,小编先从这里呈现冒泡排序代码的实现来让读者朋友们回忆部分内容:

void my_paopao(int arr[10], int sz)
{int i = 0;int flag = 1;for (i = 0; i < sz - 1; i++){int j = 0;for (j = 0; j < sz - 1 - i; j++){if (arr[j] > arr[j + 1]){int tmo = 0;tmo = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmo;flag = 0;}if (flag == 1)break;}}
}
int main()
{int arr[10] = { 0 };int i = 0;for (i = 0; i < 10; i++){scanf("%d", arr + i);}int sz = sizeof(arr) / sizeof(arr[0]);my_paopao(arr, sz);for (i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

  上面就是冒泡排序代码的实现,如果稍微有点记不清的读者朋友可以看上述代码回忆一下,或者浏览:C语言重要算法之一——冒牌排序详解(干货满满,欢迎各位朋友的观看)-CSDN博客 ,这个是我以前写过的博客,大家可以看这个回顾,回归正题,我们知道,冒泡排序只能排序整型,而qsort函数可以排序任意类型的数组,我们可以以冒泡排序为整体的框架,从而可以模拟qsort函数。

  首先,我们先来回顾一下,qsort函数内部的内容,通过上次小编介绍的网站可以清晰的看到: 

   我们可以先仿照这个来先写一个类似的函数,因为这个是我们自己模拟的,所以可以自己命名,我们对函数描述完以后,就要写函数的主题了,小编前面说过,我们可以保留冒泡排序的框架,所以我们先把代码拿出来来进行思考:

void my_qsortvoid *base,size_t count,size_t width,int (*cop)(const void* p1,const void* p2) )   //这里完全对照qsort函数本身括号内部的内容
{int i = 0;int flag = 1;for (i = 0; i < sz - 1; i++){int j = 0;for (j = 0; j < sz - 1 - i; j++){if (arr[j] > arr[j + 1]){int tmo = 0;tmo = arr[j];arr[j] = arr[j + 1];   //当然我们不能这么比较,因为我们有可能设计到字符的比较,对于改进我们在下面叙说,毕竟咱不能一口气吃个小编arr[j + 1] = tmo;flag = 0;}if (flag == 1)break;}}
}

  正如我在上面所说,我们可以把循环给保存好,然后对于内容进行修改,不知道读者朋友们是否还记得小编之前说过qsort是怎么判定可以交换的,如果忘记了请看下图 :

   当返回值大于0的时候将会让两个数进行交换,小于0或者等于0的时候是不发生交换的,那么这个时候,我们就可以我们写的最后一个函数(括号最后一个)指针来进行比较操作,通过此函数的返回值来比较是否大于0,如果大于0再进行交换操作。

  交换操作可以通过我们再写一个交换函数来进行数值的交换,我们在交换的时候,要考虑到我们传参的时候不一定传的就是整型,我们上面式子的交换是只是针对整形的,对于字符型的,小编认为,我们可以通过一个一个字节的来进行交换,这样的话,我们既可以针对字符型,也可以针对整型了,现在我们已经有了这个函数的大致思路了,下面就我们就来进行函数的写正式描写喽!

 

2.qsort函数模拟实现的代码实现

  我们刚开始就要先写一下函数名,通过我们对于qsort函数的了解,下面是代码的实现: 

int arr[10] = { 3,4,5,6,7,8,9,10,1,2 };
int sz = sizeof(arr) / sizeof(arr[0]);
my_qsort(arr, sz, sizeof(arr[0]), com_per);  //这里放函数名就好

  之后,我们就要进行比较环节了,循环方面小编就不写了(待会会把完整的代码发出来,大家不要着急),我们首先要靠比较函数来比较大小,对于这方面的实现,我们其实可以完全仿照我们之前运用比较函数的样子,首先我们要先写一个if语句来判定它与0之间的大小关系,下面是代码呈现:

	if (cop((char*)base + j * width, (char*)base + (j+1) * width) > 0){comper((char*)base + j * width, (char*)base + (j + 1) * width, width);   //这是交换的(适用于任何的数)}

  对于函数如何进行比较,小编放在了下图,完全可以仿照我们使用它的时候的比较进行书写(我们这里就以char类型的数据举例): 

 int com_per(const void* p1, const void* p2)
{return ((*(char*)p1) - (*(char*)p2));   //对于字符串的比较才用strcmp
}

  所以说,比较函数我们就原封不动的写就好(此时也是展现了为什么这么比较就可以实现两个数的交换),之后就到了我们这个代码的重头戏,对于我们如何进行两个数的交换,小编在思路部分就说了,我们可以实现一个字节一个字节的交换从而完成所有的交换,所以我们可以直接用char*指针对于我们比较两个数进行接受,然后我们可以写一个循环,通过这个循环来实现每个字节的交换,对于次数的限制,我们就以我们比较数的大小作为最大次数,从而实现字节的交换,我光说可能大家都很疑惑,下面是完整的代码展示:

void comper(char* a1, char* a2,int width)
{int i = 0;char a = 0;for (i = 0; i < width; i++){a = *a1;*a1 = *a2;*a2 = a;a1++;a2++;}
}

  上面便是对于这个交换函数进行的描写,与小编说的一样,此时我们通过循环便可以实现每个数的交换,可能有些读者很疑惑,认为整型是怎么实现交换的,为此小编通过图文的形式进行解释: 

   虽然小编画的有点抽象,但是是这么个道理,这里确实实现了两个数的交换,那么我们通过每次循环,来对于数进行交换了,最终会实现此代码的实现,下面来展示一下这个代码最后的运行图:

   可以很清楚的看已经完成了升序环节,证明此函数模拟成功了,可能现在还有很多读者朋友不知道如何完整的实现这个功能,不要急,小编这就给大家展示源代码!

 

3.代码展示

  小编这里就拿整型和字符型来进行展示了

整型的主函数:

	int arr[10] = { 3,4,5,6,7,8,9,10,1,2 };int sz = sizeof(arr) / sizeof(arr[0]);my_paopao(arr, sz, sizeof(arr[0]), com_per);  //这里放函数名就好int i = 0;for (i = 0; i < sz; i++){printf("%d ", arr[i]);}

模拟函数(这里通用的,所以下面也不展示了):

void my_paopao(void *base,size_t count,size_t width,int (*cop)(const void* p1,const void* p2))   //这里是模仿的qsort里面的内容来写的
{    //上面也用到了回调函数的思想int i = 0;for (i = 0; i < count - 1; i++)            //这里采用的模板是按照冒泡排序的思想来写的,外在并没被改变,但是内在却和冒泡排序是截然不同的{int j = 0;for (j = 0; j < count - i - 1; j++){if (cop((char*)base + j * width, (char*)base + (j+1) * width) > 0){comper((char*)base + j * width, (char*)base + (j + 1) * width, width);   //这是交换的(适用于任何的数)}}}
}

 比较函数:

int com_per(const void* p1, const void* p2)
{return (*(int*)p1 - *(int*)p2);
}

交换函数(这个是通用的,小编下面就不写了):

void comper(char* a1, char* a2,int width)
{int i = 0;char a = 0;for (i = 0; i < width; i++){a = *a1;*a1 = *a2;*a2 = a;a1++;a2++;}
}

字符型主函数:

	char arr[10] = { 'a','c','d','b','e','h','q','u','x','z' };int sz = sizeof(arr) / sizeof(arr[0]);my_paopao(arr, sz, sizeof(arr[0]), jisuan);int i = 0;for (i = 0; i < sz; i++){printf("%c ", arr[i]);}

比较函数:

 int jisuan(const void* p1, const void* p2)
{return ((*(char*)p1) - (*(char*)p2));   //对于字符串的比较才用strcmp
}

总结;

  小编先声明一下,小编这里是用冒泡排序的方式来模拟实现这个函数的,但不一定代表着只有冒泡排序才可以模拟实现这个函数,对于这个函数的具体实现可能也就只有制作这个函数的人知道了,读者朋友们学会其中的思想就好了,在这里,小编也是连着更了七天的博客了,在这期间我也发现了我忘记了很多知识,果然还是那句话:温故而知新可以为师矣 !大家平常一定要多复习自己学过的知识,避免忘记过多,明天可能会停更一天,小编歇一天,如果文章有错误,恳请大家指出,小编虚心求教,我们下一篇博客见喽!

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【WEB前端2024】3D智体编程:乔布斯3D纪念馆-第41课-动态添加3D对象

【WEB前端2024】3D智体编程&#xff1a;乔布斯3D纪念馆-第41课-动态添加3D对象 使用dtns.network德塔世界&#xff08;开源的智体世界引擎&#xff09;&#xff0c;策划和设计《乔布斯超大型的开源3D纪念馆》的系列教程。dtns.network是一款主要由JavaScript编写的智体世界引擎…

2.华为配置静态路由

通过配置静态路由让PC1和PC2互通 AR1 [Huawei]int g0/0/0 [Huawei-GigabitEthernet0/0/0]ip add 192.168.1.254 24 [Huawei]int g0/0/1 [Huawei-GigabitEthernet0/0/1]ip add 1.1.1.1 24 [Huawei]ip route-static 192.168.2.0 24 1.1.1.2AR2 [Huawei]int g0/0/0 [Huawei-Gig…

【Android面试八股文】讲一讲String、StringBuffer和StringBuilder在进行字符串操作时候的效率

文章目录 一、String二、StringBuffer三、StringBuilder四、String、StringBuffer和StringBuilder的效率测试五、String、StringBuffer和StringBuilder的选择一、String String是不可变的,final修饰,任何对String的操作都会创建一个新的String对象。在进行大量字符串拼接或修…

盘点有趣的人工智能开源项目一

字幕导出 zh_recogn是一个专注于中文语音识别的字幕生成工具&#xff0c;基于魔塔社区Paraformer模型。它不仅支持音频文件&#xff0c;还能处理视频文件&#xff0c;输出标准的SRT字幕格式。这个项目提供了API接口和简单的用户界面&#xff0c;使得用户可以根据自己的需求灵活…

前端面试题日常练-day72 【面试题】

题目 希望这些选择题能够帮助您进行前端面试的准备&#xff0c;答案在文末 在Sass中&#xff0c;以下哪个关键字用于定义一个占位符选择器&#xff0c;以便在后续使用时进行扩展&#xff1f; a) placeholder b) extend c) mixin d) import Sass中的函数&#xff08;Function&…

GitLab、jenkins

Gitlab服务器&#xff1a;192.168.10.20 jenkins服务器&#xff1a;192.168.10.30 web应用服务器&#xff1a;192.168.10.100 通过容器部署gitlab&#xff1a; 安装容器管理软件podman 修改主机的22端口&#xff0c;该gitlab软件包中会使用到该端口 gitlab容器需要使用/etc/res…

一二三应用开发平台应用开发示例(3)——生成库表及后端代码

生成库表 前端页面的配置&#xff0c;也就是视图功能&#xff0c;我们先放一放&#xff0c;来看看生成库表和后端代码。 关闭实体配置界面&#xff0c;回到实体列表&#xff0c;勾选“文件夹”实体&#xff0c;点击“生成库表”&#xff0c;并确定。 系统提示成功后&#xff…

【每天学会一个渗透测试工具】dirsearch安装及使用指南

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 ✨dirsearch介绍 dirsearch安装包百度网盘 disearch是基于Python开发的&#xff0c;因此需要确保你的系统中已经安装了pyth…

vscode连接ssh远程服务器

当使用Visual Studio Code (VSCode) 连接SSH远程服务器时&#xff0c;可以遵循以下步骤。这些步骤将帮助你设置并连接到远程服务器&#xff0c;包括免密登录的设置&#xff08;如果需要&#xff09;。 一、安装并配置Remote-SSH插件 下载并安装VSCode&#xff1a;确保你已经下…

flstudio怎么调中文

FL Studio设置中文的步骤如下&#xff1a; 打开FL Studio&#xff1a;首先&#xff0c;需要打开FL Studio编曲软件。 进入常规设置&#xff1a;在软件顶部菜单栏中&#xff0c;选择“OPTIONS”&#xff0c;然后点击“General setting”&#xff0c;进入常规设置窗口。 切换语言…

vue实现图片预览

在 Vue 中实现图片预览功能&#xff0c;通常涉及监听文件输入的变化&#xff0c;并在用户选择文件后&#xff0c;使用 FileReader API 来读取文件内容&#xff0c;然后显示这个内容作为图片的预览。以下是一个简单的 Vue 组件示例&#xff0c;它实现了图片预览功能&#xff1a;…

PostgreSQL 数据库选择指南

PostgreSQL 数据库选择指南 引言 PostgreSQL,作为一款开源的对象-关系型数据库管理系统,以其稳定性、功能丰富性和强大的扩展能力而闻名。在选择数据库时,PostgreSQL常常是企业和开发者的首选之一。本文将详细介绍PostgreSQL的特点,帮助您更好地理解为何选择PostgreSQL,…

经典电源电路基础(变压-整流-滤波-稳压)

1.电源电路的功能和组成 电子电路中的电源一般是低压直流电&#xff0c;先把220v交流电变换成低压直流电&#xff0c;再用整流电路变成脉动的直流电&#xff0c;最后用滤波电路滤除掉脉动直流中的交流成分后才能得到直流电。有的电子设备对电源的质量要求很高&#xff0c;所以…

编程C语言自学书:引领你深入编程世界的神秘之旅

编程C语言自学书&#xff1a;引领你深入编程世界的神秘之旅 在信息时代的浪潮中&#xff0c;编程技能已变得至关重要。而C语言&#xff0c;作为计算机编程的基石&#xff0c;其地位更是不可动摇。对于初学者来说&#xff0c;一本好的自学书籍是掌握C语言的关键。今天&#xff…

ant design vue table表格合并后每个单元格加点击事件并获取每个单元格的值

用 event.target.closest(.ant-table-row-cell-break-word).textContent 获取 {title: "ECP",dataIndex: "ecp",scopedSlots: { customRender: "ecp" },customRender(_, row) {return {child: row.ecp,attrs: {rowSpan: row.ecpRowSpan}}},custo…

Swift JSON

https://www.bilibili.com/read/cv32068675/ [ { "id": 32025753, "title": "【100天学习SwiftUI】第0天 如何成为一名iOS开发人员", "state": 0, "publish_time": 1708878554, "words": …

JavaWeb之初识Tomcat

Tomcat 轻量级应用服务器、JSP、Servlet Tomcat目录结构 在IDEA中创建web项目 在这里不使用maven构建项目&#xff0c;这种方式后面会更新 新建一个java项目File -> Project Settings -> Facets -> -> Web -> OK ( 此时src目录下有一个web目录 )Edit ->…

对冲基金为什么叫做Hedge Fund?

中文版 对冲基金详细介绍 “对冲基金”名称的由来 “对冲基金”&#xff08;Hedge Fund&#xff09;这个名称源于最初采用的投资策略&#xff0c;即通过对冲&#xff08;hedging&#xff09;来减少风险。1949年&#xff0c;阿尔弗雷德温斯洛琼斯&#xff08;Alfred Winslow …

[个人感悟] 缓存应该考察哪些问题?

前言 缓存, 根据冯诺依曼计算机模型, 无非是为了更高效的交互, 使用内存IO替换本地磁盘IO. 又因为内存的稀缺性, 其必然存储的是热点数据, 且较小的数据. [虽然直至今日, 已有使用缓存作为数据库的使用, 但是与磁盘IO相比, 其价格仍是数倍之多.] 当涉及缓存问题时, 又分为本地…