什么是qsort函数
qsort - Quick Sort
是c语言中一种用于排序的函数,这种方法也叫作快速排序法。
它与冒泡排序不同,冒泡排序是一种算法,而qsort是c语言中编译器函数库自带的排序函数,存在于stdlib.h文件中。
qsort 函数可以根据使用者的不同需求快速的实现不同数据的排序。
qsort函数的使用方法
在c语言的学习中,我们需要 “善假于工具”,在cplusplus中,提供了qsort函数的使用方法以及功能参数等。
功能
参数
使用方法
根据 cplusplus 提供的参数以及功能,能大致了解qsort的使用方法。
存在一个整形数组arr,且数组内的元素均为整形。
现在需要使用qsort函数 - 快速排序 将数组内的元素进行排序:
#include<stdio.h> test1() { int arr[] = {9,8,7,6,5,4,3,2,1,0};//整形数组 } int main() { test1(); return 0; }
根据cplusplus给出的参数,可以知道,在qsort中所需要的参数为:
- 指向数组首元素地址的指针;
- 数组内的元素个数;
- 数组内各个元素的大小;
- 以及可以用来判断两个数大小的函数compar( ),且该函数的返回值为int;
指向数组首元素地址的指针:
根据数组名即为首元素地址(大多数情况下),得出在传入第一个参数时,可以传入需要排列数组的数组名。
数组内元素个数:
第二个参数 - size_t num 需要排列数据的个数,即数组元素个数 - sizeof(arr) / sizeof(arr[0])
即用数组总大小除以数组内单个元素大小。
数组内各个元素大小:
第三个参数,size_tsize,需要排列的数组内元素的大小 - sizeof(arr[0])。
comper函数:
除了前三个参数,还需要一个函数指针
int (*compar)(const void*,const void*));
该指针指向的函数可以用来接收数组内两个需要比较的数据的地址,并返回整形值,若两个数比较(p1,p2),p1对应的值>p2对应的值,返回大于0的数;p1对应的值==p2对应的值,则返回0;p1对应的值<p2对应的值,则返回小于0的数。故在使用qsort函数的同时,也需创建一个同样类型的函数,根据需要返回的值进行判断,在进行排序整形时,只需要作差即可 (默认为升序,若是需要降序则将p1,p2位置调换即可)。
compar(const void*p1,const void*p2) { return *(int*)p1 -*(int*)p2; }
在这里也有个疑问,在使用数据时为什么需要将p1,p2进行强转类型呢?
在该函数的创建过程中,因为不能保证使qsort函数的使用者进行什么类型的排序,所以在函数创建的过程中,参数使用了void*(可接收任意类型的指针)进行接收;再者,该类型的指针不能直接进行解引用操作(erro - 非法间接访问),故在使用时需要进行强制类型转换。
下列代码为排列整形数据的例子:
void print(int arr[], int sz) { //打印函数 for (int i = 0; i < sz; i++) { printf("%d ", arr[i]); } } int compar(void* p1, void* p2) { //该函数需要使用者自行创建 return *(int*)p1 - *(int*)p2; } void test1() { 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]), compar); print(arr,sz);//打印函数 } int main() { test1(); return 0; }
qsort函数排序其他
qsort为不仅可以排序整形,还可以排序浮点型、字符型、字符串型、结构体类型等等…
qsort排序浮点型
int compar_by_float(void* p1, void* p2) { if (*(float*)p1 == *(float*)p2) { return 0; } return *(float*)p1 > * (float*)p2 ? 1 : -1; } void print(float flArr[], int sz) { for (int i = 0; i < sz; i++) { printf("%.2f ", flArr[i]); } } void test3() { //排列浮点型数据 float flArr[] = { 2.0f, 3.5f, 4.8f, 1.2f, 0.9f, 6.6f, 4.4f, 1.6f, 0.2f }; int sz = sizeof(flArr) / sizeof(flArr[0]); qsort(flArr, sz, sizeof(flArr[0]), cmp_by_float); print(flArr,sz); } int main() { test3();//浮点类型数据 return 0; }
浮点型数据在compar函数中,若是作差再使用int进行返回时,会出现精确丢失,所以不可作差;
可采用两种方式:一是使用if判断进行返回,二是将返回类型改为double型;
// 一 int compar_by_float(void* p1, void* p2) { if (*(float*)p1 == *(float*)p2) { return 0; } return *(float*)p1 > * (float*)p2 ? 1 : -1; } //-------------------------------------------------- // 二 double compar_by_float(void* p1, void* p2) { return *(float*)p1 - *(float*)p2) ; }
qsort排序结构体类型 - 字符串
struct Stu { char name[20]; int age; }; print(struct Stu s[], int sz) { for (int i = 0; i < sz; i++) { printf("%s ", s[i].name); } } int cmp_str_name(void* p1, void* p2) { return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name); } void test2() {//排列结构体类型数据 struct Stu s[5] = { {"Xiaoli",52} ,{"Zhangqiang",28}, {"Milaotou",66}, {"Mazi",35}, {"Wangwu",26} }; int sz = sizeof(s) / sizeof(s[0]); qsort(s,sz,sizeof(s[0]),cmp_str_name); print(s,sz); } int main() { test2();//结构体 字符串 return 0; }
字符串类型的比较大小不可用 < , > , == 进行比较,只能使用strcmp( )函数进行比较,而比较的结果与qsort函数所需的返回值相同:
故可以直接作为返回类型。
int cmp_str_name(void* p1, void* p2) { return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name); }
结构体类型 - 整形 同理。