万能排序qsort(快排)or万能冒泡

C语言qsort函数详解:从原理到实战的通用排序指南 排序是数据处理与算法设计中的基础操作,其核心目标是将数据集合按照特定规则重新排列。从经典的冒泡排序、快速排序等算法原理出发,排序的价值在于提升数据检索效率、优化存储结构,广泛应用于数据库索引、游戏排行榜、数据分析等场景。C标准库中的qsort函数通过通用指针和回调函数机制,实现了对任意数据类型的快速排序。本文以qsort函数为焦点,深入解析其函数原型、快速排序算法原理,并通过整型数组、结构体数组及指针数组等实战案例,演示如何编写安全的比较函数、规避整数溢出等常见陷阱。掌握qsort不仅能提升C语言编程效率, 阅读详情

目录

前言:

Qsort函数

"万能"冒泡排序

总结

前言:

在c语言中排序的方式有很多种,哪有没有一种排序可以应对绝大部分情况的排序呢,在c语言中的内置函数qsort就是一种"万能排序",那么借用他的逻辑还可以衍生出万能"冒泡排序".

Qsort函数:  头文件为 <stdlib.h>

void qsort(void *base, int nelem, unsigned int width, int (* pfCompare)(const void *,const void *))

qsort函数的底层逻辑是快排,所以时间复杂度与快排相同。上面为qsort的使用方式,我会为大家用小"栗子"来讲述如何使用和操作.

 void qsort :显然qsort函数的返回值是void 

 void *base:是将要进行排序数组

 int nelem :将排序的数组长度传过去

 unsigned int width :待排序的数组每个元素的大小

 int (* pfCompare)(const void *,const void *): 往简单的说就是使用者自己提供的比较函数

#include<stdlib.h>
int main()
{
	int arr[] = { 2,6,1,4,7,9,12,8,3 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cap_int);
	return 0;
}

​

 这里讲一下 sz ,sizeof(arr)是整个数组的大小,那么sizeof(arr[0])就是数组元素中第一个元素的大小,那么 sz 其实就代表了 数组 的宽度.

那么这个时候cap_int怎么写呢(这个需要用户自己提供):如下

int cap_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}

①-->为什么cap_int 接收时候需要const void *而不能使用其他的来接收呢?

这是因为我们void好像一个垃圾桶,他什么类型的数据他都接收保存,这样就大大的增强了代码的通用性质.

②-->在return 时将void*强制转化成int*

③-->cap_int 形参接收的到底是什么的值呢?

形参中接收的是数组arr中带比较的两个数,譬如e1是arr[0]的地址,e2是arr[1]的地址,而强制转化的作用就是让接受到的两个数据可以相减.

④-->这么设置是qsort的升序,而降序只需要更改成 return *(int*)e1-*(int*)e2 ;

上面讲述的是使用qsort给整形数组排序,那么接下来我们来给结构体排排;

struct stu
{
	char name[20];
	int year; 
};
int cam_stu_by_year(const void* e1, const void* e2)
{
	return ((struct stu*)e1)->year - ((struct stu*)e2)->year;
}
void text1()
{
	struct stu arr[3] = { { "张三",8 },{"李四",6},{"王五",1} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cam_stu_by_year);
}

这里的sizeof就有奇效了!

道理就和上面的一模一样!

利用这种思想我们来试试万能冒泡!

"万能"冒泡排序

底层逻辑还是冒泡排序,所以时间复杂度还是O(n^2),但是它稳定(doge)

先来写一个冒泡:

