我们之前写的冒泡排序只能排序整型数组,
而qsort是C语言提供的一个库函数,
可以排序任意类型的数据。
这里给出c++官网的qsort函数说明:
通过官网的说明,我们可以发现:
在qsort函数里,我们还调用了一个函数——compar().
也就是说,我们是在某一个函数里,通过一个函数的地址去访问了这个新的函数,
那么在此处,compar()函数就是我们上一节学习的回调函数。
qsort对比于我们之前写的冒泡排序的优势在于,他可以排任何数据类型的序。
比如,我们创建一个结构体,
struct Stu
{
char name[20];
int age;
}
struct Stu s[3] = {{"zhangsan",20},{"lisi",21},{"wangwu",22}};
我们想对这个学生列表,以年龄的大小排序,
这时候,整型的冒泡排序就做不到了,
同理,整型的冒泡排序也无法排浮点型的数组。
所以,我们需要借助qsort函数,一个更通用的函数,来排序。
注:qsort函数是借助快速排序算法来实现的,这里我们使用冒泡排序来改编。
这是C库函数提供的qsort的参数和返回类型:
void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
分别是:
1个void的指针,
2个size_t的参数,
1个函数指针。
base:目标数组的起始位置 ------ arr
num:数组的元素个数 ------ sizeof(arr)/sizeof(arr[0])
width:元素大小单位 ------ sizeof(arr[0])
compar:比较函数
我们首先来分析一下这个函数:
因为每个数据的类型是不一样的,
所以我们可以封装一个比较函数,
把地址传进排序函数,
到时候用指针去调用所指向的函数即可。
无类型指针。
先测量一下他的大小:
printf("%d\n", sizeof(void*));
结果是4.
再看看他能存放哪些数据的地址:
同理,可以存放任何数据类型的地址。
但是,如果在这里,对pa进行解引用:*pa,
就会报错,
同理,void类型的指针不能进行+1运算,
原因在于:你并不知道这个指针要访问几个字节。
综上,
void*不能解引用,不能++。
现在我们回到这个比较函数。
int int_cmp(const void * p1, const void * p2),
这个函数的两个参数都是空指针,不知道访问几个字节,
但是我们需要比较他们的数据大小,需要解引用,怎么办?
强制类型转换即可。
(int*)e1,(int*)e2.
然后再解引用:
*(int*)e1,*(int*)e2.
做差:
*(int*)e1-*(int*)e2
作为返回值。
这个函数会:
当第一个元素较大时,返回正数;
当两个元素相等时,返回0;
当第二个元素较大时,返回负数。
现在我们演示一下qsort函数的使用:
#include
//qsort函数的使用者得实现一个比较函数
int int_cmp(const void * p1, const void * p2)
{
return (*( int *)p1 - *(int *) p2);
}
int main()
{
int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
int i = 0;
qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);
for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++)
{
printf( "%d ", arr[i]);
}
printf("\n");
return 0;
}
qsort的使用方法:
第一个参数:待排序数组的首元素地址
第二个参数:待排序数组的元素个数
第三个参数:待排序数组的每个元素的大小-单位是字节
第四个参数:是函数指针,比较两个元素的所用函数的地址,这个函数由使用者自己实现
函数指针的两个参数是:待比较的两个元素的地址
#include
int int_cmp(const void * p1, const void * p2)
{
return (*( int *)p1 - *(int *) p2);
}
void _swap(void *p1, void * p2, int size)
{
int i = 0;
for (i = 0; i< size; i++)
{
char tmp = *((char *)p1 + i);
*(( char *)p1 + i) = *((char *) p2 + i);
*(( char *)p2 + i) = tmp;
}
}
void bubble(void *base, int count , int size, int(*cmp )(const void *,const void *))
{
int i = 0;
int j = 0;
for (i = 0; i< count - 1; i++)
{
for (j = 0; j 0)
{
_swap(( char *)base + j*size, (char *)base + (j + 1)*size, size);
}
}
}
}
int main()
{
int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
//char *arr[] = {"aaaa","dddd","cccc","bbbb"};
int i = 0;
bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);
for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++)
{
printf( "%d ", arr[i]);
}
printf("\n");
return 0;
}