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

C语言中qsort函数的详解,以及模拟

引言 

        C语言中qsort函数的详解模拟实现qsort函数,这里为了使用冒泡排序来模拟qsort函数

一、详解qsort函数 

        在 C 语言中,qsort 函数是一个标准库函数,用于对数组进行快速排序(Quick Sort)。它位于 <stdlib.h> 头文件中,具有较高的通用性,可以对不同类型的数组进行排序。

函数原型: 

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

参数说明

  • base:指向要排序的数组的第一个元素的指针。由于它是 void * 类型的指针,所以可以接受任意类型的数组。
  • nmemb:数组中元素的个数,类型为 size_t,通常使用 sizeof 运算符来计算。
  • size:每个元素的大小(以字节为单位),类型为 size_t,同样可以使用 sizeof 运算符来获取。
  • compar:一个指向比较函数的指针,该比较函数用于确定元素的顺序。比较函数需要接受两个 const void * 类型的参数,并返回一个整数值,用于表示两个元素的大小关系。

比较函数: 

int compar(const void *a, const void *b);
  • 参数:a 和 b 是指向要比较的两个元素的指针,类型为 const void *在函数内部需要将其转换为实际的类型。
  • 返回值:
    • 如果 *a 小于 *b,则返回一个负整数。
    • 如果 *a 等于 *b,则返回 0。
    • 如果 *a 大于 *b,则返回一个正整数。

二、qsort函数的使用 

        注意:qsort 函数是 C 语言中一个非常实用的排序工具,通过自定义比较函数,可以对不同类型的数组进行排序。需要注意的是,比较函数的实现要正确,以确保排序结果的正确性。

对整数数组进行排序

#include <stdio.h>
#include <stdlib.h>// 整数比较函数
int int_compare(const void *a, const void *b) {const int *pa = (const int *)a;const int *pb = (const int *)b;return (*pa - *pb);
}int main() {int arr[] = {5, 2, 8, 1, 9};int n = sizeof(arr) / sizeof(arr[0]);// 调用 qsort 函数进行排序qsort(arr, n, sizeof(int), int_compare);// 输出排序后的数组for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");return 0;
}

 对结构体数据进行排序

#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>
struct Stu //学生
{char name[20];//名字int age; //年龄
};int cmp_stu_by_name(const void* e1, const void* e2)
{return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);//先将数据转换成结构体对应的类型,然后比较
}int cmp_stu_by_age(const void* e1, const void* e2)
{return (((struct Stu*)e1)->age - ((struct Stu*)e2)->age);//先将数据转换成结构体对应的类型,然后比较
}
int main()
{struct Stu s[3] = { {"zhangsan", 20},{"lisi", 18}, {"wangwu", 23}};int sz = sizeof(s) / sizeof(s[0]);qsort(s, sz, sizeof(s[0]), cmp_stu_by_name); //对结构体里面的名字按照字典序来比较for (int i = 0; i <= 2; i++){printf("%s ", s[i].name);}printf("\n");qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);//对结构体里面的年龄按照从小到大来排序for (int i = 0; i <= 2; i++){printf("%d ", s[i].age);}return 0;
}

 运行结果:

三、模拟qsort函数 

        这里是在冒泡排序的基础上,改编成qsort函数,可以先看学习一下冒泡排序是什么:

C语言实现冒泡排序,超详解-CSDN博客文章浏览阅读249次,点赞4次,收藏6次。用c语言实现使用冒泡排序 https://blog.csdn.net/2401_88433210/article/details/146212798?spm=1011.2415.3001.10575&sharefrom=mp_manage_link这里只讲一下改编的核心思想:

       1.讲冒泡排序传入的参数设置成和qsort的参数一样

参数说明

  • base:指向要排序的数组的第一个元素的指针。由于它是 void * 类型的指针,所以可以接受任意类型的数组。
  • nmemb:数组中元素的个数,类型为 size_t,通常使用 sizeof 运算符来计算。
  • size:每个元素的大小(以字节为单位),类型为 size_t,同样可以使用 sizeof 运算符来获取。
  • compar:一个指向比较函数的指针,该比较函数用于确定元素的顺序。比较函数需要接受两个 const void * 类型的参数,并返回一个整数值,用于表示两个元素的大小关系。

        2.冒泡排序第二层循环里面的比较函数,使用参数部分传入的参数

        3.交换函数需要重新设计,因为是可以比较任何类型,所以也要交换任何类型的数据

 怎么实现交换任何类型的数据:

        这个问题的解决也非常的简单,众所周知,任何类型在内容中存储的一个单位是字节,只是字节的个数不一样,char类型是一个字节,int类型是4个字节,等等。

        所以可以直接交换数据在内存中的字节,如,int类型,可以交换内存中对应的4个字节。

         纯文字描述可能很难明白,这里得需要你的想像,想像有一排格子,其中四个格子对应一个int类型,借用第三者,依次交换每个格子里面的内容,将交换后的内容再解引用,就实现了数据的交换。

 核心参考代码:

#include <stdio.h>
int int_cmp(const void* p1, const void* p2)
{return (*(int*)p1 - *(int*)p2);
}
void _swap(void* p1, void* p2, int size)
{int i = 0;for (i = 0; i < size; i++){char tmp = *((char*)p1 + i);*((char*)p1 + i) = *((char*)p2 + i);*((char*)p2 + i) = tmp;}
}
void bubble(void* base, int count, int size, int(*cmp)(void*, void*))
{int i = 0;int j = 0;for (i = 0; i < count - 1; i++){for (j = 0; j < count - i - 1; j++){if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0){_swap((char*)base + j * size, (char*)base + (j + 1) * size,size);}}}
}

qsort参考代码:


#include <stdio.h>
int int_cmp(const void* p1, const void* p2)
{return (*(int*)p1 - *(int*)p2);
}
void _swap(void* p1, void* p2, int size)
{int i = 0;for (i = 0; i < size; i++){char tmp = *((char*)p1 + i);*((char*)p1 + i) = *((char*)p2 + i);*((char*)p2 + i) = tmp;}
}
void bubble(void* base, int count, int size, int(*cmp)(void*, void*))
{int i = 0;int j = 0;for (i = 0; i < count - 1; i++){for (j = 0; j < count - i - 1; j++){if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0){_swap((char*)base + j * size, (char*)base + (j + 1) * size,size);}}}
}
int main()
{int arr[] = { 1, 6, 0, 8, 9, 2, 4, 3, 7, 5 };int i = 0;bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){printf("%d ", arr[i]);}printf("\n");return 0;
}

相关文章:

C语言中qsort函数的详解,以及模拟

引言 C语言中qsort函数的详解和模拟实现qsort函数&#xff0c;这里为了使用冒泡排序来模拟qsort函数 一、详解qsort函数 在 C 语言中&#xff0c;qsort 函数是一个标准库函数&#xff0c;用于对数组进行快速排序&#xff08;Quick Sort&#xff09;。它位于 <stdlib.h>…...

9、讲一讲你理解的虚拟内存【中高频】

计算机早期&#xff0c;CPU 是直接操作 物理内存&#xff08;Physical Memory&#xff09;的&#xff0c;但这会导致 内存空间无法完全隔离&#xff0c;一个程序修改了另一个程序的地址空间&#xff0c;就会导致程序崩溃&#xff1b;同时物理内存大小有限&#xff0c;一旦超出这…...

算法刷题整理合集(四)

本篇博客旨在记录自已的算法刷题练习成长&#xff0c;里面注有详细的代码注释以及和个人的思路想法&#xff0c;希望可以给同道之人些许帮助。本人也是算法小白&#xff0c;水平有限&#xff0c;如果文章中有什么错误或遗漏之处&#xff0c;望各位可以在评论区指正出来&#xf…...

高数1.5 极限的运算法则

1. 预备知识 2.四则求极限法则 3.复合运算求极限法则...

【鸿蒙开发】Hi3861学习笔记- 定时器中断

00. 目录 文章目录 00. 目录01. 概述02. 定时器相关API2.1 hi_timer_create2.2 hi_timer_start2.3 hi_timer_stop2.4 hi_timer_delete 03. 硬件设计04. 软件设计05. 实验现象06. 附录 01. 概述 定时器&#xff0c;顾名思义就是用来计时的&#xff0c;我们常常会设定计时或闹钟…...

Spring Cloud Config 快速介绍与实例

Spring Cloud Config 是什么? Spring Cloud Config 是一个用于分布式系统的配置管理工具,提供集中化的外部配置支持。它适用于微服务架构,能够将各个服务的配置集中存储在服务端(如 Git 仓库),客户端按需动态获取配置,解决了配置分散、环境切换复杂等问题。 Spring Cl…...

Power Apps 技术分享:画布应用使用表单控件

前言 表单控件&#xff0c;是画布应用里一个非常好用的控件&#xff0c;我们今天简单介绍下&#xff0c;如何使用这个控件。 正文 1.首先&#xff0c;我们需要有一个数据源&#xff0c;我们这里用上一篇博客新建的数据源&#xff0c;如下图&#xff1a; 2.新建一个页面&#xf…...

【数据库】Data Model(数据模型)数据模型分析

理解图片中的 Data Model&#xff08;数据模型&#xff09;是学习数据库设计和应用程序开发的重要一步。作为初学者&#xff0c;你可以通过比喻和简单的解释来理解这些概念以及它们之间的联系。以下是对图片中数据模型的详细分析&#xff0c;以及如何理解它们之间的关系。 1. 数…...

【Unity】 HTFramework框架(六十二)Agent编辑器通用智能体(AI Agent)

更新日期&#xff1a;2025年3月14日。 Github源码&#xff1a;[点我获取源码] Gitee源码&#xff1a;[点我获取源码] 索引 编辑器通用智能体AIAgent类Friday&#xff08;星期五&#xff09;启用智能体设置智能体类型开放智能体权限智能体交互资源优化批处理运行代码联网搜索休闲…...

Elasticsearch 滚动索引(Rollover Index)详解

文章目录 1、滚动索引的作用2、滚动索引的用法2.1 核心概念2.2 实现步骤 3、适用场景4、与其他技术的结合使用5、案例&#xff1a;日志数据的滚动索引5.1 场景描述5.2 实现步骤 6、示例&#xff1a;结合索引生命周期管理&#xff08;ILM&#xff09;6.1 场景描述6.2 实现步骤 7…...

学习笔记:黑马程序员JavaWeb开发教程(2025.3.17)

11.5 案例-文件上传-阿里云OSS-入门 出现报错&#xff1a;Process exited with an error: 1 (Exit value: 1)&#xff0c;点击exec那一行&#xff0c;出现错误原因&#xff1a;Command execution failed. 在CSDN上找到了解决方法&#xff1a; 之后出现新的报错&…...

python局部变量和全局变量

文章目录 1.局部变量和全局变量2.局部变量2.1 局部变量的作用2.2 局部变量的生命周期 3. 全局变量3.1 函数不能直接修改全局变量的引用3.2 在函数内部修改全局变量的值3.3 全局变量定义的位置3.4 全局变量命名的建议 1.局部变量和全局变量 &#xff08;1&#xff09;局部变量 …...

攻克 3D 模型网站建设难题,看迪威系统优势

在当今数字化时代&#xff0c;3D 模型广泛应用于建筑设计、游戏开发、工业制造、文化创意等诸多领域。拥有一个功能强大的 3D 模型网站&#xff0c;对于企业展示产品、设计师分享作品、教育机构开展教学等都具有重要意义。然而&#xff0c;构建这样一个网站却并非易事&#xff…...

仿最美博客POETIZE(简易版)

写在前面 本文章参考于两个开源项目分别为&#xff1a;POETIZE-最美博客&#xff0c;拾壹博客 如有侵权&#xff0c;请联系删除 正题 此页面为拾壹博客修改而成&#xff0c;采用了POETIZE的布局以及背景图片&#xff0c;技术栈:SpringbootVue&#xff0c;主要涉及页面为网站…...

vue/H5的日历组件可简单定制

在components创建riliZujian.vue <template><div class"max_box"><!-- 日历 文字 --><div class"month"><div click"lastMonth" class"monthText13">上月</div><div class"monthText2&q…...

STM32——独立看门狗(IWDG)

IWDG 简介 独立看门狗本质上是一个 定时器 &#xff0c;这个定时器有一个输出端&#xff0c;可以输出复位信号。该定时器是一个 12 位的递减计数器 &#xff0c;当计数器的值减到 0 的时候&#xff0c;就会产生一个复位信号。如果 在计 数没减到 0 之前&#xff0c;重置计…...

C++11智能指针简述

一、实现原理 在智能指针对象中有一个裸指针&#xff0c;此指针存储的是动态创建对象的地址&#xff0c;用于生存期控制&#xff0c;能够确保智能指针对象离开所在作用域时&#xff0c;自动正确地销毁动态创建的对象&#xff0c;防止内存泄漏。 使用裸指针存在的问题&#xff…...

fastpdf应用程序错误0xc0000142

原因&#xff1a;一般是部分DLL文件未能被系统注册或者丢失&#xff0c;导致动态库调用错误造成的。 解决方法&#xff1a;将DLL文件重新注册一遍。 手动复制&#xff1a;1.按下“winr”打开运行&#xff0c;在运行框中输入“cmd”&#xff0c;再点击确定&#xff1b; 2.在命…...

Linux操作系统实验报告单(3)文本编辑器vi/vim

一、实验目的 掌握vi/vim编辑器的进入和退出方式了解vi/vim的三种模式熟练vi/vim的操作命令 二、实验内容 1.在家目录下新建一个名为“vitest_name”&#xff08;“name”为学生姓名拼音&#xff09;的目录。 ●创建用户目录命令&#xff1a;sudo mkdir /home/vitest_lw3613 …...

linux(centos8)下编译ffmpeg

必要依赖 # centos8有些找不到依赖包&#xff0c;需要手动下载源码编译 sudo dnf install -y epel-release sudo dnf install -y git gcc gcc-c make nasm yasm \libtool autoconf automake cmake \bzip2 bzip2-devel zlib-devel \xz xz-devel x264-devel x265-devel \openssl…...

Centos固定IP配置

虚拟机安装 安装vmware 网盘链接 安装centos7.5 网盘链接 安装教程自行查找 固定IP配置 对安装好的VMware进行网络配置&#xff0c;方便虚拟机连接网络&#xff0c;本次设置建议选择NAT模式&#xff0c;需要宿主机的Windows和虚拟机的Linux能够进行网络连接&#xff0c;…...

AI自动获客系统源码

一、AI自动获客的显著优势 在当今商业环境中&#xff0c;AI自动获客技术正逐渐成为企业获客的新宠。相较于传统的获客方式&#xff0c;它展现出诸多显著优势。首先&#xff0c;AI技术能够通过智能分析和精准匹配&#xff0c;快速找到潜在客户&#xff0c;从而大大提高获客效率…...

3.17[Q]CV Bézier curve

我是计算机视觉学生&#xff0c;&#xff1f;详细解释&#xff0c;越细节越好 我是计算机视觉学生&#xff0c;如何使用de Casteljau 算法来绘制由 4 个控制点表示的 Bzier 曲线&#xff1f;原理是什么&#xff1f;工作流程是什么&#xff1f;详细解释&#xff0c;越细节越好…...

K8S学习之基础三十一:k8s中RBAC 的核心概念

Kubernetes (k8s) 中的 RBAC&#xff08;Role-Based Access Control&#xff0c;基于角色的访问控制&#xff09;是一种用于管理用户和服务账户对集群资源访问权限的机制。RBAC 允许管理员通过定义角色&#xff08;Role&#xff09;和角色绑定&#xff08;RoleBinding&#xff…...

二叉树算法题实战:从遍历到子树判断

目录 一、引言 二、判断两棵二叉树是否相同 思路 代码实现 注意点 三、二叉树的中序遍历 思路 代码实现 注意点 四、判断一棵树是否为另一棵树的子树 思路 代码实现 注意点 ​编辑 五、补充 一、引言 作者主页&#xff1a;共享家9527-CSDN博客 作者代码仓库&am…...

第8章 信息安全工程(一)

8.1 信息安全管理 8.1.1 保障要求 网络与信息安全保障体系中的安全管理建设&#xff0c;通常需要满足以下 5 项原则&#xff1a; (1)网络与信息安全管理要做到总体策划&#xff0c;确保安全的总体目标和所遵循的原则。 (2)建立相关组织机构&#xff0c;要明确责任部门&…...

学习threejs,使用MeshFaceMaterial面材质容器

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.MeshFaceMaterial 二…...

Git 实战指南:本地客户端连接 Gitee 全流程

本文将以 Gitee(码云)、系统Windows 11 为例,详细介绍从本地仓库初始化到远程协作的全流程操作 目录 1. 前期准备1.1 注册与配置 Gitee1.2 下载、安装、配置客户端1.3 配置公钥到 Gitee2. 本地仓库操作(PowerShell/Git Bash)2.1 初始化本地仓库2.2 关联 Gitee 远程仓库3. …...

Spring Cloud 中的服务注册与发现: Eureka详解

1. 背景 1.1 问题描述 我们如果通过 RestTamplate 进行远程调用时&#xff0c;URL 是写死的&#xff0c;例如&#xff1a; String url "http://127.0.0.1:9090/product/" orderInfo.getProductId(); 当机器更换或者新增机器时&#xff0c;这个 URL 就需要相应地变…...

通过 SVG 使用 AI 生成理想图片:技术实现与实践指南

文章目录 1. SVG 与 AI 的结合&#xff1a;技术价值2. 技术原理&#xff1a;AI 如何生成 SVG&#xff1f;3. 实现步骤&#xff1a;从需求到图形3.1 定义需求3.2 使用 AI 生成 SVG3.3 验证与调整 4. 代码解析&#xff1a;实现科技感的关键4.1 渐变背景4.2 网格线条4.3 发光六边形…...