各位读者好,感谢大家阅读这篇拙作。现在以我对qsort函数的一点点理解,我现在介绍一下qsort函数,如有不足,恳请斧正!
目录
四个参数:(void* bace, size_t num, size_t size, int (*compar)(const void*,const void*))
4.int(*compar)(const void*,const void*)
3.qsort函数排序结构体数组(根据结构体成员name排序)
qsort函数
qsort函数是C语言编译器自带的库函数,它能实现对各种类型的数据进行排序,其底层使用的是快速排序算法,更加详细的信息我们可以在一个C语言网站https://cplusplus.com/上查询,有如下信息:
所需头文件:<stdlib.h>
返回类型:void
四个参数:(void* bace, size_t num, size_t size, int (*compar)(const void*,const void*))
我们详细介绍一下四个参数:
1.void* bace
这个参数就是待排序数据的起始地址 ,也就是待排序数组的第一个元素的地址。至于它的类型为啥是void*的呢?那是因为前面说过qsort函数是可以排序任意类型的数据,那我们就需要一个可以接收任意类型指针的参数,void*就可以接受任意类型的指针。
2.size_t num
这个参数就是待排序数据的元素个数,也就是第一个参数(base)指向的数组元素个数。
3.size_t size
这个参数就是待排序数据的一个元素的大小,也就是第一个参数(base)指向的数组元素大小,单位是字节。因为qsort函数可以排序任意类型的数据,所以我们必须知道排序数据的大小以方便排序时访问几个字节。
4.int(*compar)(const void*,const void*)
这个参数是一个函数指针,指向了一个比较函数(使用qsort函数时需自己完成这个比较函数),这个比较函数是用来比较需比较的2个元素的。通俗一点来说,我们使用qsort函数排序数据时,我们要自己完成一个比较函数 并将这个比较函数的地址(函数名)传参给qsort函数当作qsort函数的第四个参数。
比较函数的参数有两个,这两个参数都是指针,这两个指针分别指向所需比较的某两个数据。至于比较函数的返回类型是int ,返回值分三种情况:如果第一个指针(void *p1)指向的数据如果大于第二个指针(void* p2)所指向的数据,就返回一个大于0的数值;如果相等就返回一个等于0的数值;如果第一个指针指向的数据小于第二个指针指向的数据,就返回一个小于0的数值。其实这个比较函数就是告诉qsort函数所需比较的数据改如何比较。
qsort函数的应用
我们可以举几个例子:
1.qsort函数排序整形数组(升序)
#include<stdio.h>
#include<stdlib.h>
void Print(int* arr, size_t count)//打印数组
{
int i = 0;
for (i = 0; i < count; i++)
{
printf("%d ", *(arr + i));
}
printf("\n");
}
int com_int(const void* p1, const void* p2)//比较函数
{
return *(int*)p1 - *(int*)p2; /*p1的类型(void* )不能直接解引用,
因为p1指向的数据为int型,所以要强制类型转换成int* 类型*/
}
int main()
{
int arr[] = { 5,7,8,9,6,0,1,2,3,4 }; //乱序整形数组
size_t count = sizeof(arr) / sizeof(arr[0]);
Print(arr, count); //调用函数打印排序前的数组
qsort(arr, count, sizeof(arr[0]), com_int); //调用qsort函数排序数组
Print(arr, count); //调用函数打印排序后的数组
return 0;
}
2.qsort函数排序整形数组(降序)
#include<stdio.h>
#include<stdlib.h>
void Print(int* arr, size_t count)//打印数组
{
int i = 0;
for (i = 0; i < count; i++)
{
printf("%d ", *(arr + i));
}
printf("\n");
}
int com_int(const void* p1, const void* p2)//比较函数
{
return *(int*)p2 - *(int*)p1; /*p1的类型(void* )不能直接解引用,
因为p1指向的数据为int型,所以要强制类型转换成int* 类型*/
}
int main()
{
int arr[] = { 5,7,8,9,6,0,1,2,3,4 }; //乱序整形数组
size_t count = sizeof(arr) / sizeof(arr[0]);
Print(arr, count); //调用函数打印排序前的数组
qsort(arr, count, sizeof(arr[0]), com_int); //调用qsort函数排序数组
Print(arr, count); //调用函数打印排序后的数组
return 0;
}
我们可以看到升序排序和降序排序的代码基本一致,只需将更改比较函数的函数体即可。将函数体改变时,使用qsort函数时内部的逻辑就相反了,所以可以实现升序到降序的改变。
3.qsort函数排序结构体数组(根据结构体成员name排序)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct stu
{
char name[20];
size_t age;
size_t weight;
};
int com_structstubyname(const void* p1, const void* p2)//比较函数
{
return strcmp(((struct stu*)p1)->name, ((struct stu*)p2)->name);
}
int main()
{
struct stu student[] = { {"luo",20,48},{"huang",19,58},{"chen",25,60} };
int len = strlen(student);
int i = 0;
for (i = 0; i < len; i++)//打印排序前结构体成员name
{
printf("%s ", student[i].name);
}
printf("\n");
qsort(student, len, sizeof(student[0]), com_structstubyname);
for (i = 0; i < len; i++)//打印排序后结构体成员name
{
printf("%s ", student[i].name);
}
printf("\n");
return 0;
}
最后,在此强调void*类型的指针变量时不能直接解引用的,我们要将其强制类型转换成所需排序数据所对应的指针类型变量。
感谢阅读,欢迎斧正!