当前位置: 首页 > article >正文

[C语言日寄] qsort函数的练习

在这里插入图片描述

【作者主页】siy2333
【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是进阶开发者,这里都能满足你的需求!
【食用方法】1.根据题目自行尝试 2.查看基础思路完善题解 3.学习拓展算法
【Gitee链接】资源保存在我的Gitee仓库:https://gitee.com/siy2333/study


文章目录

  • 前言
  • 题目引入
  • 一、qsort函数的定义与使用
    • qsort函数的定义
    • qsort函数的使用
      • 1. 示例:对整数数组排序
      • 2. 示例:对结构体数组排序
  • 二、知识点分析
    • 1. qsort函数的参数
      • base参数
      • nitems参数
      • size参数
      • compar参数
    • 2. 比较函数的编写
      • 对整数数组排序
      • 对浮点数数组排序
      • 对字符串数组排序
      • 对结构体数组排序
    • 3. qsort函数的工作原理
  • 三、注意事项
    • 1. 比较函数的返回值
    • 2. 比较函数的参数类型
    • 3. 数组的大小
    • 4. 数组的元素个数
  • 四、拓展应用
    • 1. 对结构体数组进行多级排序
    • 2. 对结构体数组进行逆序排序
    • 3. 对结构体数组进行部分排序
    • 4. 对结构体数组进行自定义排序
  • 五、总结


前言

在C语言的世界里,qsort 函数是一个非常强大且灵活的工具,它允许我们对任意类型的数组进行快速排序。这种特性使得 qsort 在处理复杂数据排序时变得非常方便。今天,我们就通过一个简单的程序来深入探讨 qsort 的使用,以及它在C语言中的重要性。


题目引入

下面程序的输出结果是:( )

#include <stdio.h>
#include <stdlib.h>

struct stu
{
    int num;
    char name[10];
    int age;
};

int cmp(const void* a, const void* b)
{
    struct stu* pa = (struct stu*)a;
    struct stu* pb = (struct stu*)b;
    if (pa->age != pb->age) {
        return pa->age - pb->age;
    } else {
        return strcmp(pa->name, pb->name);
    }
}

void print_students(struct stu* students, int size)
{
    for (int i = 0; i < size; i++) {
        printf("Student %d: Num = %d, Name = %s, Age = %d\n", i + 1, students[i].num, students[i].name, students[i].age);
    }
}

int main()
{
    struct stu students[3] = {
        {9801, "zhang", 20},
        {9802, "wang", 19},
        {9803, "zhao", 18}
    };

    printf("Before sorting:\n");
    print_students(students, 3);

    qsort(students, 3, sizeof(struct stu), cmp);

    printf("After sorting:\n");
    print_students(students, 3);

    return 0;
}

A. 按编号排序

B. 按姓名排序

C. 按年龄排序,年龄相同按姓名排序

D. 按年龄排序,年龄相同按编号排序

在接下来的文章中,我们会一起把 qsort 的知识与题目结合起来,学习这一知识点。

一、qsort函数的定义与使用

qsort函数的定义

qsort 函数是C语言标准库 <stdlib.h> 中提供的一个通用排序函数,其原型如下:

void qsort(void* base, size_t nitems, size_t size, int (*compar)(const void*, const void*));
  • base:指向要排序的数组的首地址。
  • nitems:数组中元素的个数。
  • size:数组中每个元素的大小(以字节为单位)。
  • compar:比较函数的指针,用于定义排序的规则。

qsort函数的使用

1. 示例:对整数数组排序

#include <stdio.h>
#include <stdlib.h>

int cmp(const void* a, const void* b)
{
    return (*(int*)a - *(int*)b);
}

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

    printf("Before sorting:\n");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    qsort(arr, n, sizeof(int), cmp);

    printf("After sorting:\n");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}

输出结果:

Before sorting:
5 2 9 1 5 6
After sorting:
1 2 5 5 6 9

2. 示例:对结构体数组排序

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct stu
{
    int num;
    char name[10];
    int age;
};

int cmp(const void* a, const void* b)
{
    struct stu* pa = (struct stu*)a;
    struct stu* pb = (struct stu*)b;
    if (pa->age != pb->age) {
        return pa->age - pb->age;
    } else {
        return strcmp(pa->name, pb->name);
    }
}

void print_students(struct stu* students, int size)
{
    for (int i = 0; i < size; i++) {
        printf("Student %d: Num = %d, Name = %s, Age = %d\n", i + 1, students[i].num, students[i].name, students[i].age);
    }
}

int main()
{
    struct stu students[3] = {
        {9801, "zhang", 20},
        {9802, "wang", 19},
        {9803, "zhao", 18}
    };

    printf("Before sorting:\n");
    print_students(students, 3);

    qsort(students, 3, sizeof(struct stu), cmp);

    printf("After sorting:\n");
    print_students(students, 3);

    return 0;
}

