Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >[C语言日寄] qsort函数的练习

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

作者头像
siy2333
发布于 2025-03-16 12:28:44
发布于 2025-03-16 12:28:44
5500
代码可运行
举报
文章被收录于专栏:来自csdn的博客来自csdn的博客
运行总次数:0
代码可运行

前言

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


题目引入

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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> 中提供的一个通用排序函数,其原型如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void qsort(void* base, size_t nitems, size_t size, int (*compar)(const void*, const void*));
  • base:指向要排序的数组的首地址。
  • nitems:数组中元素的个数。
  • size:数组中每个元素的大小(以字节为单位)。
  • compar:比较函数的指针,用于定义排序的规则。

qsort函数的使用

1. 示例:对整数数组排序
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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;
}

输出结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Before sorting:
5 2 9 1 5 6
After sorting:
1 2 5 5 6 9
2. 示例:对结构体数组排序
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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;
}

输出结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 参数是一个比较函数的指针,用于定义排序的规则。比较函数的原型如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int cmp(const void* a, const void* b);
  • 如果第一个参数小于第二个参数,返回负数。
  • 如果第一个参数等于第二个参数,返回零。
  • 如果第一个参数大于第二个参数,返回正数。

2. 比较函数的编写

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

对整数数组排序
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int cmp(const void* a, const void* b)
{
    return (*(int*)a - *(int*)b);
}
对浮点数数组排序
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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;
    }
}
对字符串数组排序
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int cmp(const void* a, const void* b)
{
    return strcmp(*(char**)a, *(char**)b);
}
对结构体数组排序
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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. 对结构体数组进行多级排序

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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. 对结构体数组进行逆序排序

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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. 对结构体数组进行部分排序

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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. 对结构体数组进行自定义排序

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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语言题目详解~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-03-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验