第六节——从深层剖析qsort的使用(让你不再害怕指针)

在这里插入图片描述

文章目录

  • 1.什么是回调函数
  • 2.qsort的使用
    • qsort排序整形数据
    • qsort排序结构体数据
    • qsort排序字符串数据
  • 3.qsort的模拟实现


1.什么是回调函数

回调函数就是⼀个通过函数指针调用的函数。

如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数。回调函数不是由该函数的实现⽅直接调用,而是在特定的事件或条
件发生时由另外的⼀方调用的,用于对该事件或条件进行响应。

看完后,也许不是很通透,下面用这个代码简单解释下:
在这里插入图片描述

回顾上节使用的转移表,我们发现用switch来实现过于冗余,而明白了回调函数的原理后能大大简化代码。

在这里插入图片描述

可参考这篇文章:第五节——转移表(让你不再害怕指针)


2.qsort的使用

前言:冒泡排序内容

学完冒泡排序后,我们发现只能排序整形数据,那么要排字符数据,结构数据等等时,又是否能交给冒泡排序解决呢?
很明显,冒泡排序并不能完美地比较这些数据。那么,有没有一个函数能够实现这些数据的排序呢?

答案是肯定的,通过使用qsort可以实现任何类型的排序。

C++最权威官方网站

在这里插入图片描述
在这里插入图片描述

上面两段的含义
在这里插入图片描述


qsort排序整形数据

了解完qsort的思想及使用后,便可以使用qsort排序整形数据。

#include<stdio.h>
#include<stdlib.h>int com_int(const void* e1, const void* e2)
{return *(int*)e1 - *(int*)e2;
}void print(int arr[], int sz)
{int i = 0;for (;i < sz;i++){printf("%d ", arr[i]);}
}void test1()
{int arr[10] = { 2,3,5,6,82,4,6,67,10,30 };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), com_int);print(arr, sz);
}int main()
{test1();return 0;
}

思路理解:

  1. 先把arr数组的首元素的地址传给qsort函数,
  2. 接着告诉qsort函数有多少数据(即sz),
  3. 知道个数后,qsort并不知道一次要跳过多少个字节,因此需要告诉告诉qsort这个arr数组一个元素的长度(即字节)
  4. 最后按照qsort的使用实现两个函数的比较。在com_int函数中,发明者并不知道客户传过来的是什么类型的数据,因此设为void型指针(可以接受任何类型的数据),最后进行强制类型转换即可。

qsort排序结构体数据

#include<stdio.h>
#include<stdlib.h>struct Stu
{char name[20];int age;
};int cmp_struct(const void* e1, const void* e2)
{return (*(struct Stu*)e1).age - (*(struct Stu*)e2).age;
}void test2()
{struct Stu s[3] = { {"zhangsan",15},{"lisi",18},{"wangwu",20} };int sz = sizeof(s) / sizeof(s[0]);qsort(s, sz, sizeof(s[0]), cmp_struct);
}int main()
{test2();return 0;
}

qsort排序字符串数据

排序字符串数据时,我们会遇到一个问题:a和b如何进行比较呢?
这时要使用strcmp函数(用来比较字符串大小)。

//strcmp和qsort返回值一样
//strcmp(字符串1,字符串2)
//如果字符串1 大于 字符串2,返回>0的数字
//如果字符串1 等于 字符串2,返回0
//如果字符串1 小于 字符串2,返回<0的数字#include<stdio.h>
#include<stdlib.h>
#include<string.h>struct Stu
{char name[20];int age;
};int cmp_struct(const void* e1, const void* e2)
{return strcmp((*(struct Stu*)e1).name) - strcmp((*(struct Stu*)e2).name);
}void test2()
{struct Stu s[3] = { {"zhangsan",15},{"lisi",18},{"wangwu",20} };int sz = sizeof(s) / sizeof(s[0]);qsort(s, sz, sizeof(s[0]), cmp_struct);
}int main()
{test2();return 0;
}

总的来说,qsort可以接收任何类型的数据,并且完成两两数据的大小交换。


3.qsort的模拟实现

那么我们能不能实现一个函数,就像qsort一样能排序任意类型的数据
1.qsort是按照快速排序的思想。
2.在冒泡排序的基础上,改造成能够排序任意类型的数据。

详解冒泡排序原理
在这里插入图片描述


qsort的模拟实现
#include<stdio.h>print(int arr[], int sz)
{int i = 0;for (i = 0;i < sz;i++){printf("%d ", arr[i]);}
}void Swap(char* buf1, char* buf2, size_t width)
{int i = 0;for (i = 0;i < width;i++){char tmp = *buf1;*buf1 = *buf2;*buf2 = tmp;buf1++;buf2++;}
}int cmp_int(const void* e1, const void* e2)
{return *(int*)e1 - *(int*)e2;
}void bubble_sort(void* base, size_t num, size_t width, int (*cmp)(const void* e1, const void* e2))
{int i = 0;for (i = 0;i < num - 1;i++){int j = 0;for (j = 0;j < num - 1 - i;j++){if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0){Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);}}}
}void test3()
{int arr[10] = { 0,1,2,3,4,5,6,8,7,9 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);print(arr, sz);
}int main()
{test3();return 0;
}

我们来逐层分析这段代码的实现:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/450986.html

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

相关文章

Python画笔案例-087 绘制 旋转的文字

1、绘制 旋转的文字 通过 python 的turtle 库绘制 旋转的文字,如下图: 2、实现代码 绘制 旋转的文字,以下为实现代码: """旋转的文字.py """ import time from turtle import * from write_patch import *screen = Screen

【JPCS独立出版 | 福州大学主办 | 有确定的ISSN号】第三届可再生能源与电气科技国际学术会议(ICREET 2024)

第三届可再生能源与电气科技国际学术会议&#xff08;ICREET 2024&#xff09; 2024 3rd International Conference on Renewable Energy and Electrical Technology ICREET 2024已成功申请JPCS - Journal of Physics: Conference Series (ISSN:1742-6596) 独立出版&#xf…

架构设计笔记-16-嵌入式系统架构设计理论与实践

目录 知识要点 嵌入式微处理器 存储器&#xff08;memory&#xff09; 内&#xff08;外&#xff09;总线逻辑 嵌入式操作系统&#xff08;Embedded Operating System&#xff0c;EOS&#xff09; 通用中间件 嵌入式中间件的一般架构 典型嵌入式中间件系统 案例分析 1…

搭建mongodb单机部署-认证使用

搭建mongodb单机部署-认证使用 实现思路 先将配置文件配置好&#xff0c;使用不用认证的启动命令启动docker&#xff0c;然后创建账号并制定角色。在使用开启认证的命令重新启动容器就好。 这里我并没有说先停止容器&#xff0c;删掉容器重新创建容器。是因为我的启动命令中…

机器学习—Motivations

学习了线性回归&#xff0c;它预测了一个数字&#xff0c;接下来学习分类&#xff0c;输入变量y只能接收少数几个可能的值中的一个&#xff0c;而不是无限范围内的任何数字。事实证明&#xff0c;线性回归不是分类问题的好算法。这将引入一种不同的算法&#xff0c;叫做Logisti…

立仪科技:光谱共焦传感器精准测量玻璃

光谱共焦测量技术作为一种创新的光学检测方法&#xff0c;近年来在工业领域引起了广泛关注。 它以其高精度、非接触式的特点&#xff0c;特别适用于透明或半透明材料如玻璃的厚度和表面形貌测量。 接下来&#xff0c;立仪科技小编将深入探讨光谱共焦技术在玻璃测量上的应用及其…

【MySQL】增删改查-进阶(一)

目录 &#x1f334;数据库约束 &#x1f6a9;约束类型 &#x1f6a9;NOT NULL &#x1f6a9;UNIQUE &#x1f6a9;DEFAULT &#x1f6a9;PRIMARY KEY &#x1f6a9;FOREIGN KEY &#x1f6a9;CHECK &#x1f384;表的设计 &#x1f6a9;一对一 &#x1f6a9;一对多 …

Spring Boot知识管理:智能搜索与分析

3系统分析 3.1可行性分析 通过对本知识管理系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本知识管理系统采用JAVA作为开发语言&#xff0c;Spring Boot框…

如何做好SQL 数据库安全

随着信息技术的迅猛发展&#xff0c;数据库在现代信息系统中的重要性日益凸显。无论是电子商务平台、金融系统还是社交媒体应用&#xff0c;数据库都是其核心组件之一。其中&#xff0c;SQL&#xff08;Structured Query Language&#xff0c;结构化查询语言&#xff09;数据库…

微信小程序使用MQTT连接阿里云

目录 一、新建项目和项目整体配置​ 二、MQTT 下载引入和配置连接​ 三、阿里云配置 1、创建产品及设备 2、数据进行云流转 四、创建 MQTT 连接​ 五、微信小程序配置 六、效果展示 1、微信小程序发送控制命令 2、LED台灯反馈LED状态 七、微信小程序项目完整代码 一…

论文笔记:PTR: Prompt Tuning with Rules for Text Classification

Abstract 手动设计大量语言提示麻烦且易出错&#xff0c;而自动生成的提示&#xff0c;在非小样本场景下验证其有效性昂贵且耗时。因此&#xff0c;提示调优以处理多类别分类任务仍然具有挑战。为此&#xff0c;本文提出使用规则进行多类别文本分类提示调优&#xff08;PTR&…

Linux发展与基础

Linux基础知识 Shell 命令执行环境&#xff1a; 命令提示符的组成&#xff1a;(用户名主机名)-[当前路径]权限提示符,例&#xff1a;&#xff08;kali㉿kali)-[~]$ ~ 表示所在目录为家目录:其中root用户的家目录是/root&#xff0c;普通用户的家目录在/home下 # 表示用户的权…

C#学习笔记(二)

C#学习笔记&#xff08;二&#xff09; 第 二 章 命名空间和类、数据类型、变量和代码规范一、命名空间-namespace1. 作用与具体表达形式-using2. 命名空间如何分类&#xff1f;3. 命名空间的命名规范 第 二 章 命名空间和类、数据类型、变量和代码规范 深水区 一、命名空间-…

掌握高效工作汇报技巧:如何利用即时白板打造完美日报,提升职场影响力

在快节奏的工作环境中&#xff0c;撰写工作日报、周报和月报已成为职场人士的日常任务。一份精心准备的工作汇报不仅能够体现我们的敬业精神&#xff0c;还能吸引上级的注意&#xff0c;提升我们在团队中的能见度。使用即时白板作为辅助工具&#xff0c;可以让我们更高效地梳理…

分析调优、性能测试曲线图

目录 一、分析调优 性能测试分析的关键指标 分析步骤 收集数据&#xff1a; 找到瓶颈&#xff1a; 性能调优策略 调优硬件资源&#xff1a; 数据库调优&#xff1a; 持续监控和改进 二、性能测试曲线图 1. 轻负载阶段&#xff08;Light Load&#xff09; 2. 重负载…

mqtt客户端订阅一直重复连接?

文章 前言错误场景问题分析解决方案后言 前言 ✨✨ 他们是天生勇敢的开发者&#xff0c;我们创造bug&#xff0c;传播bug&#xff0c;毫不留情地消灭bug&#xff0c;在这个过程中我们创造了很多bug以供娱乐。 前端bug这里是博主总结的一些前端的bug以及解决方案&#xff0c;感兴…

D37【python 接口自动化学习】- python基础之函数

day37 函数的参数&#xff08;上&#xff09; 学习日期&#xff1a;20241014 学习目标&#xff1a;函数&#xfe63;-50 函数的参数&#xff1a;怎样实现函数与外部数据通信&#xff1f; 学习笔记&#xff1a; 实参与形参 代码实现 # 实参与形参 def foo(number):print(nu…

热更新解决方案2 —— Lua语法相关知识点

概述 开发环境搭建 Lua语法 1.第一个Lua程序 2.变量 print("******变量*******"); --lua当中的简单变量类型 -- nil number string boolean -- lua 中所有的变量声明 都不需要声明变量类型 它会自动的判断类型 -- 类似C# 中的var --lua中的一个变量 可以随便赋值 ——…

Python NumPy 在神经网络中的矩阵运算与激活函数详解

Python NumPy 在神经网络中的矩阵运算与激活函数详解 文章目录 Python NumPy 在神经网络中的矩阵运算与激活函数详解一 矩阵乘法回顾1 定义矩阵2 矩阵乘法计算 二 NumPy 矩阵乘法三 神经网络的分类与回归1 回归问题2 分类问题1&#xff09;定义 sigmoid 函数2&#xff09;定义学…

第十二章 RabbitMQ之失败消息处理策略

目录 一、引言 二、RepublishMessageRecoverer 实现 2.1. 实现步骤 2.2. 实现代码 2.2.1. 异常交换机队列回收期配置类 2.2.2. 常规交换机队列配置类 2.2.3. 消费者代码 2.2.4. 消费者yml配置 2.2.5. 生产者代码 2.2.6. 生产者yml配置 2.2.7. 运行效果 一、引言 …