资讯详情

资讯详情

C 语言 `qsort` 函数介绍

C 语言qsort函数介绍qsort是 C 标准库stdlib.h中提供的通用排序函数可以对任意类型的数组进行排序通常内部使用快速排序但标准并未规定具体算法。1. 函数原型#includestdlib.hvoidqsort(void*base,size_tnmemb,size_tsize,int(*compar)(constvoid*,constvoid*));参数说明参数含义base指向待排序数组首元素的指针void *可接受任意类型nmemb数组中元素的个数size每个元素的字节大小通常写sizeof(元素类型)compar比较函数的函数指针返回值无返回值排序结果直接写回base指向的数组。2. 比较函数比较函数是qsort的核心签名必须是intcompar(constvoid*a,constvoid*b);它需要比较a、b指向的两个元素返回值约定如下返回负数a应排在b前面返回 0两者相等顺序不确定返回正数a应排在b后面在比较函数内部通常需要先把void *强制转换为实际元素类型。3. 使用示例3.1 排序整数数组#includestdio.h#includestdlib.hintcmp_int(constvoid*a,constvoid*b){intia*(constint*)a;intib*(constint*)b;return(iaib)-(iaib);/* 避免 ia - ib 溢出 */}intmain(void){intarr[]{5,2,9,1,5,6};size_tnsizeof(arr)/sizeof(arr[0]);qsort(arr,n,sizeof(int),cmp_int);for(size_ti0;in;i)printf(%d ,arr[i]);printf(\n);return0;}注意不要写成return *(int*)a - *(int*)b;当两个数相差很大时可能发生整数溢出导致比较结果错误。3.2 排序结构体数组#includestdio.h#includestdlib.h#includestring.htypedefstruct{charname[32];intage;}Person;/* 先按年龄升序年龄相同按姓名升序 */intcmp_person(constvoid*a,constvoid*b){constPerson*pa(constPerson*)a;constPerson*pb(constPerson*)b;if(pa-age!pb-age)return(pa-agepb-age)-(pa-agepb-age);returnstrcmp(pa-name,pb-name);}intmain(void){Person people[]{{Alice,30},{Bob,25},{Carol,30},{Dave,20},};size_tnsizeof(people)/sizeof(people[0]);qsort(people,n,sizeof(Person),cmp_person);for(size_ti0;in;i)printf(%s (%d)\n,people[i].name,people[i].age);return0;}3.3 排序字符串指针数组intcmp_str(constvoid*a,constvoid*b){/* 数组元素是 char*所以 a、b 实际是 char** */constchar*const*sa(constchar*const*)a;constchar*const*sb(constchar*const*)b;returnstrcmp(*sa,*sb);}intmain(void){constchar*words[]{banana,apple,cherry,date};size_tnsizeof(words)/sizeof(words[0]);qsort(words,n,sizeof(char*),cmp_str);for(size_ti0;in;i)printf(%s\n,words[i]);return0;}这是新手最常出错的地方字符串数组的元素类型是char *所以传给比较函数的是char **。4. 复杂度与特性平均时间复杂度O(n log n)最坏时间复杂度取决于具体实现理论上可能是 O(n²)空间复杂度通常 O(log n)递归栈稳定性qsort不保证稳定排序。若需要稳定排序需自行附加原始下标作为次级比较键或改用归并排序等算法。5. 注意事项与常见陷阱整数溢出比较函数里不要直接用a - b改用(a b) - (a b)。严格弱序比较函数必须满足严格弱序反对称、传递否则行为未定义。不要修改元素比较函数只应读取不应写入a、b指向的内容。浮点数比较若数组含NaN、比较均为假排序结果可能异常需要特殊处理。size_t是无符号类型向qsort传元素个数和元素大小时不要传负数否则会被转换为巨大的无符号数导致越界。元素大小必须一致size必须是所有元素共同的字节大小qsort不支持变长元素。类型转换保持 const强制转换时保留const限定如const int *避免意外写入。C11 的qsort_s部分实现如 MSVC、C11 附录 K提供带上下文参数的qsort_s但可移植性差一般仍用qsort。6. 小结qsort通过void * 函数指针实现了对任意类型的通用排序是 C 语言中“泛型编程”的经典范例。使用时记住三点正确传入元素个数与元素大小、正确编写比较函数、注意整数溢出与类型转换就能应对绝大多数排序场景。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →