首页 > 其他分享 >好用的库函数,qsort函数大详解(干货满满!)(进阶)

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

时间:2024-06-18 09:33:00浏览次数:24  
标签:arr 进阶 int void qsort char 小编 库函数 函数

前言:

  小编在上一篇文章说了这一篇将要写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
}

总结;

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

 

标签:arr,进阶,int,void,qsort,char,小编,库函数,函数
From: https://blog.csdn.net/effort123_/article/details/139723248

相关文章

  • Perl 语言学习进阶
    一、如何深入要深入学习Perl语言的库和框架,可以按照以下步骤进行:了解Perl的核心模块:Perl有许多核心模块,它们提供了许多常用的功能。了解这些模块的功能和用法是深入学习Perl的第一步。一些常用的核心模块包括:Scalar::Util,List::Util,File::Spec等。学习CPAN(Comprehensi......
  • 专业程序员进阶之路:认识设计
    专业程序员进阶之路:认识设计设计是什么设计就是构思一套方案,将软件规格说明书的要求转变为可运行的软件的过程。设计将需求和编码连接在一起。设计有时候可能不是一项明确的活动,但是在项目过程中一直都存在,只是设计进行的程度或深或浅。大型项目可能有特定的正式设计阶段,由专......
  • 【C++】模板进阶(特化)
      ......
  • FASTAPI从入门到进阶
    fastapi框架fastapi,一个用于构建API的现代、快速(高性能)的web框架。fastapi是建立在Starlette和Pydantic基础上的,Pydantic是一个基于Python类型提示来定义数据验证、序列化和文档的库。Starlette是一种轻量级的ASGI框架/工具包,是构建高性能Asyncio服务的理性选择。快速:可与......
  • 好用的库函数,qsort函数大详解(干货满满!)(初阶)
    前言;  我一直在思考今天要写什么类型的文章,看到之前写的冒泡排序的写法,不过冒牌排序的算法只能针对于整型,我们如果想要排序浮点型,字符型的数据呢?这个时候我突然想到了比冒泡排序还好用的一个库函数,就是我们今天的主角——qsort函数,下面不多废话,直接进入正文: 目录:1.qsor......
  • (已校对)深入理解XGBoost:高效机器学习算法与进阶 (何龙)
    书:pan.baidu.com/s/1tGbGhhQ3Ez1SIkqdEREsjQ?pwd=eqp0提取码:eqp0XGBoost算法原理:XGBoost(ExtremeGradientBoosting)是一种基于梯度提升决策树的机器学习算法,其核心是通过多个弱学习器的组合来构建一个强学习器。梯度提升与决策树:XGBoost在每轮迭代中,通过计算每个样本的梯度和......
  • 【Python入门与进阶】综合练习题:学生成绩管理系统
    综合练习题:学生成绩管理系统题目描述:请你设计一个简单的学生成绩管理系统,要求能够进行以下操作:添加学生信息(包括姓名和学号)添加学生的成绩(包括科目和成绩)查询学生的平均成绩打印所有学生的成绩单解题思路:定义类:创建一个Student类,包含以下属性:name:学生姓名i......
  • jQuery引入,基本选择器和关系选择器,组合选择器,分组与嵌套,基本筛选器,属性选择器,前
    ⅠjQuery引入【一】什么是jQuery【1】概述jQuery是一个轻量级的、兼容多浏览器的JavaScript库。jQuery使用户能够更方便地处理HTMLDocument、Events、实现动画效果、方便地进行Ajax交互,能够极大地简化JavaScript编程。它的宗旨就是:“Writeless,domore.“【2】小结jQ......
  • Python在SQLite中的应用:从入门到进阶
    Python在SQLite中的应用:从入门到进阶Python作为一门高效、灵活的编程语言,广泛应用于各种数据处理和分析任务。而SQLite是一种轻量级的数据库管理系统,特别适合于嵌入式应用和小型项目。在本篇博文中,我们将深入探讨Python在SQLite中的应用,帮助读者从零开始,逐步掌握这项技能。......
  • 一篇文章教你如何解决vs编译器中,库函数scanf的正常使用!!!
    前言:这将是我写的第二篇博文了,以后我将会坚持每天花固定时间来写博客,希望我当我写了一定数量的文章之后,我自己简单的就能够写出质量优秀文章来,加油!!!一、scanf函数无法正常使用的原因1.错误实例在vs中如果想直接实现并使用scanf函数,很抱歉直接使用,用不了,因为编译器压根就......