qsort函数的底层逻辑

一、冒泡排序的局限性

说到排序,我们首先可能会想到冒泡排序,它非常的方便。但是,他也有他的局限性,因为对于一个特定的冒泡排序,一般只能排序一种类型的数据

比如下面

#include <stdio.h>
void bubble_sort(int arr[],int sz)
{
	
	int i = 0;
	for (i = 0; i < sz-1 ; i++)
	{
		int j = 0;
		for (j = 0; j < sz - i-1 ; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}
int main()
{
	int arr[] = { 0,2,4,6 ,3,1,7,5,8,9};
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr,sz);
	int i = 0;
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

对于这一个冒泡排序,我们只能对整形数组进行排序,对于其他数组就无能为力了。那么怎么写出一个万能的函数,可以排序所有类型的的数组呢?其实C语言库里面就有了这个函数,他就是qsort那么让我们了解一下它的底层逻辑。

二 代码展示

为了方便展示,我们依旧采用整形数组

#include<stdio.h>
int com_int(void* e1, void* e2);
int main()
{
	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]), com_int);
	int i;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}
int com_int(void* e1, void* e2)
{
	return *(int*)e1 - *(int*)e2;
}

在这段代码中,我们用了qsort这一个函数,可以观察到,这个函数有四个参数,分别为,arr, sz, sizeof(arr[0]), com_int。

其中,arr是数组名,也是数组首元素地址。sz是数组的元素个数。sizeof(arr[0])是数组内元素的大小,com_int是我们自己写的函数,它的作用就是比较两个元素的大小。所以,当我们用的时候只需要写com_int这个函数就可以了。

三my_qsorth函数的实现。

我们先看最后一个函数。再看倒数第二个,第一个。

int com_int(void* e1, void* e2)
{
	return *(int*)e1 - *(int*)e2;
	//(int*)e1 的作用是直接与返回值对应,都为整形,再进行加减;
}
void swap(char* e1, char* e2,int width)
{
	int i;
	for (i = 0; i < width; i++)
	//char*一次只能交换一个字节,所以进行width次
	{
		char tmp = *e1;
		*e1 = *e2;
		*e2 = tmp;
		e1++; e2++;
	}
}
void my_qsort(void*arr,int sz,int width,int* com(void* e1,void* e2))
{
	//void*arr,是给出数组的首元素地址,因为不知道要排序什么类型的数据,所以用空指针。
	//sz是数组中元素的个数
	//width是数组元素所占的字节数
	//int* com(void* e1,void* e2)是一个函数指针,用来比较大小,这个函数需要我们自己完成。
	int i, j;
	for (i = 0; i < sz - 1; i++)
	{
		for (j = 0; j < sz - i - 1; j++)//冒泡排序的原理,还是两次循环,我们需要变得只有比较方法。
		{
			if (com((char*)arr+j*width, (char*)arr+(j + 1)*width)>0)
			//当这个函数的返回值大于零时,就是第一个元素比第二个元素大
			//因为void*不可以加减运算所以需要强制类型转换为其他类型
			//转换成char*的原因是因为char*一次只访问一个字节,我们再加上width,就是一次访问数据 类型所对应的字节
			//j*width代表了比较的数据,每次不一样,随着循环递增
			{
				swap((char*)arr + j * width, (char*)arr + (j + 1) * width, width);
				//交换的函数
			}
		}
	}
}

以上就是qsort的底层逻辑

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值