输出结果:

Before sorting:
Student 1: Num = 9801, Name = zhang, Age = 20
Student 2: Num = 9802, Name = wang, Age = 19
Student 3: Num = 9803, Name = zhao, Age = 18
After sorting:
Student 1: Num = 9803, Name = zhao, Age = 18
Student 2: Num = 9802, Name = wang, Age = 19
Student 3: Num = 9801, Name = zhang, Age = 20

二、知识点分析

1. qsort函数的参数

base参数

base 参数是指向要排序的数组的首地址。在C语言中,数组名本身就是一个指向数组首元素的指针,因此可以直接将数组名传递给 base 参数。

nitems参数

nitems 参数表示数组中元素的个数。可以通过 sizeof(arr) / sizeof(arr[0]) 来计算数组中元素的个数。

size参数

size 参数表示数组中每个元素的大小(以字节为单位)。对于基本数据类型(如 intfloat 等),可以直接使用 sizeof 运算符来获取其大小。对于结构体类型,也可以使用 sizeof 运算符来获取其大小。

compar参数

compar 参数是一个比较函数的指针,用于定义排序的规则。比较函数的原型如下:

int cmp(const void* a, const void* b);
  • 如果第一个参数小于第二个参数,返回负数。
  • 如果第一个参数等于第二个参数,返回零。
  • 如果第一个参数大于第二个参数,返回正数。

2. 比较函数的编写

比较函数是 qsort 函数的核心部分,它决定了排序的规则。比较函数的编写需要根据具体的需求来实现。以下是一些常见的比较函数的编写方法:

对整数数组排序

int cmp(const void* a, const void* b)
{
    return (*(int*)a - *(int*)b);
}

对浮点数数组排序

int cmp(const void* a, const void* b)
{
    if (*(float*)a < *(float*)b) {
        return -1;
    } else if (*(float*)a > *(float*)b) {
        return 1;
    } else {
        return 0;
    }
}

对字符串数组排序

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

对结构体数组排序

int cmp(const void* a, const void* b)
{
    struct stu* pa = (struct stu*)a;
    struct stu* pb = (struct stu*)b;
    if (pa->age != pb->age) {
        return pa->age - pb->age;
    } else {
        return strcmp(pa->name, pb->name);
    }
}

3. qsort函数的工作原理

qsort 函数是一种快速排序算法的实现。快速排序的基本思想是:选择一个基准值(pivot),将数组分为两部分,左边的部分都小于基准值,右边的部分都大于基准值,然后递归地对左右两部分进行排序。

qsort 函数的工作原理如下:

  1. 选择一个基准值(pivot)。
  2. 将数组分为两部分,左边的部分都小于基准值,右边的部分都大于基准值。
  3. 递归地对左右两部分进行排序。

三、注意事项

1. 比较函数的返回值

比较函数的返回值必须符合以下规则:

  • 如果第一个参数小于第二个参数,返回负数。
  • 如果第一个参数等于第二个参数,返回零。
  • 如果第一个参数大于第二个参数,返回正数。

如果返回值不符合上述规则,可能会导致排序结果不正确。

2. 比较函数的参数类型

比较函数的参数类型是 const void*,表示指向任意类型的指针。在比较函数中,需要将 const void* 类型的参数强制转换为具体的类型指针,然后进行比较。

3. 数组的大小

在调用 qsort 函数时,需要正确计算数组的大小。对于基本数据类型(如 intfloat 等),可以直接使用 sizeof 运算符来获取其大小。对于结构体类型,也可以使用 sizeof 运算符来获取其大小。

4. 数组的元素个数

在调用 qsort 函数时,需要正确计算数组的元素个数。可以通过 sizeof(arr) / sizeof(arr[0]) 来计算数组中元素的个数。

四、拓展应用

1. 对结构体数组进行多级排序

在实际应用中,我们可能需要对结构体数组进行多级排序。例如,先按年龄排序,如果年龄相同,则按姓名排序。以下是一个示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct stu
{
    int num;
    char name[10];
    int age;
};

int cmp(const void* a, const void* b)
{
    struct stu* pa = (struct stu*)a;
    struct stu* pb = (struct stu*)b;
    if (pa->age != pb->age) {
        return pa->age - pb->age;
    } else {
        return strcmp(pa->name, pb->name);
    }
}

void print_students(struct stu* students, int size)
{
    for (int i = 0; i < size; i++) {
        printf("Student %d: Num = %d, Name = %s, Age = %d\n", i + 1, students[i].num, students[i].name, students[i].age);
    }
}

int main()
{
    struct stu students[3] = {
        {9801, "zhang", 20},
        {9802, "wang", 19},
        {9803, "zhao", 18}
    };

    printf("Before sorting:\n");
    print_students(students, 3);

    qsort(students, 3, sizeof(struct stu), cmp);

    printf("After sorting:\n");
    print_students(students, 3);

    return 0;
}

