qsort函数(快速排序)

qsort 是 C 标准库中提供的通用快速排序函数 ,定义在 <stdlib.h> 头文件中。它的核心优势是支持对任意类型的数组(int、char、字符串、结构体等)进行排序,通过函数指针实现类型无关的比较逻辑,是 C 语言中最常用的排序工具之一。

一、函数原型

cs 复制代码
void qsort(
    void *base,        // 待排序数组的起始地址
    size_t nitems,     // 数组中元素的个数
    size_t size,       // 单个元素的字节大小
    int (*compar)(const void *, const void *)  // 比较函数的指针
);

二、参数详细解析

参数 类型 说明
base void* 指向待排序数组的首地址,void* 支持任意类型数组(int/char/ 结构体等)
nitems size_t 数组元素的总个数,size_t 是无符号整数类型(通常等价于 unsigned int
size size_t 单个元素的字节大小,通常用 sizeof(元素类型) 获取(如 sizeof(int)
compar 函数指针 int (*)(const void*, const void*) 自定义比较函数,决定排序规则(升序 / 降序 / 按结构体字段排序)

三、核心:比较函数 compar

qsort 的排序逻辑完全由比较函数决定,需遵循以下规则:

1. 函数格式
cs 复制代码
int compar(const void *a, const void *b);
  • a/b:指向待比较的两个数组元素(const 保证不修改原数据);
  • 返回值规则:
    • 返回 < 0a 应排在 b 前面(a < b);
    • 返回 0ab 相等;
    • 返回 > 0a 应排在 b 后面(a > b)。
2. 关键注意点

void* 指针不能直接解引用,必须先强制转换为数组元素的实际类型,再解引用比较。

3. 常见比较函数示例
示例 1:int 数组(升序 / 降序)
cs 复制代码
// 升序(a < b 时返回负数)
int compare_int_asc(const void *a, const void *b) {
    // 转换为 int* 后解引用
    int num1 = *(const int*)a;
    int num2 = *(const int*)b;
    return num1 - num2;  // 升序:小的在前
}

// 降序(a > b 时返回负数)
int compare_int_desc(const void *a, const void *b) {
    int num1 = *(const int*)a;
    int num2 = *(const int*)b;
    return num2 - num1;  // 降序:大的在前
}
示例 2:字符串数组(按字典序排序)
cs 复制代码
#include <string.h>  // 需引入 strcmp
// 字符串数组的元素是 char*,因此 a/b 是 char** 类型
int compare_str(const void *a, const void *b) {
    const char *str1 = *(const char**)a;
    const char *str2 = *(const char**)b;
    return strcmp(str1, str2);  // strcmp 天然符合 qsort 返回规则
}
示例 3:结构体数组(按结构体字段排序)
cs 复制代码
// 定义结构体
typedef struct {
    char name[20];
    int age;
} Person;

// 按年龄升序排序
int compare_person_age(const void *a, const void *b) {
    const Person *p1 = (const Person*)a;
    const Person *p2 = (const Person*)b;
    return p1->age - p2->age;
}

// 按名字字典序排序
int compare_person_name(const void *a, const void *b) {
    const Person *p1 = (const Person*)a;
    const Person *p2 = (const Person*)b;
    return strcmp(p1->name, p2->name);
}

四、完整使用示例

示例 1:排序 int 数组

cs 复制代码
#include <stdio.h>
#include <stdlib.h>

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

int main() {
    int arr[] = {5, 2, 9, 1, 5, 6};
    int n = sizeof(arr) / sizeof(arr[0]);

    // 调用 qsort
    qsort(arr, n, sizeof(int), compare_int_asc);

    // 输出排序结果:1 2 5 5 6 9
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}

示例 2:排序字符串数组

cs 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int compare_str(const void *a, const void *b) {
    return strcmp(*(const char**)a, *(const char**)b);
}

int main() {
    const char *strs[] = {"banana", "apple", "orange", "grape"};
    int n = sizeof(strs) / sizeof(strs[0]);

    qsort(strs, n, sizeof(char*), compare_str);

    // 输出:apple banana grape orange
    for (int i = 0; i < n; i++) {
        printf("%s ", strs[i]);
    }
    return 0;
}

示例 3:排序结构体数组

cs 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char name[20];
    int age;
} Person;

// 按年龄升序
int compare_person_age(const void *a, const void *b) {
    const Person *p1 = (const Person*)a;
    const Person *p2 = (const Person*)b;
    return p1->age - p2->age;
}

int main() {
    Person people[] = {
        {"Alice", 25},
        {"Bob", 20},
        {"Charlie", 30}
    };
    int n = sizeof(people) / sizeof(people[0]);

    qsort(people, n, sizeof(Person), compare_person_age);

    // 输出:Bob(20) Alice(25) Charlie(30)
    for (int i = 0; i < n; i++) {
        printf("%s(%d) ", people[i].name, people[i].age);
    }
    return 0;
}

五、注意事项

  1. void 转换*:必须严格转换为数组元素的实际类型,否则会导致内存错误(如 int 数组转 char* 会读取错误字节);
  2. size_t 类型nitemssize 是无符号数,不能传入负数;
  3. 排序稳定性qsort不稳定排序(相同值的元素相对位置可能变化),若需稳定排序需自行实现
复制代码
   int compare_int_safe(const void *a, const void *b) {
       int x = *(const int*)a;
       int y = *(const int*)b;
       return (x > y) - (x < y);  // 无溢出风险
   }
  1. 底层实现 :标准未规定具体排序算法,多数编译器(如 glibc)的 qsort 是「快速排序 + 插入排序 + 堆排序」的混合实现(优化小数据量和最坏情况)。

总结

qsort 是 C 语言中灵活且高效的通用排序函数,核心是通过自定义比较函数适配任意类型数组。使用时只需关注:

  1. 正确传递数组地址、元素个数、元素大小;
  2. 编写符合规则的比较函数(重点是 void* 类型转换)。
相关推荐
轻描淡写6062 小时前
二进制存储数据
java·开发语言·算法
爱潜水的小L2 小时前
自学嵌入式day28,文件操作
linux·数据结构·算法
2301_800399722 小时前
误用sizeof()计算指针
算法
ULTRA??2 小时前
QT向量实现GJK碰撞检测算法几何图形二维版本
c++·qt·算法
flashlight_hi2 小时前
LeetCode 分类刷题:987. 二叉树的垂序遍历
数据结构·算法·leetcode
小尧嵌入式2 小时前
C++模板
开发语言·c++·算法
仰泳的熊猫2 小时前
1120 Friend Numbers
数据结构·c++·算法·pat考试
仰泳的熊猫2 小时前
1116 Come on! Let‘s C
数据结构·c++·算法·pat考试
Bear on Toilet3 小时前
17 . 爬楼梯
算法·深度优先