【C语言】剖析qsort函数的实现原理

主页:17_Kevin-CSDN博客

专栏:《C语言》

本文将从回调函数,qsort函数的应用,qsort函数的实现原理三个方面进行讲解,请自行跳转至相对位置进行阅读~ 

目录

回调函数

qsort函数的应用

qsort函数实现原理

回调函数

什么是回调函数?

回调函数实际上是一个指针,指向的是一个函数。它作为一个参数传递给另一个函数,并且在特定的条件下被执行。

回调函数的作用

回调函数的主要作用是使代码更加灵活和模块化。通过使用回调函数,我们可以将特定的行为或逻辑与原始函数分离开来,这样可以让我们更容易地进行代码重用和维护。

回调函数的实现

定义一个函数,然后将其作为参数传递给其他函数,在特定条件下执行

回调函数的示例

让我们以 C 语言为例,来看一个简单的回调函数示例:

#include <stdio.h>

void performOperation(int a, int b, int (*callback)(int, int))
{
    int result = callback(a, b);
    printf("The result is: %d\n", result);
}

int add(int a, int b)
{
    return a + b;
}

int main()
{
    int x = 10, y = 20;
    performOperation(x, y, add);  // 传递 add 函数作为回调函数
    return 0;
}

在这个示例中,performOperation 函数接受两个整数和一个函数指针作为参数,然后在内部调用传递进来的函数指针,实现了加法运算。在主函数中,我们将 add 函数作为回调函数传递给 performOperation 函数。这就是一个简单的回调函数的例子。

qsort函数的应用

函数定义

在官方文档中qsort的函数定义如下:

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

函数参数的剖析

base:

参数base是一个void* 类型的,qsor使用来排序的函数,该参数就是传入的要进行排序的数组。作为一个void*类型的指针,我们传入数组的地址,即可完成对要排序数组的传入。

num:

该参数位置要传入的是要进行排序的数组的元素个数,一般使用sizeof(数组名)/ sizeof(数组中的任意元素)进行计算得到个数。

size:

参数size传入的参数是数组中单个元素的大小,该参数可以确保在函数内排序的时候每次跳跃的字节大小是一个元素的字节的大小。

compar:
该参数是一个函数指针,指向比较两个元素的函数。 qsort内部会反复调用此函数来比较两个元素,以此来决定排序方向。

请注意!在传入该参数的时候请严格按照该参数的规范结构来书写。

int (*compar)(const void*,const void*)

为什么要用void*?

这是因为 qsort 函数可以对任意类型的数组进行排序,而不同类型的数据可能需要不同的比较方法。使用 void* 类型作为参数可以让比较函数更加通用,因为 void* 是一种无类型指针,可以指向任何类型的数据。在比较函数内部,我们可以将 void* 类型的指针转换为实际的数据类型再进行比较(强制类型转化)。

通过使用 void* 类型,可以在不知道具体数据类型的情况下编写通用的比较函数,使 qsort 函数更加灵活和通用。在比较函数中,我们需要负责将 void* 类型的指针转换为实际的数据类型,并进行比较操作。

使用 void* 类型的参数可以使比较函数更加通用,适用于不同类型的数据,从而增强了函数的灵活性和通用性。

经典代码示例

#include <stdio.h>
#include <stdlib.h>

// 比较函数,用于升序排序
int compare(const void *a, const void *b) {
    return (*(int*)a - *(int*)b);
}

int main() {
    int arr[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};

    int n = sizeof(arr) / sizeof(arr[0]);

    // 使用 qsort 对数组进行排序
    qsort(arr, n, sizeof(int), compare);

    printf("Sorted array: ");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}

在这个示例中,首先定义了一个整型数组 arr,然后通过 qsort 函数对数组进行排序。在 main 函数中,我们计算数组的大小 n,然后调用 qsort 函数,传入数组、数组大小、每个元素的大小以及比较函数 compare。比较函数 compare 中,我们将 void* 类型的指针转换为 int* 类型,并进行升序排序。最终得到的就是升序排序的数组了。

