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

qsort函数深度解析:如何自定义比较函数?

文章目录qsort函数深度解析如何自定义比较函数什么是qsort函数自定义比较函数的重要性基本示例排序整数数组排序字符串数组排序结构体数组️多条件排序降序排序和其他顺序可视化qsort的执行流程注意事项和最佳实践⚠️外部资源链接结论qsort函数深度解析如何自定义比较函数在C语言的标准库中qsort函数是一个非常强大且常用的工具用于对数组进行快速排序。它高效、灵活并且通过自定义比较函数可以适应各种数据类型和排序需求。在本篇博客中我将深入解析qsort函数特别是如何自定义比较函数来扩展其功能。通过代码示例、可视化图表和外部资源链接帮助你掌握这一重要主题。让我们开始吧什么是qsort函数qsort是C标准库stdlib.h中提供的快速排序实现。它的原型如下voidqsort(void*base,size_tnmemb,size_tsize,int(*compar)(constvoid*,constvoid*));参数说明base指向待排序数组的指针。nmemb数组中元素的数量。size每个元素的大小以字节为单位。compar比较函数的指针用于定义排序顺序。qsort使用快速排序算法平均时间复杂度为O(n log n)是一种高效的通用排序方法。它的核心在于通过compar函数来实现自定义排序逻辑这使得它可以排序任何类型的数据。自定义比较函数的重要性默认情况下qsort不知道如何比较非基本类型如结构体或特殊顺序如降序。自定义比较函数允许你定义排序顺序升序、降序或其他。处理复杂数据类型例如按结构体的某个字段排序。实现多条件排序例如先按年龄排序再按姓名排序。比较函数的签名必须是intcompar(constvoid*a,constvoid*b);它应返回负数如果a应排在b之前。零如果a和b相等。正数如果a应排在b之后。基本示例排序整数数组让我们从一个简单的例子开始排序一个整数数组升序。#includestdio.h#includestdlib.h// 比较函数 for integers (ascending order)intcompare_int(constvoid*a,constvoid*b){intint_a*((int*)a);intint_b*((int*)b);if(int_aint_b)return-1;if(int_aint_b)return1;return0;}intmain(){intarr[]{5,2,8,1,9};intnsizeof(arr)/sizeof(arr[0]);qsort(arr,n,sizeof(int),compare_int);printf(Sorted array: );for(inti0;in;i){printf(%d ,arr[i]);}printf(\n);return0;}输出Sorted array: 1 2 5 8 9在这个例子中compare_int函数将void指针转换为int指针然后解引用获取整数值并进行比较。返回-1、0或1来指示顺序。排序字符串数组qsort也可以用于排序字符串数组按字典序。#includestdio.h#includestdlib.h#includestring.h// 比较函数 for strings (using strcmp)intcompare_string(constvoid*a,constvoid*b){returnstrcmp(*(constchar**)a,*(constchar**)b);}intmain(){constchar*arr[]{banana,apple,cherry,date};intnsizeof(arr)/sizeof(arr[0]);qsort(arr,n,sizeof(constchar*),compare_string);printf(Sorted array: );for(inti0;in;i){printf(%s ,arr[i]);}printf(\n);return0;}输出Sorted array: apple banana cherry date这里compare_string使用strcmp函数来自string.h来比较字符串。注意由于数组元素是const char*类型我们需要将a和b转换为const char**然后解引用。排序结构体数组️对于更复杂的数据类型如结构体自定义比较函数非常有用。假设我们有一个Person结构体包含姓名和年龄我们想按年龄升序排序。#includestdio.h#includestdlib.h#includestring.htypedefstruct{charname[50];intage;}Person;// 比较函数 for Person by age (ascending)intcompare_person_by_age(constvoid*a,constvoid*b){Person*person_a(Person*)a;Person*person_b(Person*)b;returnperson_a-age-person_b-age;}intmain(){Person people[]{{Alice,30},{Bob,25},{Charlie,35}};intnsizeof(people)/sizeof(people[0]);qsort(people,n,sizeof(Person),compare_person_by_age);printf(Sorted by age:\n);for(inti0;in;i){printf(%s: %d\n,people[i].name,people[i].age);}return0;}输出Sorted by age: Bob: 25 Alice: 30 Charlie: 35在这个例子中我们直接比较age字段。返回person_a-age - person_b-age是一种简写如果结果为负a排在前面正数b排在前面零相等。多条件排序有时我们需要按多个条件排序。例如先按年龄升序如果年龄相同再按姓名升序。// 比较函数 for Person: first by age, then by nameintcompare_person_multiple(constvoid*a,constvoid*b){Person*person_a(Person*)a;Person*person_b(Person*)b;// First compare by ageintage_diffperson_a-age-person_b-age;if(age_diff!0){returnage_diff;}// If ages are equal, compare by name (using strcmp)returnstrcmp(person_a-name,person_b-name);}在main中使用这个函数调用qsort输出将按年龄和姓名排序。降序排序和其他顺序要实现降序排序只需反转比较逻辑。例如对整数降序intcompare_int_desc(constvoid*a,constvoid*b){intint_a*((int*)a);intint_b*((int*)b);if(int_aint_b)return-1;// Reverse the comparisonif(int_aint_b)return1;return0;}或者更简洁地intcompare_int_desc(constvoid*a,constvoid*b){return(*(int*)b-*(int*)a);// Note: b first to reverse order}可视化qsort的执行流程为了更直观地理解qsort如何工作下面是一个Mermaid流程图展示了排序过程以整数数组为例渲染错误:Mermaid 渲染失败: Parse error on line 5: ...-- Yes -- E[Return (base case)] D - -----------------------^ Expecting SQE, DOUBLECIRCLEEND, PE, -), STADIUMEND, SUBROUTINEEND, PIPE, CYLINDEREND, DIAMOND_STOP, TAGEND, TRAPEND, INVTRAPEND, UNICODE_TEXT, TEXT, TAGSTART, got PS这个流程图简化了快速排序的步骤选择基准、分区、递归排序子数组。自定义比较函数在分区和比较时被调用。注意事项和最佳实践⚠️类型安全在比较函数中确保正确转换void指针。错误转换可能导致未定义行为。稳定性qsort不是稳定排序即相等元素的顺序可能改变。如果需要稳定性考虑其他方法或使用额外数据。性能对于大数据集qsort高效但最坏情况时间复杂度为O(n²)。如果需要保证性能可能需选择其他算法。测试 always test your comparison function with edge cases, such as empty arrays, duplicate values, and extreme values.外部资源链接为了进一步学习这里有一些有用的资源CPlusPlus.com qsort reference - 详细的函数说明和示例。GeeksforGeeks on qsort - 包含多种代码示例。Stack Overflow讨论 on custom comparisons - 社区问答解决常见问题。这些资源提供了额外的示例和解释帮助你深入理解。结论qsort是C语言中一个强大的排序工具通过自定义比较函数你可以灵活地排序各种数据类型和顺序。记住关键点比较函数必须返回int并接受两个const void*参数。正确转换指针类型以避免错误。利用多条件排序处理复杂需求。实践这些示例尝试修改代码并探索更多排序场景。Happy coding!

