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

【c语言】qsort函数及泛型冒泡排序的模拟实现

🌟🌟作者主页ephemerals__

🌟🌟所属专栏C语言

目录

一、qsort函数

1.回调函数

2.qsort函数

3.void* 指针

二、泛型冒泡排序的模拟实现

1.比较函数的编写

2.交换函数的编写

3.冒泡排序的编写

4.全部代码和使用示例

总结


一、qsort函数

1.回调函数

        在了解qsort函数之前,我们先来学习一个概念:回调函数。那么回调函数是什么呢?

简单地说,回调函数就是通过函数指针调用的函数。

        如果你将函数A的地址传给另外一个函数B,当B通过这个地址调用函数A时,函数A就称作回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或者条件进行响应。

2.qsort函数

        在了解了回调函数的概念后,我们来学习一下qsort函数。qsort函数是c语言标准库下的一个函数,它的作用是对任意类型的数据进行排序。我们在cplusplus上搜索一下它:

可以看到,这个函数在使用的时候需要引头文件<stdlib.h>。它有四个参数,其中第四个参数就是一个函数指针。我们再观察一下四个参数的内容:

第一个参数是一个指向数组首元素的指针base,它会被转换为void*类型的指针。

第二个参数是这个数组中的元素个数num,类型是size_t。

第三个参数是数组中每一个元素的内存大小size。

第四个参数是一个函数指针compar,这个函数指针指向的函数用于比较两个元素,也就是说,在qsort函数执行排序功能时,需要调用我们自己写的元素比较函数。对于比较函数,如果第一个参数小于第二个参数,就返回负数,反之就返回正数,相等则返回0。

可以看出,qsort函数是通过compar函数的地址调用它的,所以这里的compar函数就是一个回调函数

        好,我们现在来试着使用一下qsort函数:

#include <stdio.h>
#include <stdlib.h>int cmp_int(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;//对int类型数据进行比较,将void*型指针强制转换为int*类型
}int main()
{int arr[10] = { 2,10,5,4,9,3,6,8,1,7 };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(int), cmp_int);for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}

运行结果:

可以看到,数组的元素确实被排序过来了。

3.void* 指针

        刚才的代码当中,我们使用了void*类型的指针作为形参。我们来着重介绍一下void*类型的指针。

void*类型的指针也叫做无具体类型的指针,它的作用是可以接收任何类型的指针,常常存在于形参之中。当使用void*类型的指针时,它是无法直接进行解引用操作的,需要将其强制类型转换为其他类型的指针,才能确定访问的字节数,从而继续使用。

二、泛型冒泡排序的模拟实现

        接下来,我们基于能够排序任意类型的数据qsort函数,模拟实现一个冒泡排序,能够排序任意类型的数据。

1.比较函数的编写

        首先我们来编写比较函数。以int类型为例,将void*指针转换为int*类型即可。

int cmp_int(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;
}

这里将传入元素的地址,之后以int类型的形式访问四个字节,然后进行大小比较,前者大于后者

则返回正数,否则返回负数,相等返回0。

2.交换函数的编写

接下来我们写一个函数来实现元素的交换(注意:这里由于不知要交换什么类型的元素,所以要转换为char*类型的指针,然后一个字节一个字节地交换):

void swap(void* p1, void* p2, size_t size)
{int i = 0;char tmp = 0;for (i = 0; i < size; i++)//一个字节一个字节地交换,交换size次{tmp = *((char*)p1 + i);*((char*)p1 + i) = *((char*)p2 + i);*((char*)p2 + i) = tmp;}
}

注意:由于强制类型转换是临时的,所以每一次使用的时候都要进行强制类型转换。

为了便于大家理解这里的交换过程,我们画图演示一下:

3.冒泡排序的编写

        冒泡排序的编写大体和原本的冒泡排序相同,但是有些细节需要处理:

void bubble_sort(void* base, size_t num, size_t sinumze, int(*cmp)(const void*, const void*))
{int i = 0;int j = 0;for (i = 0; i < num - 1; i++){for (j = 0; j < num - 1 - i; j++){//这里需要将数组中下标为j和j+1的元素进行比较,所以将base强制转换为char*类型,然后加上相应内存大小的j倍或j+1倍就可以得到第j和j+1个元素的地址if (cmp((char*)base + size * j, (char*)base + size * (j + 1)) > 0){//相同道理,交换第j和j+1个元素swap((char*)base + size * j, (char*)base + size * (j + 1), size);}}}
}

4.全部代码和使用示例

程序全部代码:

int cmp_int(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;
}void swap(void* p1, void* p2, size_t size)
{int i = 0;char tmp = 0;for (i = 0; i < size; i++)//一个字节一个字节地交换,交换size次{tmp = *((char*)p1 + i);*((char*)p1 + i) = *((char*)p2 + i);*((char*)p2 + i) = tmp;}
}void bubble_sort(void* base, size_t num, size_t size, int(*cmp)(const void*, const void*))
{int i = 0;int j = 0;for (i = 0; i < num - 1; i++){for (j = 0; j < num - 1 - i; j++){//这里需要将数组中下标为j和j+1的元素进行比较,所以将base强制转换为char*类型,然后加上相应内存大小的j倍或j+1倍就可以得到第j和j+1个元素的地址if (cmp((char*)base + size * j, (char*)base + size * (j + 1)) > 0){//相同道理,交换第j和j+1个元素swap((char*)base + size * j, (char*)base + size * (j + 1), size);}}}
}

接下来我们试着使用一下,看看是否能够排序成功:

可以看到,排序成功了。大家也可以尝试编写其他类型的比较函数来进行排序。

        像这种可以针对任意类型的编程方法,我们称之为泛型编程。泛型编程提高了代码的重复利用率,增加了程序安全性和执行效率。

总结

        今天我们学习了qsort函数及泛型冒泡排序的模拟实现,由此可以看出泛型编程的好处。之后博主会和大家介绍一些c语言中的常见字符串函数,并且模拟实现。如果你觉得博主讲的还不错,就请留下一个小小的赞在走哦,感谢大家的支持❤❤❤

相关文章:

【c语言】qsort函数及泛型冒泡排序的模拟实现

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C语言 目录 一、qsort函数 1.回调函数 2.qsort函数 3.void* 指针 二、泛型冒泡排序的模拟实现 1.比较函数的编写 2.交换函数的编写 3.冒泡排序的编写 4…...

MySQL之多表查询—表子查询

一、引言 上一篇博客学习了行子查询。&#xff08;看弹幕&#xff1a;同一张表用or,不同张表用union&#xff09; 下面接着学习子查询当中的最后一种——表子查询。 表子查询 1、概念 子查询返回的结果是多行多列&#xff0c;这种子查询称为表子查询。 2、常用的操作符 IN 3、…...

Java 18风暴来袭:解锁编程新纪元

一、引言 Java 18的发布标志着Java语言在性能、安全性和开发效率方面的又一次飞跃。本次更新不仅带来了新的语言特性&#xff0c;还包括了一些实验性功能和工具的改进。这些新特性旨在帮助开发者编写更高效、更安全的代码&#xff0c;并提升开发体验。 二、新特性概述 1. 默…...

文件操作(Python和C++版)

一、C版 程序运行时产生的数据都属于临时数据&#xff0c;程序—旦运行结束都会被释放通过文件可以将数据持久化 C中对文件操作需要包含头文件< fstream > 文件类型分为两种: 1. 文本文件 - 文件以文本的ASCII码形式存储在计算机中 2. 二进制文件- 文件以文本的二进…...

Git【版本控制命令】

02 【本地库操作】 1.git的结构 2.Git 远程库——代码托管中心 2.1 git工作流程 代码托管中心用于维护 Git 的远程库。包括在局域网环境下搭建的 GitLab 服务器&#xff0c;以及在外网环境下的 GitHub 和 Gitee (码云)。 一般工作流程如下&#xff1a; 1&#xff0e;从远程…...

打字侠是一款PWA网站,如何下载到电脑桌面?

嘿&#xff0c;亲爱的键盘侠们&#xff01; 你是否还在为寻找一款好用的打字练习工具而烦恼&#xff1f;别担心&#xff0c;今天我要给大家介绍一位超级英雄——打字侠&#xff01;它不仅是一个超级酷的打字练习网站&#xff0c;还是一款PWA&#xff08;渐进式网页应用&#x…...

Scikit-learn使用步骤?使用场景?

Scikit-learn&#xff08;简称sklearn&#xff09;是Python中一个非常流行的机器学习库&#xff0c;它提供了广泛的机器学习算法和工具&#xff0c;用于数据分析、特征工程、模型训练、模型评估等任务。以下是一个关于sklearn的基础教程&#xff0c;内容将按照几个主要部分进行…...

MySQL 5.7详细下载安装配置教程(MySQL 5.7安装包)_mysql5.7的安装教程

记录MySQL 5.7 的下载安装教程&#xff0c;并提供了Mysql 安装包 &#xff0c;以下是详细下载安装过程。 一、下载Mysql安装包 网盘下载&#xff1a; 下载MySQL 5.7安装包&#xff0c;网盘下载地址&#xff1a;点击此处直接下载 官网下载&#xff1a; 进入官网&#xff0c…...

电阻十大品牌供应商

选型时选择热门的电阻品牌&#xff0c;主要是产品丰富&#xff0c;需求基本都能满足。 所所有的电路中&#xff0c;基本没有不用电阻的&#xff0c;电阻的选型需要参考阻值、精度、封装、温度范围&#xff0c;贴片/插件等参数&#xff0c;优秀的供应商如下&#xff1a; 十大电…...

深度学习复盘与论文复现C

文章目录 4、Distributed training4.1 GPU architecture 5、Recurrent neural network5.1 The basic structure of RNN5.2 Neural networks without hidden states5.3 Recurrent neural networks with hidden states5.4 summary 6、Language Model Dataset (lyrics from Jay Ch…...

海洋日特别活动—深海来客——可燃冰

深海中有一种神奇的物质&#xff0c;似冰又不是冰。 别看它其貌不扬&#xff0c;但本领不小&#xff0c;遇火即燃&#xff0c;能量巨大&#xff0c;可谓是能源家族的新宠。它就是被国务院正式批准列为我国第173个矿种的“可燃冰”&#xff01; 可燃冰到底是个啥&#xff1f;它…...

Web前端放图片位置:深入探索与最佳实践

Web前端放图片位置&#xff1a;深入探索与最佳实践 在Web前端开发中&#xff0c;图片作为重要的视觉元素&#xff0c;其放置位置往往影响着网页的整体布局和用户体验。然而&#xff0c;如何合理地放置图片&#xff0c;以最大化其视觉效果并提升用户体验&#xff0c;却是一个颇…...

leetcode-02-[977]有序数组的平方[209]长度最小的子数组[59]螺旋矩阵II

一、[977]有序数组的平方 重点&#xff1a; 新引入一个数组&#xff0c;不要原数组操作 class Solution {public int[] sortedSquares(int[] nums) {int left0,right nums.length-1;int[] resultnew int[nums.length];int index nums.length-1;while(left<right){if(nums…...

Spring Cloud Gateway CORS 跨域方案

通过配置文件&#xff0c;以下配置就是其中一种方案。 gateway: #跨域配置globalcors: cors-configurations: [/**]: allowedMethods: "*"allowedHeaders: "*"allowedOriginPatterns: "*"allowCredentials: truedefault-filters: - DedupeRespo…...

高考后志愿填报信息采集系统制作指南

在高考的硝烟散去之后&#xff0c;每位学生都面临着一个重要的任务——志愿填报。老师们如何高效、准确地收集和整理这些信息&#xff0c;成为了一个棘手的问题。难道我们只能依赖传统的手工登记方式&#xff0c;忍受其繁琐和易错吗&#xff1f; 易查分是一个简单易用的在线工具…...

Python使用Flask构建简单的web应用

构建一个简单的 Flask Web 应用程序是学习 Python Web 开发的良好起点。Flask 是一个轻量级的 WSGI Web 应用框架&#xff0c;它的主要目标是让开发者更容易构建 Web 应用&#xff0c;同时保持简单性和灵活性。下面我们将详细介绍如何使用 Flask 构建一个简单的 Web 应用&#…...

看似不同的事情,却是相同的坑

目录 一、背景二、过程1.遭遇战-微盘股的下杀2.不失为一件好事3.一切向后看吧&#xff0c;最近的学习感受4.该有的心境 三、总结 一、背景 也在一点点改变&#xff0c;期间势必要经历流血的过程&#xff1b;所谓无疯狂不成长&#xff0c;积极的心态去应对&#xff0c;去总结总…...

在 Linux 系统上安装 Android NDK

在 Linux 系统上安装 Android NDK 1. Android NDK2. NDK Downloads2.1. Latest LTS Version (r26d)2.2. Old Unsupported Versions 3. 安装 NDK4. Get started with the NDK (NDK 使用入门)References 1. Android NDK https://developer.android.com/ndk The Android NDK is …...

SpringBoot的学习要点

目录 SpringBoot 创建项目 配置文件 注解 命名规范 SpringBoot整合第三方技术 …… 中文文档&#xff1a;Spring Boot 中文文档 SpringBoot Spring Boot 是基于 Spring 框架的一种快速构建微服务应用的方式它主要提供了自动配置、简化配置、运行时应用监控等功能它…...

vue3引入cesium和olcs

首先引入包 pnpm i olcs; pnpm i -D vite-plugin-cesium pnpm i -S cesium在vite.config.js中配置&#xff0c;参考这位大佬的笔记 添加链接描述 import { defineConfig } from vite import vue from vitejs/plugin-vue import cesium from vite-plugin-cesium; // https://…...

代码随想录算法训练营第25天|回溯

回溯part02 216. 组合总和 III /*** param {number} k* param {number} n* return {number[][]}*/ var combinationSum3 function(k, n) {// k个数字相加为n// 只能使用1-9// 每个数字只能使用一次// 不能重复 如 1 2 4 、 4 1 2 不可以let res [];backtracking(k, n, [], …...

Ajax 快速入门

Ajax 概念&#xff1a;Ajax是一种Web开发技术&#xff0c;允许在不重新加载整个页面的情况下&#xff0c;与服务器交换数据并更新网页的部分内容。 作用&#xff1a; 数据交换&#xff1a;Ajax允许通过JavaScript向服务器发送请求&#xff0c;并能够接收服务器响应的数据。 异…...

面试官:前端实现图片懒加载怎么做?这不是撞我怀里了嘛!

前端懒加载&#xff08;也称为延迟加载或按需加载&#xff09;是一种网页性能优化的技术&#xff0c;主要用于在网页中延迟加载某些资源&#xff0c;如图片、视频或其他媒体文件&#xff0c;直到它们实际需要被用户查看或交互时才进行加载。这种技术特别适用于长页面或包含大量…...

每天学习一个Windows命令或Linux命令——seq

今天我们来学习 seq命令&#xff01; seq命令&#xff08;单词sequence序列的缩写&#xff09;是Linux系统中用于输出序列化的一串整数的命令。 一、seq用法 seq用法一共有以下三种&#xff1a; seq [选项]... 尾数 seq [选项]... 首数 尾数 seq [选项]... 首数 增量&#…...

C++设计模式-中介者模式,游戏对象之间的碰撞检测

运行在VS2022&#xff0c;x86&#xff0c;Debug下。 31. 中介者模式 中介者模式允许对象之间通过一个中介者对象进行交互&#xff0c;而不是直接相互引用。可以减少对象之间的直接耦合&#xff0c;同时集中化管理复杂的交互。应用&#xff1a;如在游戏开发中&#xff0c;可以使…...

Rust-02-变量与可变性

在Rust中&#xff0c;变量和可变性是两个重要的概念。 变量&#xff1a;变量是用于存储数据的标识符。在Rust中&#xff0c;变量需要声明其类型&#xff0c;例如&#xff1a; let x: i32 5; // 声明一个名为x的变量&#xff0c;类型为i32&#xff08;整数&#xff09;&#…...

mov指令中不允许的操作——汇编语言

在 x86 汇编语言中&#xff0c;MOV 指令的限制有助于确保系统的稳定性和正确的操作。下面详细解释为什么这些操作是不允许的。 1. 段寄存器之间直接传送数据 MOV DS, ES ; 错误&#xff0c;不允许原因&#xff1a; 段寄存器是用来定义程序段的开始位置&#xff0c;如代码段…...

Python进阶-部署Flask项目(以TensorFlow图像识别项目WSGI方式启动为例)

本文详细介绍了如何通过WSGI方式部署一个基于TensorFlow图像识别的Flask项目。首先简要介绍了Flask框架的基本概念及其特点&#xff0c;其次详细阐述了Flask项目的部署流程&#xff0c;涵盖了服务器环境配置、Flask应用的创建与测试、WSGI服务器的安装与配置等内容。本文旨在帮…...

WooYun-2016-199433 -phpmyadmin-反序列化RCE-getshell

参考资料&#xff1a; Phpmyadmin 脚本/设置.php反序列化漏洞 &#xff08;WooYun-2016-199433&#xff09;复现_phpmyadmin scriptssetup.php 反序列化漏洞-CSDN博客 https://blog.csdn.net/haoxue__/article/details/129368455利用pearcmd.php文件包含拿shell&#xff08;L…...

社交“学习伙伴”:Meta Llama助力对话升级

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

安装wordpress之后/谷歌搜索引擎下载

前提 这里做下笔记&#xff0c;记录下项目中遇到的问题 eslint别名设置 javascrpt开发 没有使用typescript之前&#xff0c;只需要在webpack或者vue.config.js设置alias即可。 // WEBPACK配置 configureWebpack{resolve: {extensions: [.js, .less, .sass, .css, .vue],alias:…...

南山网站制作/网站维护费用

题目描述&#xff1a; 给定一个单链表&#xff0c;把所有的奇数节点和偶数节点分别排在一起。请注意&#xff0c;这里的奇数节点和偶数节点指的是节点编号的奇偶性&#xff0c;而不是节点的值的奇偶性。 请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1)&#xff0c;时…...

wordpress安卓ios应用/google下载安卓版下载

2018 年的数字加密资产市场有 2 个热点&#xff1a;ICO 和 DAPP。ICO 的热度从 2017 年持续到 2018 年上半年就慢慢地淡出了我们的视野&#xff0c;DAPP 很快就接了这个市场的热度。从 2018 年 6 月份开始&#xff0c;随着 EOS 公链的上线&#xff0c;不少开发者也看到了 DAPP …...

那些是flash做的网站/西安霸屏推广

作为一名程序员&#xff0c;尤其是开发Android应用程序的程序员&#xff0c;不会自己折腾ROM简直就是一件不好意思的事情&#xff0c;于是乎我就费劲巴力的上网看资料&#xff0c;找工具&#xff0c;准备自己开始制作有“中国特色”的ROM&#xff0c;以下是解决的一些问题&…...

wordpress 提示要安装/soe搜索优化

作为2017世界物联网博览会的重要活动之一,由中国经济信息社江苏中心研撰的《2016-2017中国物联网发展年度报告》(下称《年报》)近日在无锡发布。《年报》认为,我国智慧城市步入实质发展阶段,企业广泛参与、营收能力增强。 2016年以来,我国智慧城市建设开放合作特征进一步凸显,B…...

做三国的网站/深圳网络营销推广招聘网

【解决方法】&#xff1a; 更改build/utils.js文件中的 ExtractTextPlugin 的 options配置. if (options.extract) {return ExtractTextPlugin.extract({use: loaders,publicPath: ../../, //注意: 此处根据路径, 自动更改fallback: vue-style-loader}) } else {return [vue-st…...