C标准库qsort()函数可以实现对数组的快速排序,其原型如下:
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*));
第1个参数是指针,指向待排序数组的首元素。ANSI C允许va指向任何数据类型的指针强制转换成指向void的指针,因此,qsort()的第一个实际参数可以引用任何类型的数组。
第2个参数是待排序项的数量。函数原型把该值转换为size_t类型。size_t定义在标准头文件中,是sizeof运算符返回的整数类型。
由于qsort()把第1个参数转换为void指针,所以qsort()不知道数组中的每个元素的大小。为此,函数原型用第3个参数补偿这以信息,显示指明待排序数组中每个元素的大小。例如,如果排序double类型的数组,那么第3个函数应该是sizeof(double)。
最后,qsort()还需要一个指向函数的指针,这个被指针指向的比较函数用于确定排序的顺序。改函数应接受两个参数:分别指向待比较两项的指针。
如果第1项大于第2项,比较函数返回正数;如果两项相同,则返回0;如果第1项的值小于第2项,则返回负数。
比较函数的形式:
int (*compar)(const void *, const void*))
表明qsort()最后一个参数是一个指向函数的指针,该函数返回int类型的值且接受两个指向
const void的指针作为参数,这两个指针指向待比较项。
那如何使用比较函数呢?
int mycomp(const void* p1, const void* p2)
{
const double* a1 = (const double*)p1;
const double* a2 = (const double*)p2;
if (*a1 < *a2)
return -1;
else if (*a1 == *a2)
return 0;
else
return 1;
}
为了比较指针所指向的值,必须解引用指针。因为值是double类型,所以要把指针解引用为double类型的值。必须把每个数组中每个元素的大小明确告诉qsort(),并且再比较函数的定义中,必须把该函数的指针参数转换为对具体应用而言类型正确的指针。
更简洁的写法:
int mycomp(const void *a, const void *b)
{
const int *aa = (int*)a;
const int *bb = (int*)b;
return (*aa > *bb) - (*aa < *bb);
}
return *(int *)a < *(int *)b ? -1 : *(int *)a > *(int *)b;//升序排序
return *(int *)a < *(int *)b ? *(int *)a > *(int *)b : -1;//降序排序
qsort()函数的用法:
#include <stdio.h>
#include <stdlib.h>
int values[] = { 88, 56, 100, 2, 25 };
int mycomp (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int main()
{
int n;
printf("排序之前的列表:\n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
qsort(values, 5, sizeof(int), mycomp);
printf("\n排序之后的列表:\n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
return(0);
}
使用qsort排序整型数据:
#include <stdio.h>
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;
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(int), cmp);
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
使用qsort排序结构数据:
#include <stdio.h>
#include <string.h>
struct Stu
{
char name[10];
int age;
};
int cmp_age(const void* p1, const void* p2)
{
return ((struct Stu*)p1)->age- ((struct Stu*)p2)->age;
}
int cmp_name(const void* p1, const void* p2)
{
return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}
int main()
{
struct Stu s[] = { {"zhangsan",20},{"lisi",18},{"wangwu",30} };
int sz = sizeof(s) / sizeof(s[0]);//元素个数
//选1年龄,选2姓名,其他退出
int input = 0;
int i = 0;
scanf("%d", &input);
if (input == 1)
{
qsort(s, sz, sizeof(s[0]), cmp_age);
}
else if (input == 2)
{
qsort(s, sz, sizeof(s[0]), cmp_name);
}
for (i = 0; i < sz; i++)
{
printf("%s\n", s[i]);
}
return 0;
}