相关文章:

qsort函数深度解析:如何自定义比较函数?

文章目录qsort函数深度解析:如何自定义比较函数?🚀什么是qsort函数?🤔自定义比较函数的重要性🎯基本示例:排序整数数组🔢排序字符串数组📝排序结构体数组🏗️…...

C语言中的泛型尝试:void_ + 函数指针

文章目录C语言中的泛型尝试:void* 函数指针 🧪什么是泛型?🤔C语言中的工具:void* 和函数指针 🛠️代码示例:泛型排序函数 📝进阶示例:泛型链表 📚优缺点分析…...

服务器Docker容器使用

0.基础指令 # 查看容器 docker ps docker images1.删除旧容器 docker rm -f novnc-test 2>/dev/null2.删除旧镜像 docker rmi ubuntu-novnc-vnc:22.04 2>/dev/null3.确认删除情况 docker ps -a | grep novnc-test docker images | grep ubuntu-novnc-vnc4.重新加载镜像 c…...

使用开源 Authentik 实现 AWS 单点登录

前言 懒得自己编了, Gemini 这样介绍 Authentik: 简单来说,Authentik 是一款功能极其强大的开源身份验证与访问管理 (IAM) 解决方案。 如果你觉得像 Okta 或 Auth0 这种商业服务太贵,或者觉得像 Keycloak 这种传统方案配置起来太头疼,那么…...

袁永福 电子病历,医疗信息化际

在AI辅助开发的语境下,Skill就是一个包含了领域知识、最佳实践、代码模板的知识包。 以"DAO层CRUD生成"为例,一个Skill包含: /mnt/skills/dao-crud/ ├── SKILL.md # 使用说明 │ ├── 何时使用这个Skill │ …...

算法优化中的多线程数据一致性问题的技术9

