qsort的使用

核心:stdlib.h中的通用排序函数,支持任意数据类型,关键靠自定义比较函数控制排序规则。

一、函数原型

void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *));

4个参数拆解(精准抓重点):

  1. base:待排序数组的首地址(直接传数组名即可);

  2. nitems:数组中元素总个数;

  3. size:单个元素的字节大小(用 sizeof(元素类型) 获取,避免出错);

  4. compar:比较函数指针,排序规则由这个函数决定(核心关键)。

总结:qsort(指定数组首地址即数组名,元素个数,单个元素大小,比较函数);

二、核心:自定义比较函数

  1. 比较函数原型(固定格式,不能改)

int compar(const void *a, const void *b);

• 入参 a、b:指向两个待比较元素的指针(必须先强制转换为对应数据类型指针,再解引用);

• 返回值规则(固定逻辑,决定升/降序):

◦ 返回 < 0:a 排在 b 前面(升序核心);

◦ 返回 = 0:a 和 b 排序位置不变;

◦ 返回 > 0:a 排在 b 后面(降序核心)。

  1. 常见数据类型示例(直接复用)

(1)int 型数组(最常用)

复制代码
// 升序(默认常用)
int cmp_int_asc(const void *a, const void *b) {
    return *(int*)a - *(int*)b; // a比b小,返回负,a在前
}

// 降序
int cmp_int_desc(const void *a, const void *b) {
    return *(int*)b - *(int*)a; // 反过来减,b比a小,a在后
}

(2)double 型数组(注意:不能直接减,避免精度丢失)

复制代码
// 升序
int cmp_double_asc(const void *a, const void *b) {
    return *(double*)a > *(double*)b ? 1 : -1; // 用三目运算符判断
}

// 降序
int cmp_double_desc(const void *a, const void *b) {
    return *(double*)a < *(double*)b ? 1 : -1;
}

(3)结构体数组(算法竞赛高频场景)

复制代码
//假设结构体存储学生成绩,按成绩升序排:
typedef struct {
    char name[20];
    int score;
} Student;

// 按score升序排
int cmp_student(const void *a, const void *b) {
    return ((Student*)a)->score - ((Student*)b)->score;
}

(4)常见

复制代码
#include <stdio.h>
#include <stdlib.h> // 必须包含头文件

// 自定义比较函数(int升序)
int cmp_int(const void *a, const void *b) {
    return *(int*)a - *(int*)b;
}

int main() {
    int arr[] = {5, 2, 9, 1, 3};
    int len = sizeof(arr) / sizeof(arr[0]); // 计算元素个数
    
    qsort(arr, len, sizeof(int), cmp_int); // 调用qsort
    
    // 打印结果:1 2 3 5 9
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}

三、注意点

  1. 头文件必加:#include <stdlib.h>,否则编译报错;

  2. 元素大小精准:size 必须是单个元素字节数,比如 sizeof(int)、sizeof(Student),别写死数字;

  3. double 比较:严禁直接 *(double*)a - *(double*)b,精度丢失会导致排序异常,用三目运算符;

  4. 结构体比较:若按多个条件排(如成绩相同按姓名字典序),可嵌套判断,例:

// 成绩升序,成绩相同则姓名字典序升序(用strcmp,string.h头文件)

int cmp_student2(const void *a, const void *b) {

Student s1 = *(Student*)a;

Student s2 = *(Student*)b;

if (s1.score != s2.score) return s1.score - s2.score;

return strcmp(s1.name, s2.name); // strcmp返回值符合compar规则

}

  1. 效率:平均时间复杂度 O(n log n),竞赛中大部分场景够用,无需手动写排序。
相关推荐
STDD几秒前
ntfy 自托管推送通知服务搭建:一条 curl 命令向手机发送通知
java·开发语言·智能手机
AbandonForce3 分钟前
滑动窗口:定长滑动窗口与不定长滑动窗口
数据结构·c++·算法
周末也要写八哥10 分钟前
线程的生命周期之线程睡眠
java·开发语言·jvm
炸薯条!15 分钟前
二叉树的链式表示(2)
java·数据结构·算法
Tairitsu_H19 分钟前
[LC优选算法#2] 滑动窗口 | 长度最小的子数组 | 无重复字符的最长子串 | 最大连续1的个数
算法
小欣加油20 分钟前
leetcode3689最大子数组总值I
c++·算法·leetcode·职场和发展·贪心算法
徐寿春27 分钟前
什么是数据倾斜
java·guava
下午写HelloWorld28 分钟前
【概念与应用】轻量级加密算法LEA、动态脱敏算法DDA、零知识证明ZKP和优化协同交互协议OCIP
算法·区块链·密码学·安全架构·零知识证明
李白的天不白35 分钟前
一个服务器可以搭建多个网站
java·tomcat
●VON35 分钟前
AtomGit Flutter鸿蒙客户端:共享组件
java·flutter·华为·harmonyos·鸿蒙