安阳市网站建设_网站建设公司_MySQL_seo优化
2025/12/22 19:27:57 网站建设 项目流程

一、qsort 函数的前世今生

  1. 历史背景
    qsort函数最早出现在C89 标准(1989 年发布的 ANSI C 标准)中,是 C 标准库<stdlib.h>的核心函数之一。它的设计初衷是为 C 语言提供一个通用、高效的排序接口 —— 由于 C 语言是强类型语言,早期的排序函数往往只能针对特定类型(如整型、字符型),而qsort通过函数指针和void 类型指针的结合,实现了对任意数据类型的排序支持,成为 C 语言泛型编程的经典范例。
  2. 底层实现
    qsort的名字源于 “quick sort”(快速排序),标准并未强制要求其实现必须采用快速排序,但主流编译器(如 GCC、Clang、MSVC)均以快速排序为核心,部分版本会在数据量较小时切换为插入排序(优化快速排序的小数据性能)。其时间复杂度平均为O(nlogn),最坏情况为O(n2)(可通过随机化基准值优化),空间复杂度为O(logn)(递归栈开销)。
  3. 标准库依赖
    qsort函数声明在<stdlib.h>头文件中,使用时需包含该头文件;若涉及字符串比较(如结构体中字符串成员排序),还需引入<string.h>头文件,使用strcmp等字符串处理函数。

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

base void* 指向待排序数组的首地址,void*使其能接收任意类型的数组指针
nitems size_t 数组中元素的个数,size_t是 C 语言的无符号整数类型(通常为unsigned int)
size size_t 数组中单个元素的字节大小,需通过sizeof计算
compar 函数指针 自定义比较函数,决定排序规则,返回值需满足:- 负数:第一个参数排在第二个前- 0:两个参数相等- 正数:第一个参数排在第二个后
#include <stdio.h>   // 标准输入输出库,用于打印结果
#include <stdlib.h>  // 包含qsort函数声明,C89标准核心头文件
#include <string.h>  // 包含strcmp字符串比较函数,处理姓名排序/*** @brief 定义学生结构体,包含姓名和分数两个成员* @note name采用字符数组存储,避免指针管理的内存问题;score为整型存储成绩*/
typedef struct {char name[20];  // 学生姓名,固定长度20字节int score;      // 学生分数,整型
} Student;/*** @brief 比较函数:按学生分数降序排序* @param a 指向第一个学生结构体的void指针* @param b 指向第二个学生结构体的void指针* @return int 分数差值(score2 - score1),实现降序* @note void*需强制转换为Student*才能访问结构体成员,const保证不修改原数据*/
int comStudentScore(const void *a, const void *b) {// 将void*转换为const Student*,避免修改原数据int score1 = ((const Student *)a)->score;int score2 = ((const Student *)b)->score;// 分数降序:返回score2 - score1,大分数排在前return score2 - score1;
}/*** @brief 比较函数:按学生姓名字典序降序排序* @param a 指向第一个学生结构体的void指针* @param b 指向第二个学生结构体的void指针* @return int strcmp的返回值,实现姓名降序* @note strcmp基于ASCII码比较字符串,b在前a在后实现降序*/
int comStudentName(const void *a, const void *b) {// strcmp(b->name, a->name):交换参数实现字典序降序return strcmp(((const Student *)b)->name, ((const Student *)a)->name);
}/*** @brief 主函数:初始化学生数据,调用qsort实现双维度排序并打印结果* @param argc 命令行参数个数(本文未使用)* @param argv 命令行参数数组(本文未使用)* @return int 程序退出状态码,0表示正常退出*/
int main(int argc, char* argv[]) {// 初始化学生结构体数组,包含4名学生的姓名和分数Student students[] = {{"Alice", 99},{"Bob", 92},{"ChaLi", 81},{"Davi", 77}};// 计算数组元素个数:总字节数 / 单个元素字节数int n = sizeof(students) / sizeof(Student);// 1. 按分数降序排序qsort(students, n, sizeof(Student), comStudentScore);printf("===== 按分数降序排序结果 =====\n");for (int i = 0; i < n; i++) {printf("姓名:%-6s 分数:%d\n", students[i].name, students[i].score);}printf("\n");  // 换行分隔,优化输出格式// 2. 按姓名字典序降序排序qsort(students, n, sizeof(Student), comStudentName);printf("===== 按姓名降序排序结果 =====\n");for (int i = 0; i < n; i++) {printf("姓名:%-6s 分数:%d\n", students[i].name, students[i].score);}return 0;  // 程序正常退出
}
// 按浮点分数降序排序
int comStudentFloatScore(const void *a, const void *b) {float score1 = ((const Student *)a)->score;float score2 = ((const Student *)b)->score;if (score1 > score2) return -1;  // 降序:大值在前else if (score1 < score2) return 1;else return 0;
}
int comStudentMulti(const void *a, const void *b) {const Student *s1 = (const Student *)a;const Student *s2 = (const Student *)b;// 先按分数降序if (s1->score != s2->score) {return s2->score - s1->score;}// 分数相同时按姓名升序return strcmp(s1->name, s2->name);
}

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询