多线程数据一致性问题概述多线程环境下,数据一致性是算法优化中常见的技术挑战。多个线程同时访问和修改共享数据可能导致竞态条件、脏读或不可重复读等问题。确保数据一致性对算法正确性和性能至关重要。常见数据一致性问题类型竞态条件(Race Condition…...

BM25(Best Matching 25)信息检索

文章目录一、BM25本质在做什么二、核心思想(直观理解)1️⃣ 词出现次数(Term Frequency, TF)2️⃣ 词的稀有程度(IDF)3️⃣ 文档长度归一化三、BM25公式(核心)这是标准BM25打分函数&…...

AI 编程盛行的时代,为什么 “『DC- WFW』” 仍然具有必要性?沼

这&#xff0c;是一个采用C精灵库编写的程序&#xff0c;它画了一幅漂亮的图形&#xff1a; 复制代码 #include "sprites.h" //包含C精灵库 Sprite turtle; //建立角色叫turtle void draw(int d){for(int i0;i<5;i)turtle.fd(d).left(72); } int main(){ …...

算法的能耗模型与绿色计算优化方向的技术4

能耗模型基础理论算法复杂度与能耗关系时间复杂度与空间复杂度对硬件资源消耗的影响&#xff0c;建立数学模型描述指令执行次数、数据访问频率与能耗的关联。硬件层面的能耗因素CPU动态功耗&#xff08;CVf&#xff09;、静态功耗、内存访问能耗、缓存命中率等关键参数&#xf…...

3步解决浏览器Markdown阅读难题:从乱码到专业渲染的蜕变之路

3步解决浏览器Markdown阅读难题&#xff1a;从乱码到专业渲染的蜕变之路 【免费下载链接】markdown-viewer Markdown Viewer / Browser Extension 项目地址: https://gitcode.com/gh_mirrors/ma/markdown-viewer 你是否遇到过这样的窘境&#xff1a;在浏览器中打开本地M…...

Docker 容器中运行 AI CLI 工具:用户隔离与持久化卷实战指南暗

环境安装 pip install keystone-engine capstone unicorn 这3个工具用法极其简单&#xff0c;下面通过示例来演示其用法。 Keystone 示例 from keystone import * CODE b"INC ECX; ADD EDX, ECX" try:ks Ks(KS_ARCH_X86, KS_MODE_64)encoding, count ks.asm(CODE)…...

电子电路中的“心脏”:电源铝

前言 Kubernetes 本身并不复杂&#xff0c;是我们把它搞复杂的。无论是刻意为之还是那种虽然出于好意却将优雅的原语堆砌成 鲁布戈德堡机械 的狂热。平台最初提供的 ReplicaSets、Services、ConfigMaps&#xff0c;这些基础组件简单直接&#xff0c;甚至显得有些枯燥。但后来我…...

如何永久保存微信聊天记录:WeChatMsg本地数据备份完整指南

如何永久保存微信聊天记录&#xff1a;WeChatMsg本地数据备份完整指南 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/W…...

第十五节:启动序列——从 claude 命令到 REPL 就绪

知识图谱定位:前面两节我们分别拆解了终端 UI(第13节 React Ink)和命令系统(第14节 斜杠路由)——它们都假设一个前提:REPL 已经就绪。但从用户在终端敲下 claude 按回车,到他看到交互界面,这中间到底发生了什么?答案是一个精心设计的三阶段启动序列:cli.tsx::main()…...

贾子科学的历史意义与现实影响:挑战西方科学哲学霸权的新范式

贾子科学的历史意义与现实影响&#xff1a;挑战西方科学哲学霸权的新范式摘要&#xff1a; 贾子科学是贾龙栋于2025-2026年提出的原创科学哲学体系&#xff0c;其历史意义在于直接挑战以波普尔证伪主义为核心的西方科学划界标准&#xff0c;提出“公理驱动可结构化”新标尺&…...

Vitest单元测试教程

Vitest 是 Vite 生态的极速单元测试框架&#xff0c;API 兼容 Jest&#xff0c;上手快、配置简单、性能极高。下面从 安装 → 配置 → 编写测试 → 常用断言 → Mock → 组件测试 → 运行与覆盖率 完整流程带你上手。一、安装 1. 基础安装 npm i -D vitest # 或 yarn add -D vi…...

Jenkins 学习总结腋

先唠两句&#xff1a;参数就像餐厅点单 把API想象成一家餐厅的“后厨系统”。 ? 路径参数/dishes/{dish_id} -> 好比你要点“宫保鸡丁”这道具体的菜&#xff0c;它是菜单&#xff08;资源路径&#xff09;的一部分。查询参数/dishes?spicytrue&typeSichuan -> 好比…...

2025届学术党必备的十大AI科研平台横评

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 人工智能本领在学术写作范畴的运用越来越普遍&#xff0c;它的关键价值是协助科研者达成文献…...

ARM 架构 JuiceFS 性能优化:基于 MLPerf 的实践与调优死

Qt是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本笔记将重点介绍QSpinBox数值微调组件的常用方法及灵活应用。…...

OpenClaw 太难装了?试试 LangTARS:一行命令部署 + WebUI 管理面板,还能接入 Dify/Coze/nn??悠

1. 什么是 Apache SeaTunnel&#xff1f; Apache SeaTunnel 是一个非常易于使用、高性能、支持实时流式和离线批处理的海量数据集成平台。它的目标是解决常见的数据集成问题&#xff0c;如数据源多样性、同步场景复杂性以及资源消耗高的问题。 核心特性 丰富的数据源支持&#…...

PHP AI校验配置被低估的致命细节(内存泄漏触发点、AST解析偏差、Token限流阈值)——资深SRE连夜重写配置手册

第一章&#xff1a;PHP AI校验配置的全局认知与风险图谱PHP AI校验配置并非孤立的技术模块&#xff0c;而是横跨应用层、中间件、模型服务与基础设施的复合型安全控制面。其核心目标是在AI能力注入业务流程的同时&#xff0c;确保输入合法性、输出可控性、行为可审计及策略可收…...

嵌入式进阶——MCU启动与代码执行教程

MCU启动与代码执行教程 1. 简介 本教程旨在帮助理解&#xff0c;深入剖析ARM Cortex-M系列单片机上电后的完整启动流程&#xff0c;以及程序在Flash、RAM、寄存器三者的协同执行机制。基于STM32等典型MCU&#xff0c;从硬件复位瞬间开始&#xff0c;逐步讲解向量表加载、Reset_…...

学Simulink——基于Simulink的坡道起步防溜坡电机转矩控制

目录 手把手教你学Simulink ——基于Simulink的坡道起步防溜坡电机转矩控制 一、问题背景 二、系统架构与控制逻辑 1. 控制层级 2. 防溜坡转矩需求 三、无传感器坡度估计方法 方法:基于加速度计 + 车速微分 Simulink 实现 四、防溜坡转矩控制器设计 1. 基础转矩规划…...

基于yolov8和faster-rcnn的电动车戴头盔检测,界面可选择模型,支持图像、视频和摄像实时检测【pytorch框架、python源码】

更多目标检测、图像分类识别、目标追踪、图像分割、图像检索等项目可看我主页其他文章 功能演示&#xff08;看shi pin 下面的简介&#xff09;&#xff1a; https://www.bilibili.com/video/BV1DWXrBaE3Z/?spm_id_from333.1387.homepage.video_card.click&vd_source23c…...

打卡信奥刷题(3078)用C++实现信奥题 P7033 [NWRRC 2016] CodeCoder vs TopForces

P7033 [NWRRC 2016] CodeCoder vs TopForces 题目描述 在 Byteland&#xff0c;竞赛编程非常流行。事实上&#xff0c;每位 Byteland 的公民都在两个编程网站——CodeCoder 和 TopForces 上注册。每个网站都有自己专有的评分系统。每位公民在每个网站上都有一个唯一的整数评分&…...

打卡信奥刷题(3077)用C++实现信奥题 P7023 [NWRRC 2017] Equal Numbers

P7023 [NWRRC 2017] Equal Numbers 题目描述 给定一个包含 nnn 个整数 a1,…,ana_{1}, \ldots, a_{n}a1​,…,an​ 的列表。你可以执行以下操作&#xff1a;选择某个 aia_{i}ai​ 并将其乘以任意正整数。 你的任务是计算在进行 kkk 次操作后列表中可能出现的不同整数的最小数…...

法国Hornetsecurity联合里尔大学:如何让人工智能学会保护隐私

这项由法国Hornetsecurity公司与里尔大学、法国国家信息与自动化研究院(Inria)、法国国家科学研究中心(CNRS)以及里尔中央理工学院联合开展的研究&#xff0c;发表于2026年3月31日的计算机科学期刊&#xff0c;论文编号为arXiv:2603.29497v1。有兴趣深入了解的读者可以通过这个…...

SAP MM | 物料主数据:为什么修改了“特殊采购类型”但在 MM04 查不到修改历史?

在 SAP 物料主数据&#xff08;Material Master&#xff09;的操作中&#xff0c;用户有时会修改 “特殊采购类型”&#xff08;SOBSL&#xff09;&#xff0c;比如从“厂内生产”改为“从其他工厂调拨&#xff08;40&#xff09;”。但用户说&#xff0c;修改了主数据之后&…...

容器化网络与Kubernetes网络深度解析

一、Docker网络基础 Docker四大网络驱动 Driver 1: Bridge (默认) ┌────────────────────────────────┐ │ Docker主机 │ │ │ │ ┌─────────────┐ ┌──────────┐ │ │ │ Container A │ │ Bridge │ │ │…...

Shell流程控制(if-else、循环,实现复杂逻辑)

在Linux/Unix系统中&#xff0c;Shell脚本是自动化运维、批量处理任务的核心工具&#xff0c;而流程控制则是让脚本“摆脱线性执行”、实现灵活逻辑的关键。无论是简单的条件判断&#xff08;如“文件是否存在”&#xff09;&#xff0c;还是复杂的批量操作&#xff08;如“遍历…...