C生万物 | 从浅入深理解指针【第三部分】(qsort的使用和模拟实现)

C生万物 | 从浅入深理解指针【第四部分】(qsort的使用和模拟实现)

文章目录

  • C生万物 | 从浅入深理解指针【第四部分】(qsort的使用和模拟实现)
    • 回调函数是什么?
    • qsort使用举例
    • qsort函数的模拟实现

回调函数是什么?

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

qsort使用举例

  • qsort是一个库函数,用来对数据进行排序,可以排任意类型的数据

  • 我们打开cplusplus网站搜索qsort

在这里插入图片描述

这个qsort函数有4个参数:

void qsort(void* base, size_t num, size_t size,int (*compar)(const void*, const void*));
  • 第一个参数是指向待排序的第一个元素
  • 第一个参数是待排序的元素个数
  • 第一个参数是待排序的数组元素的大小(单位是字节)
  • 第一个参数是比较两个元素

  • 这里有个void*的指针类型,这个指针类型是通用指针类型,这个指针类型可以接收任意类型数据的地址,就可以理解成指针垃圾桶,谁的地址都可以往里扔~~

  • 是一个无具体类型的指针,所以就不能+1,也不能解引用


我们也介绍完了这个函数,我们来使用一下

写出我们的主函数:

int main()
{int arr[] = { 3,2,5,6,8,7,9,1,4 };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_int);for (size_t i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}
  • 下面这里就剩下一个比较函数了,怎么写呢?我们再来看一个网站上面的介绍~~
  • 这个函数能够比较e1和e2指向的两个元素,并给出返回值~~

在这里插入图片描述

  • 我们也就按照上面的案例来写~~
int cmp_int(const void* e1, const void* e2)
{return *(int*)e1 - *(int*)e2;
}
  • 现在我们来看已经完美排序了~~

在这里插入图片描述

qsort函数的模拟实现

使用回调函数,模拟实现qsort(采用冒泡的方式)。

  • 今天我们使用冒泡排序,来实现一个对任意类型能够排序的函数

  • 我们先来实现一个整形的冒泡排序,然后再进行改造~~

void bubble_sort(int arr[], int sz)
{int i = 0;for ( i = 0; i < sz - 1; i++){int j = 0;for (j = 0; j < sz - 1 - i; j++){if (arr[j] > arr[j + 1]){int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}}
}int main()
{int arr[] = { 3,2,5,6,8,7,9,1,4 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz);for (size_t i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}

接下来我们开始改造~~

  1. 改造参数 – 让这个函数能够接受任意类型的数据
  2. 改造比较方法 – 让函数能够在排序时,比较不同类型的数据
  3. 交换的代码也需要修改

  • 我们来看完整代码
void print_arr(int arr[], int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%d ", arr[i]);}
}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 cmp_int(const void* e1,const void* e2)
{return *(int*)e1 - *(int*)e2;
}void test1()
{int arr[] = { 3,2,5,6,8,7,9,1,4 };int sz = sizeof(arr) / sizeof(arr[0]);bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), cmp_int);print_arr(arr,sz);}int main()
{test1();return 0;
} 

  • 可以看到,我们对整形的排序也成功了

在这里插入图片描述


好了,指针的第四部分就到这里就结束了~~
如果有什么问题可以私信我或者评论里交流~~
感谢大家的收看,希望我的文章可以帮助到正在阅读的你🌹🌹🌹

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

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

相关文章

算法:Java构建二叉树并递归实现二叉树的前序、中序、后序遍历

先自定义一下二叉树的类&#xff1a; // Definition for a binary tree node. public class TreeNode {int val;TreeNode left;TreeNode right;TreeNode() {}TreeNode(int val) { this.val val; }TreeNode(int val, TreeNode left, TreeNode right) {this.val val;this.left…

centos7中多版本go安装

安装go的方式 官网下载tar.gz包安装 # 1.下载tar包 wget https://go.dev/dl/go1.18.1.linux-amd64.tar.gz # 2.解压tar包到指定路径 tar -xvf go1.18.1.linux-amd64.tar.gz -C /usr/local/go1.18 # 3.配置环境变量&#xff0c;打开 /etc/profile 文件添加以下文件每次开机时…

