【算法】C程序超详细的qsort排序函数解释和模拟

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);

			}
		}
	}
}

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

posted @ 2021-10-10 23:28  背包Yu  阅读(12)  评论(0编辑  收藏  举报  来源