一.qsort函数
1.功能: 对任意类型的数组进行排序
csvoid qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
void *base:指向要排序的数组的起始地址 (第一个元素的地址)类型是
void *(通用指针),这意味着qsort可以处理任何数据类型的数组
size_t nmemb:数组中元素的数量
size_t size: 数组中每个元素的大小 (以字节为单位)使用
sizeof(数组元素类型)或sizeof(array[0])来获取int (*compar)(const void *, const void *)这是一个函数指针 ,指向用户提供的比较函数
这个函数决定了排序的顺序(升序、降序、按特定规则)
它接受两个
const void *参数(指向要比较的两个元素的指针)它返回一个
int值,表示两个元素的比较结果2.核心:比较函数
compar函数签名必须匹配
csint your_comparison_function_name(const void *a, const void *b);参数
a和b是指向数组中两个待比较元素的指针使用
const void *是为了保证函数不会修改原始数据,并且qsort可以传递任何类型的指针返回值必须是
int返回值规则:
如果a指向的元素 应该排在b指向的元素 前面 ,则返回一个 负数 (通常用-1表示)
如果a指向的元素 等于b指向的元素,则返回 0
如果a指向的元素 应该排在b指向的元素 后面 ,则返回一个 正数 (通常用1表示)
简单记忆:a - b返回负、零、正,对应a排在b前、相等、后3.示例 1:对
int数组升序排序
csint compare_ints_asc(const void *a, const void *b) { // 1. 将 void* 转换为 int* const int *ia = (const int *)a; const int *ib = (const int *)b; // 2. 比较值并返回结果 // 升序:a - b return (*ia - *ib); // 更严谨的写法(避免整数溢出): // if (*ia < *ib) return -1; // else if (*ia > *ib) return 1; // else return 0; }解释:
*ia - *ib如果ia的值小,结果是负数,表示ia应该排在ib前面(升序)。如果ia的值大,结果是正数,表示ia应该排在ib后面(升序)。相等则返回 0
注意: 直接使用*ia - *ib在值非常大时可能导致整数溢出(例如INT_MIN - 1)。更安全的方式是使用if语句进行显式比较4.示例 2:对
int数组降序排序
csint compare_ints_desc(const void *a, const void *b) { const int *ia = (const int *)a; const int *ib = (const int *)b; // 降序:b - a return (*ib - *ia); // 安全写法: // if (*ib < *ia) return -1; // b < a, 我们希望 b 排前面?不,降序需要 b > a 才排前面 // else if (*ib > *ia) return 1; // b > a, 我们希望 b 排后面?不 // else return 0; // 更清晰的降序写法: if (*ia > *ib) return -1; // a > b, 我们希望 a 排前面 -> 返回负 else if (*ia < *ib) return 1; // a < b, 我们希望 a 排后面 -> 返回正 else return 0; }解释: 要降序,只需反转比较结果。
*ib - *ia如果ib的值小(即ia的值大),结果是负数,表示ia应该排在ib前面(符合降序:大数在前)。如果ib的值大(即ia的值小),结果是正数,表示ia应该排在ib后面(符合降序:小数在后)。同样可以使用if语句显式控制5.示例 3:对
char *数组(字符串数组)按字典序升序排序
cs#include <string.h> // 需要 strcmp int compare_strings_asc(const void *a, const void *b) { // 1. 将 void* 转换为 char** (因为数组元素是 char*, 所以指针是指向 char* 的指针) const char **str_a = (const char **)a; const char **str_b = (const char **)b; // 2. 使用 strcmp 比较字符串 return strcmp(*str_a, *str_b); }
csreturn strcmp(*(const char **)a, *(const char **)b);
6.对结构体数组按特定字段排序
csstruct Person { char name[50]; int age; float height; };
按 age升序排序:
csint compare_person_by_age_asc(const void *a, const void *b) { const struct Person *pa = (const struct Person *)a; const struct Person *pb = (const struct Person *)b; // 比较 age 字段 if (pa->age < pb->age) return -1; else if (pa->age > pb->age) return 1; else return 0; // 或者更简洁(注意可能的溢出): // return (pa->age - pb->age); }
按 name字段字典序升序排序
csint compare_person_by_name_asc(const void *a, const void *b) { const struct Person *pa = (const struct Person *)a; const struct Person *pb = (const struct Person *)b; // 直接比较结构体内的 name 字符数组 return strcmp(pa->name, pb->name); }
按 height降序排序,若 height相同则按 age升序排序:
csint compare_person_by_height_desc_age_asc(const void *a, const void *b) { const struct Person *pa = (const struct Person *)a; const struct Person *pb = (const struct Person *)b; // 先比较 height (降序) if (pa->height > pb->height) return -1; // pa 更高,我们希望 pa 排前面 -> 返回负 else if (pa->height < pb->height) return 1; // pa 更矮,我们希望 pa 排后面 -> 返回正 else { // height 相等,再按 age 升序 return (pa->age - pb->age); // 升序直接减 } }
7.原地排序: qsort直接修改传入的数组 (base),是原地排序算法。原始数组的顺序会被改变。
CPrimer Plus第十六章C预处理器和C库总结2-qsort函数
qiuiuiu4132025-10-08 19:59
相关推荐
前端小L3 小时前
单调栈的“降维打击”:从直方图到矩阵——再探「最大矩形」逐步前行3 小时前
C数据结构--数组|矩阵|广义表小丁努力不焦虑3 小时前
c++基本语法Olrookie3 小时前
Maven快速上手笔记喵手3 小时前
调试技巧:从 IDE 调试到生产环境定位问题,提升调试效率的全方位指南货拉拉技术3 小时前
大模型音频水印技术:用AI守护音频数据的“身份指纹”ysa0510304 小时前
利用数的变形简化大规模问题#数论喜欢读源码的小白4 小时前
Spring Boot+MyBatis实现无限层级组织架构设计|邻接表vs闭包表性能对比|树形结构数据存储方案安当加密4 小时前
基于ASP身份认证服务器实现远程办公VPN双因素认证的架构与实践奔跑吧邓邓子4 小时前
【C语言实战(59)】C语言打造你的专属密码管家