qsort函数实现原理

详细定义

qsort 函数是一个用于快速排序(Quick Sort)的标准库函数。它接受一个数组和一个比较函数作为参数,并对数组进行排序。快速排序是一种分治的排序算法,通过选择一个基准元素,将数组分为两部分,一部分比基准元素小,一部分比基准元素大,然后对这两部分递归地进行排序,最终得到一个有序的数组。

实现原理

  1. 选择基准元素qsort 函数首先选择数组中的一个元素作为基准元素。通常情况下,可以选择数组的第一个元素作为基准元素。

  2. 分区(Partition)qsort 函数使用选定的基准元素将数组分为两部分,一部分小于等于基准元素,另一部分大于基准元素。这个过程称为分区。

  3. 递归排序qsort 函数递归地对小于等于基准元素和大于基准元素的两部分进行排序。它分别对这两部分调用 qsort 函数,并将相应的比较函数传递给子函数。

  4. 合并结果:最后,qsort 函数将排序后的两部分合并起来,形成一个有序的数组。

模拟实现sort

以下代码使用C语言模拟实现qsort函数的代码:

#include <stdio.h>

void swap(int* a, int* b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int partition(int arr[], int low, int high) {
    int pivot = arr[high];
    int i = low - 1;

    for (int j = low; j <= high - 1; j++) {
        if (arr[j] < pivot) {
            i++;
            swap(&arr[i], &arr[j]);
        }
    }
    swap(&arr[i + 1], &arr[high]);
    return i + 1;
}

void quickSort(int arr[], int low, int high) {
    if (low < high) {
        int pi = partition(arr, low, high);

        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}

void myQsort(int arr[], int n) {
    quickSort(arr, 0, n - 1);
}

int main() {
    int arr[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};
    int n = sizeof(arr) / sizeof(arr[0]);

    myQsort(arr, n);

    printf("Sorted array: ");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}

这是一个以快速排序为基础的qsort函数实现,通过选择一个基准元素,并将数组分成两部分,使得左边的元素都小于或等于基准元素,而右边的元素都大于基准元素,然后对左右两部分递归地进行排序,最终得到一个有序的数组。

以下是各个函数的分解解析:

  1. swap 函数:这个函数用于交换两个整数的值。它接受两个整数指针作为参数,并使用 temp 变量来暂存其中一个整数的值,然后将两个整数的值进行交换。
  2. partition 函数:这个函数用于将一个数组的某个子数组分成两部分,使得左边的元素都小于或等于基准元素,而右边的元素都大于基准元素。它接受一个整数数组、子数组的起始索引和结束索引作为参数。首先,它选择最后一个元素作为基准元素,并将 i 初始化为 low - 1。然后,它使用一个循环从 low 到 high - 1 遍历数组,如果当前元素小于基准元素,就将 i 向右移动一个位置,并将当前元素和 arr[i] 进行交换。最后,它将基准元素和 arr[i + 1] 进行交换,使得基准元素位于正确的位置上。
  3. quickSort 函数:这个函数用于对一个数组进行快速排序。它接受一个整数数组和起始索引和结束索引作为参数。如果起始索引小于结束索引,它就调用 partition 函数将数组分成两部分,并对左右两部分递归地进行排序。
  4. myQsort 函数:这个函数是一个封装的快速排序函数,它接受一个整数数组和数组的大小作为参数,并调用 quickSort 函数对数组进行排序。
  5. main 函数:这个函数是程序的入口函数。它首先定义了一个整数数组 arr,并计算数组的大小。然后,它调用 myQsort 函数对数组进行排序,并打印排序后的结果。

 

本篇博客到此就结束啦~

如果有帮助到您的学习是我的无上荣幸!

感谢阅读!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

可让照片人物“开口说话”阿里图生视频模型EMO,高启强普法

3 月 1 日消息&#xff0c;阿里巴巴研究团队近日发布了一款名为“EMO&#xff08;Emote Portrait Alive&#xff09;”的 AI 框架&#xff0c;该框架号称可以用于“对口型”&#xff0c;只需要输入人物照片及音频&#xff0c;模型就能够让照片中的人物开口说出相关音频&#xf…

HTML+CSS+BootStrap景区官网

一、技术栈 支持pc、pad、手机访问&#xff0c;页面自适应&#xff01;&#xff01; html5cssbootstrapjs 二、项目截图 接受项目定制&#xff0c;站内联系博主&#xff01;&#xff01;&#xff01;

CPython:比较运算符串联的差异

相关阅读 Pythonhttps://blog.csdn.net/weixin_45791458/category_12403403.html?spm1001.2014.3001.5482 在C语言和Python中&#xff0c;比较运算符是一个常用的运算符&#xff0c;但这两种语言在某些情况下对比较运算符的解析缺存在差异&#xff0c;本文旨在明确这一点。 P…

【Spring云原生】Spring Batch:海量数据高并发任务处理!数据处理纵享新丝滑!事务管理机制+并行处理+实例应用讲解

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《Spring 狂野之旅&#xff1a;从入门到入魔》 &#x1f680; 本…

STM32(13)串口

串口的数据帧 1.空闲 2.起始位 3.数据位 4.校验位&#xff08;可有可无&#xff09; 为了验证数据传输是否出错而设立的比特位 1和4传输方式比较常见 校验规则&#xff1a; 根据1的个数&#xff0c;校验位会自己补0或1 5.停止位 例子&#xff1a; 同步通信 异步通信 波特率 …

避坑——Matlab c# 联合编程——Native

相同的库&#xff0c;Matlab生成供.net调用的库时会有两套&#xff0c;也就是Native&#xff08;本地&#xff09;&#xff0c;两套库各有优缺点&#xff0c;这这里就不说了&#xff0c;可以翻看网上其他博文 主要是MWStructArray&#xff0c;MWArray等数据交换对象有两套&…

魔行观察-蜜雪冰城-2008年至2023年的开店趋势图

闲来无事做&#xff0c;用魔行观察-魔查查上的品牌门店数据简单分析了一下知名饮品类品牌&#xff1a;蜜雪冰城 从2008年开始一直到2023年11月份的开店情况&#xff0c;发现在2022年是开得最猛的&#xff0c;确实牛皮。 魔查查数据获取地址&#xff1a;魔查查https://www.moxi…

【开发工具】GIF 录屏工具推荐 ( GIF123 - 推荐使用 | GifCam | LICEcap )

文章目录 一、GIF 录屏工具推荐1、GIF123 ( 推荐使用 )2、GifCam3、LICEcap 本博客中介绍的 3 款 GIF 录屏工具下载地址 : https://download.csdn.net/download/han1202012/88905642 也可以到对应的官网独立下载 : GIF123 : https://gif123.aardio.com/ ;GifCam : https://bl…

如何一键批量采集拼多多商品图片?无压缩高清主图/sku图/详情和视频下载|拼多多商品数据采集接口

大家好&#xff0c;这期我教下大家怎么下载拼多多上面的商品主图、详情页图、SKU图、主图视频、详情页视频的下载教程~~ 运营一个多多电商店铺&#xff0c;上架商品&#xff0c;我们都需要采集大量的商品图片进行分析和参考&#xff0c;一张张下载的话将耗费大量时间和精力&am…

美摄科技实时语音数字人解决方案

随着科技的飞速发展&#xff0c;数字人技术已经逐渐渗透到我们生活的各个角落。作为数字人技术的先驱者&#xff0c;美摄科技凭借其卓越的实时语音数字人解决方案&#xff0c;正引领着企业步入一个全新的交互时代。 美摄科技的实时语音数字人解决方案&#xff0c;是基于语音和…

小米消息队列的选型与实践

之前写了一篇关于消息队列的文章&#xff1a;《消息队列介绍与对比》&#xff0c;本文主要介绍消息队列在实际工作中的使用情况&#xff08;截止到2023年&#xff0c;因为我2023年离职了&#xff0c;后续的情况不了解了&#xff0c;哈哈&#xff09;。 市面上的多种消息队列都有…

STM32CubeMX实战教程: TIM6、TIM7 - 基本定时器

基本定时器的作用 基本定时器&#xff0c;主要用于实现定时和计数功能。作用包括&#xff1a; 定时功能&#xff1a;可以产生周期性的中断&#xff0c;用于实现定时任务。例如&#xff0c;可以设置一个定时器每隔一定时间&#xff08;如1秒&#xff09;产生一次中断&#xff0…

【图像版权】论文阅读:CRMW 图像隐写术+压缩算法

不可见水印 前言背景介绍ai大模型水印生成产物不可见水印CRMW 在保护深度神经网络模型知识产权方面与现有防御机制有何不同&#xff1f;使用图像隐写术和压缩算法为神经网络模型生成水印数据集有哪些优势&#xff1f;特征一致性训练如何发挥作用&#xff0c;将水印数据集嵌入到…

带大家做一个,易上手的水煮牛肉

今天带大家做川菜系中的 水煮牛肉 这个菜是比较费辣椒的 制作成本相对一般菜来说 会高一些 一块牛肉 泡水划冰 从超时买的干腐竹 切成小片 温水浸泡五分钟 泡软它 然后捞出来 去干水分 牛肉切片 尽量切薄一点 三瓣左右蒜 一块生姜 去皮切末 牛肉中下入 一个鸡蛋 小半勺…

【网站项目】136公司项目管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

大日志精选案例一:南京师范大学教育信息化安全实践

南京师范大学&#xff0c;由江苏省人民政府和中华人民共和国教育部共建&#xff0c;是国家“211工程”重点建设的江苏省属重点大学。在南京师范大学的教育信息化建设过程中&#xff0c;网络安全被视为重中之重。为了保障教学、科研和教务管理等信息化工作的安全进行&#xff0c…

每日一题——LeetCode1576.替换所有的问号

方法一 3个字母原则 把&#xff1f;替换为和他左右都不相等的字符&#xff0c;那么找3个字符abc&#xff0c;&#xff1f;总能替换为abc中的一个字符&#xff0c;遍历字符串找到所有&#xff1f;&#xff0c;再遍历abc把&#xff1f;替换为abc中的一个字符 var modifyString …

产品营销展示型wordpress外贸网站模板

工艺品wordpress外贸主题 简约大气的wordpress外贸主题&#xff0c;适合做工艺品进出品外贸的公司官网使用。 https://www.jianzhanpress.com/?p5377 餐饮设备wordpress外贸主题 简洁的wordpress外贸主题&#xff0c;适合食品机械、餐饮设备公司使用。 https://www.jianzh…

Redis 由浅入深 (7) - 集群操作手册

目录 Redis运维查询命令登录redis集群&#xff08;登录任意一台即可&#xff09;查询redis集群信息&#xff08;登录之后&#xff09;通过客户端执行命令&#xff08;redis-cli&#xff09;查询正则“pattern”所有的key redis 启动和创建的命令Redis 常用命令redis 手动命令设…

2024022701-信息安全(二)——密码学

密码学的基本概念 密码学(Cryptology)&#xff1a; 研究信息系统安全保密的科学。 密码编码学(Cryptography)&#xff1a; 研究对信息进行编码,实现对信息的隐蔽。 密码分析学(Cryptanalytics) &#xff1a; 研究加密消息的破译或消息的伪造。 消息被称为明文(Plaintext)。 用…