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

2024-06-17 12:36

本文主要是介绍好用的库函数,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
}

总结;

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

 

这篇关于好用的库函数,qsort函数大详解(干货满满!)(进阶)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1069459

相关文章

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

SQL 中多表查询的常见连接方式详解

《SQL中多表查询的常见连接方式详解》本文介绍SQL中多表查询的常见连接方式,包括内连接(INNERJOIN)、左连接(LEFTJOIN)、右连接(RIGHTJOIN)、全外连接(FULLOUTER... 目录一、连接类型图表(ASCII 形式)二、前置代码(创建示例表)三、连接方式代码示例1. 内连接(I

Go路由注册方法详解

《Go路由注册方法详解》Go语言中,http.NewServeMux()和http.HandleFunc()是两种不同的路由注册方式,前者创建独立的ServeMux实例,适合模块化和分层路由,灵活性高... 目录Go路由注册方法1. 路由注册的方式2. 路由器的独立性3. 灵活性4. 启动服务器的方式5.

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详

Java中八大包装类举例详解(通俗易懂)

《Java中八大包装类举例详解(通俗易懂)》:本文主要介绍Java中的包装类,包括它们的作用、特点、用途以及如何进行装箱和拆箱,包装类还提供了许多实用方法,如转换、获取基本类型值、比较和类型检测,... 目录一、包装类(Wrapper Class)1、简要介绍2、包装类特点3、包装类用途二、装箱和拆箱1、装

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

Python中Markdown库的使用示例详解

《Python中Markdown库的使用示例详解》Markdown库是一个用于处理Markdown文本的Python工具,这篇文章主要为大家详细介绍了Markdown库的具体使用,感兴趣的... 目录一、背景二、什么是 Markdown 库三、如何安装这个库四、库函数使用方法1. markdown.mark

PLsql Oracle 下载安装图文过程详解

《PLsqlOracle下载安装图文过程详解》PL/SQLDeveloper是一款用于开发Oracle数据库的集成开发环境,可以通过官网下载安装配置,并通过配置tnsnames.ora文件及环境变... 目录一、PL/SQL Developer 简介二、PL/SQL Developer 安装及配置详解1.下

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

轻松上手MYSQL之JSON函数实现高效数据查询与操作

《轻松上手MYSQL之JSON函数实现高效数据查询与操作》:本文主要介绍轻松上手MYSQL之JSON函数实现高效数据查询与操作的相关资料,MySQL提供了多个JSON函数,用于处理和查询JSON数... 目录一、jsON_EXTRACT 提取指定数据二、JSON_UNQUOTE 取消双引号三、JSON_KE