[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.rhkb.cn/news/34035.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言每日一练——day_8

引言 针对初学者&#xff0c;每日练习几个题&#xff0c;快速上手C语言。第八天。&#xff08;连续更新中&#xff09; 采用在线OJ的形式 什么是在线OJ&#xff1f; 在线判题系统&#xff08;英语&#xff1a;Online Judge&#xff0c;缩写OJ&#xff09;是一种在编程竞赛中用…

python从邮件中提取链接中的符号为什么会变成amp; 解决办法

在Python中&#xff0c;从邮件中提取链接时&#xff0c;&符号变成&amp;是因为HTML实体编码。HTML使用&amp;表示&&#xff0c;以确保在浏览器中正确显示。 原因 HTML实体编码&#xff1a;&在HTML中有特殊含义&#xff0c;用于表示实体编码的开始。为了避免…

农业电商|基于SprinBoot+vue的农业电商服务系统(源码+数据库+文档)

农业电商服务系统 目录 基于SprinBootvue的农业电商服务系统 一、前言 二、系统设计 三、系统功能设计 5.1系统功能实现 5.2后台模块实现 5.2.1管理员模块实现 5.2.2商家模块实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码…

【JAVA】七、基础知识“if+switch+循环结构”详细讲解~简单易懂!

目录 7、逻辑控制 7.1 分支结构 7.1.1 if 语句 语法格式1 语法格式2 语法格式3 7.1.2 switch语句 基本语法 执行流程 7.2 循环结构 7.2.1 while循环 语法格式 7.2.2 Break 7.2.3 Continue 7.2.4 for循环 语法格式 执行过程 7.2.5 do while循环 语法格式 7.3 …

C# Exe + Web 自动化 (BitComet 绿灯 自动化配置、设置)

BitComet GreenLight,内网黄灯转绿灯 (HighID), 增加p2p连接率提速下载-CSDN博客 前两天写个这个&#xff0c;每次开机关机后要重来一遍很麻烦的索性写个自动化。 先还是按照上面的教程自己制作一遍&#xff0c;留下Luck 以及 路由器相关的 端口记录信息。 &#xff08;因为自…

JumpServer基础功能介绍演示

堡垒机可以让运维人员通过统一的平台对设备进行维护&#xff0c;集中的进行权限的管理&#xff0c;同时也会对每个操作进行记录&#xff0c;方便后期的溯源和审查&#xff0c;JumpServer是由飞致云推出的开源堡垒机&#xff0c;通过简单的安装配置即可投入使用&#xff0c;本文…

sqldef:一款免费的数据库变更管理工具

应用程序的升级通常伴随着数据库表结构的变更&#xff0c;为了维护各种环境的数据库变更&#xff0c;我们通常需要引入 Liquibase 或者 Flyaway 这样的数据库版本控制工具。不过&#xff0c;这类工具通常需要绑定某种编程语言&#xff0c;例如 Java&#xff1b;这次我们介绍一个…

行为模式---状态模式

概念 状态模式是一种行为模式&#xff0c;用于在内部状态改变的时候改变其行为。它的核心思想就是允许一个对象在其内部状态改变的时候改变它的行为。状态模式通过将对象的状态封装成独立的类&#xff0c;并将其行为委托给当前的状态对象&#xff0c;从而使得对象行为随着状态…

1688按图搜索商品(拍立淘)接口的参数说明【附代码实例】

阿里巴巴中国站按图搜索1688商品&#xff08;拍立淘&#xff09; API 返回值说明 item_search_img-按图搜索1688商品&#xff08;拍立淘&#xff09; 1688.item_search_img 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;se…

Linux文件管理练习

1、列出所有账号的账号名 切割显示-cut 作用&#xff1a;cut命令用于按列提取文本内容 格式: cut -d "分隔符" -f列数字 文件名 2、将/etc/passwd中内容按照冒号隔开的第三个字符从大到小排序后输出所有内容 排序显示-sort 作用:sort命令用于对文本内容进行排…

解决PC串流至IPad Pro时由于分辨率不一致导致的黑边问题和鼠标滚轮反转问题

问题背景 今天在做 电脑串流ipad pro 的时候发现了2个问题&#xff1a; 1.ipadpro 接上鼠标后&#xff0c;滚轮上下反转&#xff0c;这个是苹果自己的模拟造成的问题&#xff0c;在设置里选择“触控板与鼠标”。 关闭“自然滚动”,就可以让鼠标滚轮正向滚动。 2. ipadpro 分…

【数据结构初阶第十九节】八大排序系列(下篇)—[详细动态图解+代码解析]

hello&#xff0c;好久不见&#xff01; 云边有个稻草人-CSDN博客 上篇内容&#xff0c;回顾一下吧【数据结构初阶第十八节】八大排序系列(上篇)—[详细动态图解代码解析]-CSDN博客 今天我们来学习下篇 目录 &#xff08;2&#xff09;快速排序 【挖坑法】 —思路 —思路…

使用Open WebUI下载的模型文件(Model)默认存放在哪里?

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Ollama部署LLM专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2025年2月21日21点21分 &#x1f004;️文章质量&#xff1a;95分 文章目录 使用CMD安装存放位置 默认存放路径 Open WebUI下…

XSS漏洞学习(1)

XSS漏洞学习&#xff08;1&#xff09; HTTP协议回顾 HTTP的请求方式 常用 GET 请求从服务器获取资源 HEAD 类似于GET请求&#xff0c;只不过不会返回实体数据&#xff0c;只获取报头 POST 向服务器提交数据 PUT 替换服务器的内容 不常用 DELETE 请求服务器删除指定的…

【统计学相关笔记】抽样基本定理的证明

抽样基本定理的证明 法 1 法 2 什么是 辅助统计量&#xff1f; 法 3

基于Asp.net的物流配送管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

vue-treeselect 【单选/多选】的时候只选择最后一层(绑定的值只绑定最后一层)

欢迎访问我的个人博客 &#xff5c;snows_ls BLOGhttp://snows-l.site 一、单选 1、问题&#xff1a; vue-treeselect 单选的时候只选择最后一层&#xff08;绑定的值只绑定最后一层&#xff09; 2、方法 1、只需要加上 :disable-branch-nodes"true" 就行&#xff0…

Python的那些事第四十五篇:继承自Nose的测试框架Nose2

Nose2:继承自Nose的测试框架 摘要 本文深入探讨了Nose2这一继承自Nose的测试框架。在软件开发过程中,测试是确保代码质量和稳定性的重要环节,而测试框架为测试工作的开展提供了有力支持。Nose2作为Nose的继承者,在保留Nose优势的基础上进行了诸多改进和扩展,为Python测试…

LLM后训练:解锁大型语言模型推理能力的关键路径

引言&#xff1a;从语言生成到逻辑推理的跃迁 大型语言模型&#xff08;LLMs&#xff09;通过预训练掌握了海量语言模式&#xff0c;但其核心缺陷——幻觉、逻辑断裂、价值观偏差——暴露了单纯预训练的局限性。后训练&#xff08;Post-Training&#xff09;作为预训练后的精修…

Rabit

之前发过rabit了&#xff0c;所以这里不再赘述&#xff0c;讲讲原理 在线Rabbit加密 | Rabbit解密- 在线工具 (sojson.com) rabbit加密原理 Rabbit加密算法是一种流密码算法&#xff0c;由Daniel J. Bernstein设计&#xff0c;并被广泛用于多种加密和安全通信应用中。它的设…