目录
[二、qsort 使用举例](#二、qsort 使用举例)
三、模拟qsort
一、回调函数
回调函数就是一个通过函数指针调用的函数。
举个例子:
cs
int Add(int x, int y)
{
return x+y;
}
void test(int (*pf)(int, int))
{
int r = pf(10 ,20);
printf("%d\n" ,r);
}
int main()
{
test(Add);
return 0;
}
简单点说,就是把函数的地址作为一个参数传递给另外一个函数,在其中被调用,那么被调用的函数就称为回调函数
二、qsort 使用举例
qsort 是C语言中提供的一个排序函数,是基于快速排序思想的。
它的原型如下:
cs
void qsort(void* base, size_t num, size_t size, int(*compar)(const void* ,const void*));
void* base //指针,指向被排序数组的第一个元素
size_t num //元素个数
size_t size //元素的大小(单位:字节)
int (*compar)(const void* ,const void*) //函数指针,指向的函数是用来比较被排序数组中的两个元素,根据自己需要,自己编写
下面举个例子:
cs
int compar(const void* p1, const void* p2)
{
if( *(int*)p1 > *(int*)p2 )
return 1;
else if( *(int*)p1 < *(int*)p2)
return -1;
else
return 0;
}
这个自行编写的函数要满足一下要求:
(1)返回类型为整型
(2)在默认升序的情况下,当 p1 > p2时,返回1, p1 == p2 时返回 0 ,p1 < p2 时返回 -1。
(3)如果你想降序,把(2)中的 条件互换就行
(4)具体的比较标准由你自己来定,你可以比较整形,浮点型,字符型或者其他,不过要记得强制类型转换
三、用冒泡排序模拟 qsort 函数
首先,要模拟,我们需要根据 qsort 函数的原型模拟:
cs
void my_bubble( void* base, size_t num ,size_t size, int (*compare)(const void* ,const void*);
然后我们在把原本普通的冒泡函数写出来:
cs
void my_bubble( void* base, size_t num ,size_t size, int (*compare)(const void* ,const void*)
{
for(int i = 0 ;i <sz-1;i++)
{
for(int j = 0 ;j <sz-1-i ;j++)
{
if(arr[j] > arr[j+1])//判断条件我们需要修改
{
//交换过程我们也要修改
int mid = arr[j];
arr[j] = arr[j+1];
arr[j+1] = mid;
}
}
}
为什么要用void*呢?因为我们不知道要排序的数据类型
为什么要专门写一个比较函数呢?因为我们不提前知道比较规则
那如何比较两个元素呢?我们连数据类型都不知道

如图所示,我们知道起始地址,但不知道元素类型,也就不知道一个元素究竟占多少字节,整型一个元素占4个字节,短整型占两个字节,我们该如何准确地找到下一个元素的地址呢?

如图,别忘了我们还有每个元素的大小,那么第 j 个元素的地址就是 arr+j*size ,j 第 +1 个 元素的地址就是 arr + (j +1)*size 。
但是,void*作为无类型指针,是不可以被计算和解引用的,那我们就要对其强制类型转化为 char* 类型。
为什么是 char* 类型呢?因为char的大小为 1 个字节,是最小的单位了,你总不能拿 int 去吧,你用了int ,那char 、short 怎么办呢
所以那个条件应该为:
cs
if(compar((char*)p1 ,(char*)p2) > 0)
那如果满足这个条件了,按照原先冒泡函数思想,我们就应该互换位置了,那怎么互换呢?
互换一般要创建第三个变量,但是,我们不知道元素类型,就不知道第三者变量的类型,怎么办呢?
我们每个字节每个字节互换:

如此往复循环,直到两个元素调换完成,那我们应该循环几次呢?答案是 size 次,因为每个元素就是 size 个字节,每次调换一个字节,需要调换 size 次
cs
void Swap(char* su1, char*su2 ,size_t size)
{
for(int i = 0; i<sz ;i++)
{
char mid = *su1;
*su1 = *su2;
*su2 = mid;
su1++;
su2++;
}
}
好了,我们的用冒泡排序模拟qsort就可以出来了:
cs
void Swap(char* su1, char*su2 ,size_t size)
{
for(int i = 0; i<sz ;i++)
{
char mid = *su1;
*su1 = *su2;
*su2 = mid;
su1++;
su2++;
}
}
void my_bubble( void* base, size_t num ,size_t size, int (*compare)(const void* ,const void*)
{
for(int i = 0 ;i <sz-1;i++)
{
for(int j = 0 ;j <sz-1-i ;j++)
{
if(compare((char*)p1+j*size , (char*)p2+(j+1)*size) >0)
{
swap((char*)p1+j*size , (char*)p2+(j+1)*size) ,size);
}
}
}