【缓存】Spring全家桶中@CacheEvict无效情况共有以下几种

Spring全家桶中CacheEvict无效情况共有以下几种 一、背景介绍二、原因分析三、解决方案 一、背景介绍 SpringBoot中使用Cacheable注解缓存数据&#xff0c;使用CacheEvict注解删除缓存。但是在项目使用过程中&#xff0c;发现使用CacheEvict注解删除缓存无效。 拓展&#xff…

ElementuiPlus的table组件实现行拖动与列拖动

借助了插件sortablejs。这种方法只适合做非树状table。如果想实现树状table&#xff0c;并且可拖动。可以试一下aggridVue3这个插件 <template><div class"draggable" style"padding: 20px"><el-table row-key"id" :data"t…

【3D图像分割】基于 Pytorch 的 VNet 3D 图像分割3(3D UNet 模型篇)

在本文中&#xff0c;主要是对3D UNet 进行一个学习和梳理。对于3D UNet 网上的资料和GitHub直接获取的代码很多&#xff0c;不需要自己从0开始。那么本文的目的是啥呢&#xff1f; 本文就是想拆解下其中的结构&#xff0c;看看对于一个3D的UNet&#xff0c;和2D的UNet&#x…

keepalived与nginx与MySQL

keepalived VRRP介绍 集群&#xff08;cluster&#xff09;技术是一种较新的技术&#xff0c;通过集群技术&#xff0c;可以在付出较低成本的情况下获得在性能、可靠性、灵活性方面的相对较高的收益&#xff0c;其任务调度则是集群系统中的核心技术。 集群组成后&#xff0c;可…

IMU漂移相关

个人对IMU的漂移一直以来都很困惑&#xff0c;总结整理了这些材料&#xff0c;希望能理清楚一点思路。 总的来讲&#xff0c;IMU的漂移可建模为三部分&#xff0c;随机常值相关漂移白噪声&#xff0c; 但实际使用时&#xff0c;三者都出现的用法很少。严恭敏老师在博客中有相关…

【软件测试】工作内容

测试工程师工作&#xff1a; 阶段&#xff1a;编写测试计划测试用例、测试缺陷报告并执行测试用例&#xff1b;搭建Windows测试环境熟练&#xff1b;使用Bugzilla 提交软件缺陷报告 使用测试技术及工具&#xff1a;白盒测试黑盒测试 Loadrunner、Winrunner 能够运用边界值、等…

【ArcGIS Pro二次开发】(74):Python、C#实现Excel截图导出图片

以村庄规划制图为例&#xff0c;通过对现状和规划用地的统计&#xff0c;生成Excel格式的【空间功能结构调整表】后&#xff0c;需要进一步将表格导出成图片&#xff0c;并嵌入到图集中&#xff0c;这样可以实现全流程不用手动参与&#xff0c;让制图的流程完全自动化。 关于E…

【Mybatis小白从0到90%精讲】09:Mybatis动态SQL:if、where、set标签

文章目录 前言一、if 标签二、where 标签三、set 标签前言 动态SQL 是 Mybatis的亮点功能之一,如果你经历过 拼接SQL 的繁琐痛苦,那么你就能切身感受到动态SQL到底有多爽!真香哈~ 另外,Mybatis将动态SQL设计的如此自然,让人看看就能理解和接受,我想这也是Mybaits如此深…

CCF-CSP真题《202305-4 电力网络》思路+python,c++满分题解

想查看其他题的真题及题解的同学可以前往查看&#xff1a;CCF-CSP真题附题解大全 试题编号&#xff1a;202305-4试题名称&#xff1a;电力网络时间限制&#xff1a;1.0s内存限制&#xff1a;512.0MB问题描述&#xff1a; 问题描述 西西艾弗岛电力公司需要修建一套电网对岛上的众…

LIME低亮度图像增强

LIME低亮度图像增强 main.cpp #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <iostream> #include <opencv2/imgproc/imgproc.hpp> #include "lime.h"int main() {cv::Mat img_in cv::imread("…