库函数qsort 的模拟实现

news2024/11/20 12:36:19

在之前了解了库函数qsort的使用之后 我们来模拟实现一下

上篇有介绍 qsort的底层实现是快速排序 由于害怕没有人了解过快速排序 我就用大家熟知的冒泡排序进行模拟实现

先来展示完整代码 以下代码为升序排序 如果降序将冒泡排序中的大于号改为小于号就可以了

#define _CRT_SECURE_NO_WARNINGS 1


#include<stdio.h>

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

void Swap(char* buf1, char* buf2, int width)
{
    for (int i = 0; i < width; i++)
    {
        char tmp = *buf1;
        *buf1 = *buf2;
        *buf2 = tmp;
        buf1++;
        buf2++;
    }
}

void my_qsort(void* base, size_t num, size_t width, int (*my_cmp)(const void* p1, const void* p2))
{
    for (size_t i = 0; i < num - 1; i++)
    {
        for (size_t j = 0; j < num - i - 1; j++)
        {
            if (my_cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
            {
                Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
            }
        }
    }
}
void Print(int* arr[], int sz)
{
    for (int i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main()
{
    int arr[] = { 7,4,1,8,5,2,9,6,3 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    Print(arr, sz);
    my_qsort(arr, sz, sizeof(arr[0]), my_cmp);
    Print(arr, sz);
    return 0;
}

解释以上代码

void my_qsort(void* base, size_t num, size_t width, int (*my_cmp)(const void* p1, const void* p2))
{
    for (size_t i = 0; i < num - 1; i++)
    {
        for (size_t j = 0; j < num - i - 1; j++)
        {
            if (my_cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
            {
                Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
            }
        }
    }
}

我们可以看出 在参数中 base(数组arr首元素地址) 是void*类型的 所以没有大小 那么我们就不能对voide*指针变量作加减操作 如果要作加减必须强制转化为其他的指针类型(具有大小的指针类型)

那我们这块为什么要用char*进行强制类型转换 因为他的大小只有一个字节 适合便利传过来的数组的各种类型 (数组类型的大小无非就是char*指针进行堆积的效果吗)所以用它进行访问最合适了

my_cmp是我们要传的函数指针 (char*)base + j*width 是该数组元素地址的起始地址 第二的参数是数组第二个元素的起始地址 传过去的就是一个char*大小的指针(理解这块 这块是核心)

那么如何交换两个元素呢

我们交换了两个元素的地址 不就交换了 两个元素了吗 接下来就是怎样交换两个元素的地址

void Swap(char* buf1, char* buf2, int width)
{
    for (int i = 0; i < width; i++)
    {
        char tmp = *buf1;
        *buf1 = *buf2;
        *buf2 = tmp;
        buf1++;
        buf2++;
    }
}

bud1,buf2就是传过来元素地址的首字节 将数组元素占的地址一一交换

就是这样的实现方式

最后代码的运行结果如下

以上就是qsort的实现 如果掌握其他排序方式 也可以用来实现~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

malloc实现原理探究

2021年末面试蔚来汽车&#xff0c;面试官考察了malloc/free的实现机制。当时看过相关的文章&#xff0c;有一点印象&#xff0c;稍微说了一点东西&#xff0c;不过自己感到不满意。今天尝试研究malloc的实现细节&#xff0c;看了几篇博文&#xff0c;发现众说纷纭&#xff0c;且…

MySql启动错误(Mac系统 安装 mysql-8.0.32-macos13-arm64 后每次点击启动 无法启动) --- 已解决

MySql启动的时候: 立即变红! 查看日志如下: 2023-03-04T14:18:01.089671Z 0 [System] [MY-010910] [Server] /usr/local/mysql/bin/mysqld: Shutdown complete (mysqld 8.0.32) MySQL Community Server - GPL. 2023-03-04T14:18:10.304169Z 0 [System] [MY-010116] [Server]…

【EDA工具使用】——VCS和Verdi的联合仿真的简单使用

目录 1.芯片开发所需的工具环境 2.编译仿真工具 3.三步式混合编译仿真&#xff08;最常用&#xff09;​编辑 4.两步式混合编译仿真​编辑 5.VCS的使用 ​6.verdi的使用 1.产生fsdb文件的两种方法​编辑 1.芯片开发所需的工具环境 2.编译仿真工具 3.三步式混合编译仿真…

按位与为零的三元组[掩码+异或的作用]

掩码异或的作用前言一、按位与为零的三元组二、统计分组1、map统计分组2、异或掩码总结参考资料前言 当a b 0时&#xff0c;我们能够很清楚的知道b是个什么值&#xff0c;b 0 - a -a&#xff0c;如果当a & b 0时&#xff0c;我们能够很清楚的知道b是什么值吗&#xf…

Python GUI界面编程-初识

图形用户界面(Graphical User Interface&#xff0c;简称 GUI&#xff0c;又称图形用户接口)是指采用图形方式显示的计算机操作用户界面。与早期计算机使用的命令行界面相比&#xff0c;图形界面对于用户来说在视觉上更易于接受。然而这界面若要通过在显示屏的特定位置&#xf…

HiveSQL一天一个小技巧:如何精准计算非连续日期累计值【闪电快车面试题】

0 需 求稀疏字段累计求和问题1 问题分析根据图片中数据变换的形式&#xff0c;可以看出是根据字段term补齐数据中缺失的日期&#xff0c;term为连续日期的个数&#xff0c;当为12时&#xff0c;表明由2018-12-21到2019-01-02连续日期个数为12&#xff0c;当补齐日期后&#xff…

sklearn中的逻辑回归

目录 一.名为“回归”的分类器 二.逻辑回归的优点 三.sklearn中的逻辑回归 四.linear_model.LogisticRegression 五.penalty & C(正则化) 六.逻辑回归中的特征工程 1.业务选择 2.PCA和SVD一般不用 3.统计方法可以使用&#xff0c;但不是非常必要 4.高效的嵌入法e…

【vulhub漏洞复现】CVE-2013-4547 Nginx 文件名逻辑漏洞

一、漏洞详情影响版本 Nginx 0.8.41 ~ 1.4.3 / 1.5.0 ~ 1.5.7通过%00截断绕过后缀名的限制&#xff0c;使上传的php内容文件被解析执行。当Nginx得到一个用户请求时&#xff0c;首先对url进行解析&#xff0c;进行正则匹配&#xff0c;如果匹配到以.php后缀结尾的文件名&#x…

2022秋-2023-中科大-数字图像分析-期末考试试卷回忆版

今天晚上刚考完&#xff0c;心累&#xff0c;在这里继续授人以渔(仅供参考&#xff0c;切勿对着复习不看ppt&#xff0c;ppt一定要过两遍)。 注意:往年的经验贴&#xff0c;到此为止&#xff0c;全部作废&#xff0c;一个没考。千万不要只对着复习&#xff0c;SIFT没考&#x…

JavaScript(JS)

一、三种引入方式&#xff1a; 1、内部js 通过script标签嵌入到html里面 <script>alert(hello);</script> 2、外部js 写成一个单独的.js文件&#xff0c;让html引入进来 <script src"app.js"></script> 3、行内js 直接写到html内部 &…

Python爬虫——使用socket模块进行图片下载

Python爬虫——使用socket模块进行图片下载什么是socket爬虫的工作流程socket爬取图片为什么能用socket能下载图片socket下载图片和request下载图片的区别使用socket下载一张图片使用socket下载多张图片方法1方法2什么是socket Socket 是一种通信机制&#xff0c;用于实现网络…

AQS为什么用双向链表?

首先&#xff0c;在AQS中&#xff0c;等待队列是通过Node类来表示的&#xff0c;每个Node节点包含了等待线程的信息以及等待状态。下面是Node类的部分源码&#xff1a;static final class Node {// 等待状态volatile int waitStatus;// 前驱节点volatile Node prev;// 后继节点…

【AI绘图学习笔记】深度学习相关数学原理总结(持续更新)

如题&#xff0c;这是一篇深度学习相关数学原理总结文&#xff0c;由于深度学习中涉及到较多的概率论知识&#xff08;包括随机过程&#xff0c;信息论&#xff0c;概率与统计啥啥啥的)&#xff0c;而笔者概率知识储备属实不行&#xff0c;因此特意开一章来总结&#xff08;大部…

Jackson CVE-2017-17485 反序列化漏洞

0x00 前言 同CVE-2017-15095一样&#xff0c;是CVE-2017-7525黑名单绕过的漏洞&#xff0c;主要还是看一下绕过的调用链利用方式。 可以先看&#xff1a; Jackson 反序列化漏洞原理 或者直接看总结也可以&#xff1a; Jackson总结 涉及版本&#xff1a;2.8.10和2.9.x至2.…

leetcode_贪心算法

贪心算法相关题简单题目455.分发饼干1005.K次取反后最大化的数组和860.柠檬水找零序列问题376.摆动序列法一&#xff1a;贪心法法二&#xff1a;动态规划单调递增的数字简化版本有点难度53.最大子序和贪心算法动态规划134.加油站968.监控二叉树两个维度权衡问题分发糖果406.根据…

MATLAB——系统环境

MATLAB概述MATLAB的发展MATLAB:MATrix LABoratory1980年前后&#xff0c;Cleve Moler教授编写的Linpack 和Eispack的接口程序。1984年&#xff0c;MATLAB第1版(DOS版)1992年&#xff0c;MATLAB4.0版1994年&#xff0c;MATLAB 4.2版1997年&#xff0c;MATLAB 5.0版1999年&#x…

12-Trie树

Trie树&#xff08;又称字典树、单词查找树&#xff09;是一种树型的数据结构&#xff0c;常用于保存和查找字符串&#xff0c;是一种十分高效率的存储和检索方式。 Trie树原理 我们先假设有六个字符串需要存储&#xff1a;abc、abcd、abef、cfgh、bc、bcd。Trie树的存储原理…

Scala04 方法与函数

Scala04 方法与函数 Scala 中的也有方法和函数的概念。 Scala中的 方法 是类的一部分。 Scala中的 函数 是一个对象&#xff0c;可以赋值给变量。 在类中定义的函数就是方法 4.1 方法 Scala 中方法 与 Java 中类似&#xff0c;是组成类的一部分 4.1.1 语法结构 格式&#x…

数据库“啃”不动?CnosDB带你轻松阅读十万行源码!

最近一直有社区的小伙伴问&#xff0c;我们很感兴趣CnosDB&#xff0c;但从何开始阅读CnosDB的代码呢&#xff0c;其实这个问题在之前的CnosDB HiTea直播时就有聊到&#xff0c;今天我们就再来回顾一下。CnosDB的源代码主要分为Query Engine和Storage Engine。Query Engine在qu…

JOSN数据转换和解析

文章目录JOSN数据转换和解析内容回顾Map 集合转成 JSON 字符串List 集合转换成 JSON 字符串Ajax 异步和同步异步概念同步概念异步和同步区别异步请求案例同步请求时间格式化旧时间 api 格式化格式化和解析的工具类JSTL 时间格式化JSTL 使用JOSN数据转换和解析 内容回顾 ajax …