2. 对结构体数组进行逆序排序

在实际应用中,我们可能需要对结构体数组进行逆序排序。以下是一个示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct stu
{
    int num;
    char name[10];
    int age;
};

int cmp(const void* a, const void* b)
{
    struct stu* pa = (struct stu*)a;
    struct stu* pb = (struct stu*)b;
    if (pa->age != pb->age) {
        return pb->age - pa->age;
    } else {
        return strcmp(pb->name, pa->name);
    }
}

void print_students(struct stu* students, int size)
{
    for (int i = 0; i < size; i++) {
        printf("Student %d: Num = %d, Name = %s, Age = %d\n", i + 1, students[i].num, students[i].name, students[i].age);
    }
}

int main()
{
    struct stu students[3] = {
        {9801, "zhang", 20},
        {9802, "wang", 19},
        {9803, "zhao", 18}
    };

    printf("Before sorting:\n");
    print_students(students, 3);

    qsort(students, 3, sizeof(struct stu), cmp);

    printf("After sorting:\n");
    print_students(students, 3);

    return 0;
}

3. 对结构体数组进行部分排序

在实际应用中,我们可能需要对结构体数组进行部分排序。以下是一个示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct stu
{
    int num;
    char name[10];
    int age;
};

int cmp(const void* a, const void* b)
{
    struct stu* pa = (struct stu*)a;
    struct stu* pb = (struct stu*)b;
    if (pa->age != pb->age) {
        return pa->age - pb->age;
    } else {
        return strcmp(pa->name, pb->name);
    }
}

void print_students(struct stu* students, int size)
{
    for (int i = 0; i < size; i++) {
        printf("Student %d: Num = %d, Name = %s, Age = %d\n", i + 1, students[i].num, students[i].name, students[i].age);
    }
}

int main()
{
    struct stu students[5] = {
        {9801, "zhang", 20},
        {9802, "wang", 19},
        {9803, "zhao", 18},
        {9804, "li", 21},
        {9805, "sun", 22}
    };

    printf("Before sorting:\n");
    print_students(students, 5);

    qsort(students + 1, 3, sizeof(struct stu), cmp);

    printf("After sorting:\n");
    print_students(students, 5);

    return 0;
}

4. 对结构体数组进行自定义排序

在实际应用中,我们可能需要对结构体数组进行自定义排序。以下是一个示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct stu
{
    int num;
    char name[10];
    int age;
};

int cmp(const void* a, const void* b)
{
    struct stu* pa = (struct stu*)a;
    struct stu* pb = (struct stu*)b;
    if (pa->age != pb->age) {
        return pa->age - pb->age;
    } else {
        return strcmp(pa->name, pb->name);
    }
}

void print_students(struct stu* students, int size)
{
    for (int i = 0; i < size; i++) {
        printf("Student %d: Num = %d, Name = %s, Age = %d\n", i + 1, students[i].num, students[i].name, students[i].age);
    }
}

int main()
{
    struct stu students[3] = {
        {9801, "zhang", 20},
        {9802, "wang", 19},
        {9803, "zhao", 18}
    };

    printf("Before sorting:\n");
    print_students(students, 3);

    qsort(students, 3, sizeof(struct stu), cmp);

    printf("After sorting:\n");
    print_students(students, 3);

    return 0;
}

五、总结

qsort 函数是C语言中一个非常重要的概念,它允许我们将多个不同类型的数据组合在一起,形成一个逻辑上的整体。

关注窝,每三天至少更新一篇优质c语言题目详解~

[专栏链接QwQ] :⌈c语言日寄⌋CSDN
[关注博主ava]:siy2333
感谢观看~ 我们下次再见!!


http://www.kler.cn/a/586599.html

相关文章:

  • css模拟雷达扫描动画
  • 用ST7789屏幕导致负片(反色)的问题
  • Alembic 实战指南:快速入门到FastAPI 集成
  • 深入解析对象存储及工作原理
  • Java 综合实战项目:生成不重复随机字符串数组
  • Android LeakCanary 使用 · 原理详解
  • 微信小程序面试内容整理-数据绑定
  • AcWing 4889. 空调II
  • Rust语言的信号量
  • 【STM32】USART串口协议串口外设-学习笔记
  • 【深度解析:以“不要的心态”获取所求的本质逻辑】
  • 反射、反射调用以及修改成员变量,成员方法,构造函数、反射的应用
  • DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加列宽调整功能,示例Table14_11多功能组合的固定表头表格
  • 绿色高效运维:分布式光伏监控系统的全生命周期管理
  • 文件系统 linux ─── 第19课
  • 新手村:统计量均值、中位数、标准差、四分位数
  • 将pdf或者word转换成base64格式
  • 通达信软件+条件选股+code
  • 如何在github上参与开源项目
  • Java基础语法练习43(线程)