int main()
{
	int i,j;
	int arr[] = { 9,7,5,4,2,1 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (i = 0; i < sz - 1; i++)
	{
		for (j = 0; j < sz - i - 1; j++)
		{
			if (arr[j] > arr[j+1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
	return 0;
}

冒泡的外层for循环决定趟数,内存for循环来比较数组中两个数的值,但这种冒泡排序并不能比较非整形数据.

那么我们就要创造一个万能的冒泡排序,也是因此bubble_sort的形参就很有考究了

int cap_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}
void bubble_sort(void* base, int num, int width, int* (cmp)(const void* e1, const void* e2))
{
	int i, j;
	for (i = 0; i < num-1; i++)
	{
		for (j = 0; j < num - i - 1; 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 text4()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cap_int);
	int i;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}

}

还是老规矩,*base是待排序数组,num是整个数组大小,width是每个数据的大小(宽度)

*(cmp)就是函数指针了,他是由我们用户来自定义的也是用来判断传参数据的大小,他的作用和cap_int 一样,就是换了个名字使代码易读。

让我们理解一下这个代码 : cmp((char*)base + j * width, (char*)base + (j + 1) * width)

cmp就是函数cap_int,那么函数cap_int的作用就是比较两个参数的大小.

Q1:那么为什么要把参数都强制转化成char(*)?

char(*)在内存中占用一个字节是int*是四个字节

char*是精度最高的,如果你强制转化成int(*),在本题中是没有问题,但是如果比较7个字节为width的数据,那么int(*)的准确度显然不够高

Q2:(char*)base + j * width这段话怎么解释?

如果j=0 那么(char*)base + j * width就等于(char*)base,指向数组中第一个元素

如果j=1 那么(char*)base + j * width就指向了数组中第二个元素了

最后一步就是实现Swap函数了,先上代码:

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

 这时候就突出强调了转化成char(*)的重要性了,如果是int(*)那么++将会跳过四个字节

swap函数在内存中是这么操作:

把arr[1](值为9)和arr[2](值为8)交换

09 00 00 00 和 08 00 00 00交换时就是将09和08交换,再继续将后面的数组交换

02 03 04 05 和 06 07 08 09交换就是将02和06、03和07、04和08、05和09交换

从而达到交换值的效果

总结

qsort和万能冒泡的思想都是一样的,多看看我相信一定能看懂,对于对指针有一定基础的人理解起来应该是更容易的,void*是一个垃圾桶他可以接受任意类型数据的指针,这也是能实现"万能"的原因

C语言qsort函数深度解析:从原理到实战避坑指南 在C语言编程中,排序是数据处理的基础操作,其核心在于高效地比较和交换元素。快速排序算法通过分治策略,平均时间复杂度可达O(n log n),是泛型排序实现的经典选择。C标准库中的qsort函数正是这一思想的体现,它通过void指针和回调函数机制,实现了对任意数据类型的排序,极大提升了代码的复用性和可移植性。理解qsort的关键在于掌握其比较函数的编写,这直接决定了排序的规则与正确性。在实际工程中,无论是嵌入式系统、操作系统内核开发,还是需要高可移植性的C项目,qsort都是不可或缺的工具。本文将深入剖析qs 阅读详情

相关推荐

AlphaDev用强化学习在汇编层优化排序算法

排序算法是计算机科学的基础概念,其本质是在确定性约束下实现元素的有序映射;传统分析聚焦于抽象时间复杂度,但真实性能取决于指令级执行效率、分支预测、缓存行为等硬件特性;强化学习自动编程为此提供了新范式——通过在精简指令集(如RISC-V)上建模状态-动作空间,并以周期数、指令数、内存访问为奖励信号,AI可直接生成经形式化验证的最优小规模排序原语;这类技术已落地LLVM与嵌入式场景,显著提升标准库原子操作性能;AlphaDev正是这一方向的代表性实践,它不替代高层逻辑开发,而是重构底层‘零开销抽象’的实现方式。

HJ921004的博客 297

C语言库函数——快排函数qsort()

qsort包含在头文件中,根据你给出的比较函数进行快速排序,通过指针移动实现排序,排序之后的结果仍然放在原数组中,使用qsort函数必须自己写一个比较函数。注意:qsort()函数无返回值。

weixin_73141021的博客 1827

Sentinel2 哨兵2数据下载方法(USGS)-史上最全讲解

本文讲述了从USGS官网下载Sentinel2的方法。主要包括USGS官网的注册和下载流程,以及选定研究区中所出现的问题、解决办法。

xiatiandexia123的博客 6万+

快排函数 -- qsort函数(Quick Sort)

👁️qsort()函数是C语言库函数中的一种排序算法,其用到的排序思想是快速排序(quicksort)。它的独特之处在于可以排序任意类型的数组元素(整型、浮点型、字符串和结构体类型)可以参考一下 cplusplus 中的资料👇🔴使用qsort来排序整型数组,这里就由qsort函数的使用者来提供一个比较函数(自定义函数),这个比较函数能够比较2个整数的大小🔴。

weixin_74937672的博客 5818

基于车牌识别的停车收费系统的设计与实现(源码+开题)

本系统(程序源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景: 随着城市化进程的加速和汽车保有量的增加,停车难成为了一个普遍存在的问题。传统的停车收费方式存在着效率低下、管理混乱等问题。因此,开发一款基于车牌识别的停车收费系统具有重要的现实意义。研究意义: 基于车牌识别的停车收费系统可以有效地解决传统停车收费方式在效率和准确性方面的问题,提高停车服务的效率和质量。

迟限程序设计 1392

MATLAB/simulink电力系统之变压器仿真+变压器饱和仿真+空载变压器电流畸变原因及仿真+空载合闸励磁涌流仿真+simulink免费仿真资源

单相变压器空载运行时,原边电流主要用来产生主磁场,而电路损耗和铁芯损耗很小,因此即使外加电压很大,空载电流仍然很小。如果想观察某个相对磁导率下电感系数的数值,可以在程序中增加这样的语句,比如,在程序中end语句之后,加上L(100),运行程序后就可以得到相对磁导率为 100时的电感系数值。在交流铁芯线圈中,当交变磁通按照正弦规律变化时,受到磁路饱和的影响,线圈中的电流会发生畸变,并成为尖顶波,这就是所谓的交流磁路电流畸变。需要指出,铁芯内的主磁通Ф可以通过空载时的副边电压从来测量,两者之间的数学关系,即。

m0_37724753的博客 4230

C语言——冒泡排序和qsort排序

这里需要注意的是,前面提到过,qsort可以对任意类型的数据进行排序,所以,qsort函数对于参数的类型的选择,使用void*进行表示,void*可以匹配任意类型的数据,但是,因为void*可以匹配任意类型的数据,所以在前面提到的不同类型指针的特殊性质,即指针和整数的加减以及指针的访问权限在void*指针上均不满足。所以,在书写比较函数的代码时,需要进一步将void*类型的数据,强制转换成被排序的数组的数据类型,例如,上面对int型的数据进行排序,则在书写比较函数时,需要将void*转为int*类型。

2301_76836325的博客 393

GAMES101作业3-遇到的各种问题及解决方法

记录在做作业3时遇到的一些坑!以及最后的解决办法。

qq_41835314的博客 6819

qsort()函数(快速排序)

快排函数-----qsort()

Lucky.Mr.Li的博客 2471

微信小程序内容安全审核:从API调用到工程化落地的全流程实践

内容安全是互联网应用开发中的基础性技术环节,尤其在用户生成内容(UGC)场景下,它直接关系到平台的合规性与用户体验。其核心原理通常结合了关键词过滤、自然语言处理(NLP)和计算机视觉(CV)等技术,通过AI模型对文本、图像、音频进行多维度风险识别。这项技术的价值在于,它不仅是满足监管要求的必要手段,更是构建健康社区生态、保护品牌声誉、实现产品长期稳定运营的基石,广泛应用于社交、电商、社区论坛等各类UGC平台。本文聚焦于微信小程序生态,深入剖析其官方提供的内容安全解决方案,详细解读如何将文本同步检测与多媒体异

weixin_28622215的博客 453

【DL经典回顾】距离度量大汇总(7-余弦距离(Cosine Distance))

余弦距离(Cosine Distance)衡量的是两个向量在方向上的差异性,而不是在大小上的差异。

悦学共鸣,温柔以待,汇聚光芒,共同成长 2579

排序 | 冒泡排序的优化与qsort快速排序

冒泡排序 冒泡排序 Bubble_Sort,是极为简单的一种排序算法。虽然效率差一点,但好在具有结构简单,容易理解,易于操作等优点。冒泡排序就是把小的元素往前调或者把大的元素往后调。在相邻的两个元素间比较,交换也发生在这两个元素之间。 冒泡排序是一种稳定排序算法,在排序后相同元素的前后顺序并没有改变。 相比于传统的冒泡排序,平均时间复杂度为O(n2),最好的时间复杂度为2,是一种效率不高的的排序。...

专注于C/C++/Linux领域创作 750

想在 Visual Studio Code 里进行 ABAP 开发,需要安装的扩展列表

安装完毕后,我们可以将 SAP 系统配置为 Visual Studio Code 连接的远程文件系统。为了连接到 SAP 系统,需要启用 ABAP 开发工具 (ADT) ICF 节点,这与 SAP Hana Studio 等工具使用的服务相同。打开 SAP GUI 并连接到目标系统,运行事务 SICF,然后激活 ADT_SRV 服务,如下所示。这启用了允许代码编辑器和 IDE 连接到 SAP 系统的服务。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 3123

排序算法还在手写?万能排序神器qsort函数,搞定90%笔试面试!

排序算法还在手写?万能排序神器qsort函数,搞定90%笔试面试!

萧邯嵌入式笔记 1161

Matplotlib之bar3d画3D柱状图

3D柱状图通常用于展示数据集中不同分类项的数据大小或数量。与普通的柱状图相比,3D柱状图更适合展示数据的三个维度 3D 柱状图 按行/列涂颜色 柱加阴影、描黑边 自定义座标轴名、刻度标签、范围

我走的每一步都算数 1122

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

用快排的思维模拟实现“万能“的冒泡排序--“Qsort“

1.先来看一看刚学习c语言时,那时我们写的冒泡排序 那时因为能力有限,把代码写死了,只能对整形的数组进行排序。 2.那么问题来了,以后想要对字符数组,浮点型数组,结构体数组进行排序的时候,我们应 该如何设计代码呢? 改进: 运用快速排序的思路(快排的函数:qsort) 参照优快云:qsort 解析: 参数1:void*类型的指针,可以接收任何类型的数组的地址; 参数2:接收数组的长度; 参数3:数组中一个元素的字节长度; 参数4:...

xaiobit_hl的博客 573

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

qsort函数

C语言中qsort函数

Jambo!的博客 1138

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

C语言qsort模拟实现:内存模型、迭代快排与嵌入式安全实践

qsort是C语言中理解泛型编程与内存操作的核心接口,其本质是基于void*指针的字节级内存搬运与分治排序。掌握其原理需深入理解指针算术(如char*强制转换)、size_t边界计算、栈式迭代替代递归等底层机制。在嵌入式开发中,qsort模拟实现直接关联栈空间控制、内存对齐安全、无malloc约束等关键工程能力;在算法学习中,它串联起partition划分、三数取中防退化、比较函数溢出防护等经典考点。本文以可落地的迭代快排实现为线索,覆盖从PTA练习题到CAN报文排序的真实场景,提供符合ASAM标准与MCU

weixin_30907935的博客 394

从qsort到通用排序引擎:C语言回调函数与泛型编程实践

在数据处理中,排序是基础且高频的操作,其核心目标是将数据元素按照特定规则高效组织。从经典的冒泡排序到快速排序,算法效率的差异源于不同的数据组织和比较策略。回调函数作为一种关键编程范式,允许将易变的比较逻辑从固定的排序框架中分离,这正是实现通用排序引擎的技术原理。通过函数指针,排序算法可以操作任意数据类型的内存块,而无需关心其具体结构,这种设计模式极大地提升了代码的复用性和灵活性,是泛型编程思想的典型体现。本文以C语言标准库qsort为蓝本,深入剖析了其利用void指针和比较函数实现通用排序的机制,并手把手指

weixin_34292402的博客 443

C语言qsort函数详解:从原理到实战,掌握万能排序技巧

在C语言程序开发中,排序是数据处理的基础操作,涉及算法效率、内存管理和数据类型处理等核心概念。快速排序算法因其平均时间复杂度优异而广泛应用,C标准库通过qsort函数将其封装为通用排序工具。该函数利用函数指针和void*类型实现泛型编程,将比较逻辑委托给用户自定义的回调函数,从而支持对整型、浮点型、字符串及复杂结构体等多种数据类型进行排序。其技术价值在于分离算法实现与数据比较逻辑,提供了高度优化且类型安全的排序方案。在数据结构操作、学生成绩管理、文件列表整理等应用场景中,qsort能显著提升开发效率与代码可

weixin_42116058的博客 282

【初识C语言】qsort 函数保姆级教程,搞定各种数据类型的排序

本文详细介绍了C语言标准库中的qsort函数,这是一个支持多种数据类型的通用快速排序工具。文章首先解析了qsort函数的4个核心参数:数组首地址、元素个数、元素大小和自定义比较函数。重点讲解了比较函数的编写规则,通过返回值决定排序顺序(负数表示正序,正数表示降序)。随后分类型展示了int、float/double、char以及字符串的排序实现方法,特别强调了浮点数比较时的精度问题处理技巧。最后还介绍了结构体数组的排序方式,帮助读者全面掌握qsort函数的使用技巧,实现高效便捷的数据排序。

2301_82161965的博客 1031

深入理解C语言qsort:从快速排序原理到手写泛型排序实现

排序算法是计算机科学的基础,快速排序因其平均O(n log n)的时间复杂度而广泛应用。其核心原理是分治策略,通过选取枢轴将数组划分为子序列递归排序。在C语言中,标准库的qsort函数通过泛型设计和回调函数机制,实现了对任意数据类型的排序,这体现了算法与数据分离的编程思想。理解其底层实现,尤其是函数指针和内存操作,对于掌握系统编程和性能优化至关重要。本文以快速排序和回调函数为切入点,通过手写my_qsort的实践,详细解析了分区算法、小数组优化等工程细节,并对比了标准库实现的性能与健壮性,帮助开发者深化对核

weixin_33226548的博客 214

排序类...

└── 分配排序类 (核心:利用“多关键字”分配和收集,不依赖比较) ←── 这里补上你问的“基数排序”│ └── 堆排序 (利用堆结构选最值) ←── 这里补上你问的“选择排序”├── 选择排序类 (核心:在待排序列中选出最值,放到最终位置)├── 交换排序类 (核心:通过比较并交换元素位置来排序)├── 插入排序类 (核心:将元素插入到已有序的序列中)│ └── 希尔排序 (本质:多次分组插入排序)│ ├── 简单选择排序 (直接选最值)│ ├── 直接插入排序。

qq_43519774的博客 299

【算法】常见基础算法

常见算法:双指针、滑动窗口、前缀和、二分、分治归并、分治快排、BFS、DFS、递归、回溯、FloodFill等

志之所趋,无远弗届,穷山距海,不能限也 1328

快速排序和qsort函数详解详解qsort函数

💕是非成败转头空,青山依旧在,几度夕阳红💕作者:Mylvzi文章主要内容:快速排序和qsort函数详解。

Mylvzi的博客 1135

qsort函数 - (Quick Sort)【快速排序的使用方法】

是c语言中一种用于排序的函数,这种方法也叫作快速排序法。它与冒泡排序不同,冒泡排序是一种算法,而qsort是c语言中编译器函数库自带的排序函数,存在于stdlib.h文件中。qsort函数可以根据使用者的不同需求快速的实现不同数据的排序。

小侯宝的博客 612
上一篇: 踏入c语言的世界
下一篇: 模拟实现字符串操作函数
Obto-
博客等级 码龄5年 721粉丝 58原创
评论 20
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Obto-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值