qsort的理解--加强对指针的理解

news2024/9/24 2:28:31

前言:前面我们学习指针变量数组指针变量函数指针变量;这些实际上都是变量实质上是在内存中开辟一块空间;而这些变量存储的都是地址。还有指针数组,函数指针数组,这指的是把多个地址存在数组中,要注意分别。


回调函数

在将qort之前,先来引入一个回调函数的概念。

回调函数就是一个通过函数指针调用的函数。

如果你把函数指针(地址)作为参数传给另一个函数,当这个指针被用来调用其所指向的函数,这就是回调函数。

 


 冒泡排序

冒泡排序的核心思想就是:俩俩相邻的元素进行比较。


问题与解答(递进式解决)

1. 问题如果我们有10个元素,要进行几次排序?

回答:首先,进行第一次排序,把最大的一个数字排在最右边然后就不用再和别的数字进行比较。最后一个数字不用比较,直接固定。所以要进行9次排序

 


2.问题那10个元素需要比较几次?

 回答:对于第一次排序,有10个元素,需要进行9对比较;第二次,最大数字固定好了,就9个元素,进行8对比较依次类推。


 

#include <stdio.h>
void bubble_sort(int arr[], int sz) //参数接收的元素的个数
{
	int i = 0;
	int j = 0;
	for (i = 0; i < sz - 1; i++) //循环n-1次
	{
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int bottle = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = bottle;
			}
		}
	}
}
void print_sort(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}


}

int main()
{
	int arr[10] = { 3,9,4,10,7,5,8,1,2, 6 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	print_sort(arr, sz);

	return 0;
}

 


 

qsort函数使用

qsort--库函数,它可以实现任意类型数据的排序。它用是快速排序。 默认升序

qsort函数底层使用了回调函数的方式 。

  1. 今天学习qsort的使用
  2. qsort函数的实现原理,模拟实现一下(冒泡排序的思想)。

先来看一下语法:

 

 void qsort(void* base, //base中存放的是待排序数组的第一个元素的地址

 size_t num, //num存放的是base指向的数组中的元素个数

 size_t size, //size是base指向的数组中一个元素的长度,单位是字节

 int (*compar)(const void*e1, const void*e2) //函数指针-指向了一个比较函数,这个比较函数是用来比较数组中的两个元素的

如果e1指向的元素大于e2指向的元素,那么函数返回>0的数字

如果e1指向的元素等于e2指向的元素,那么函数返回0

如果e1指向的元素小于e2指向的元素,那么函数返回<0的数字

 );


 qsort对整型的排序

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

Print(int* p, int len)
{
	int i = 0;
	for (i = 0; i < len; i++)
	{
		printf("%d ", *(p + i));
		

	}
}

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

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


 qsort对结构体的排序

struct Stu
{
	char name[200];
	int age;
};

int cmp_stu_by_name(const void* e1, const void* e2)
{
	return strcmp((*(struct Stu*)e1).name, (*(struct Stu*)e2).name);
}

int main()
{

	struct Stu s[3] = { {"zhangsan", 25 }, {"lisi", 98 }, {"wangwu", 11 } };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
	return 0;
}

 


  如图,我们可以知道qort默认排序是升序,只需要写一个比较函数它就能给出排序的结果


 qsort函数的实现原理,模拟实现一下(冒泡排序的思想)。

int main()
{
	test();
	return 0;
}

 通过函数调用实现复杂的逻辑

void test()
{
	int arr[] = { 3,2,6,5,8,4,10,9,7 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), compare);
	Print(arr, sz);
}

 

void bubble_sort(void* base, size_t sz, size_t size, int (*pf)(const void* e1, const void* e2))
{
	int i = 0;
	int j = 0;
	for (i = 0; i < sz - 1; i++)
	{
		for (j = 0; j < sz - i - 1; j++)
		{
			//arr[j] > arr[j + 1];
			if (pf((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
			{
				swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}

 首先,参数是void,因为不知道传过来的参数是什么,所以用void接收。接下来,把传过来的数据强制类型转换成为字符指针类型,这样每个字节的内容都不会遗漏。

当进入pf函数的时候,就会指向比较函数,这就是回调函数。

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

当符合判断条件的时候,就会进行字节交换

void swap(char* p, char* p2, size_t size)
{
	int i = 0;
	for (i = 0; i < size; i++)
	{
		char tmp = *p;
		*p = *p2;
		*p2 = tmp;
		p++;
		p2++;
	}
}

 接下来,看一下整体的代码。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void swap(char* p, char* p2, size_t size)
{
	int i = 0;
	for (i = 0; i < size; i++)
	{
		char tmp = *p;
		*p = *p2;
		*p2 = tmp;
		p++;
		p2++;
	}
}

void bubble_sort(void* base, size_t sz, size_t size, int (*pf)(const void* e1, const void* e2))
{
	int i = 0;
	int j = 0;
	for (i = 0; i < sz - 1; i++)
	{
		for (j = 0; j < sz - i - 1; j++)
		{
			//arr[j] > arr[j + 1];
			if (pf((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
			{
				swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}

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

void test()
{
	int arr[] = { 3,2,6,5,8,4,10,9,7 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), compare);
	Print(arr, sz);
}

int main()
{
	test();
	return 0;
}

 

希望对你有帮助,喜欢的点个赞 。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

相关文章

AIGC大模型扩图:Sanster/IOPaint(4)

AIGC大模型扩图&#xff1a;Sanster/IOPaint&#xff08;4&#xff09; 用大模型实现AI扩大一张图的周边区域&#xff0c;变得更大&#xff0c;当然必须契合原图&#xff0c;和原图浑然一体。 1、这次模型换用 Sanster/PowerPaint-V1-stable-diffusion-inpainting 启动&#xf…

文件对比工具--BeyondCompare

&#x1f496;简介 Beyond Compare 是一款功能强大的文件和文件夹比较工具&#xff0c;由Scooter Software开发。它可以帮助用户轻松地比较文件和文件夹的差异&#xff0c;并且可以合并变化、同步文件以及备份重要数据 &#x1f4bb;环境 windows &#x1f4d6;版本 Beyon…

RocketMQ安装与使用

什么是消息中间件 消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流&#xff0c;并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型&#xff0c;它可以在分布式环境下扩展进程间的通信。对于消息中间件&#xff0c;常见的角色大致也就有Prod…

OpenCV高阶操作

在图像处理与计算机视觉领域&#xff0c;OpenCV&#xff08;Open Source Computer Vision Library&#xff09;无疑是最为强大且广泛使用的工具之一。从基础的图像读取、 1.图片的上下&#xff0c;采样 下采样&#xff08;Downsampling&#xff09; 下采样通常用于减小图像的…

日志相关知识

1.作用 a.为了代替System.out.println()&#xff0c;可以定义格式&#xff0c;重定向文件等。 b.可以存档&#xff0c;便于追踪问题。 c.可以按级别分类&#xff0c;便于打开或关闭某些级别。 d.可以根据配置文件调整日志&#xff0c;无需修改代码。 …

如何逆转Instagram账号流量减少?实用技巧分享

Instagram作为全球十大社媒之一&#xff0c;不仅是个人分享生活的平台&#xff0c;还是跨境卖家进行宣传推广和客户开发的关键工具。在运营Instagram的过程中&#xff0c;稍有不慎就容易出现账号被限流的情况&#xff0c;对于账号状态和运营工作的进行都十分不利。 一、如何判断…

图片预览、拖拽和缩放组件分享

业务场景 项目中不需要点击小图然后展示大图&#xff0c;类似于elementui中的Image图片组件。适用于直接展示大图&#xff0c;支持拖拽和缩放的场景&#xff0c;比如&#xff1a;用户需要比对两种数据的图片展示&#xff0c;左右两侧进行展示。 效果图 使用方式 在components…

宏任务和微任务+超全面试真题

概念 微任务和宏任务是在异步编程中经常使用的概念&#xff0c;用于管理任务的执行顺序和优先级。 宏任务&#xff1a;setTimeout, setInterval&#xff0c;I/O 操作和 UI 渲染等。微任务&#xff1a; Promise 回调、async/await等 微任务通常比宏任务具有更高的优先级。 执…

S7-1500替代S7-300全解析系列

硬件篇上 01 概述工控人加入PLC工业自动化精英社群 2022年十月初的时候&#xff0c;想必工控圈的小伙伴们都被S7-300系列即将于2023年10月1日退市的消息刷屏了吧&#xff1f;倒退到2020年的10月1日&#xff0c;同样伴随我们多年的ET200S系列也已经悄无声息地退市了。在感叹经…

GEE 将本地 GeoJSON 文件上传到谷歌资产

在地理信息系统&#xff08;GIS&#xff09;领域&#xff0c;Google Earth Engine&#xff08;GEE&#xff09;是一个强大的平台&#xff0c;它允许用户处理和分析大规模地理空间数据。本文将介绍如何使用 Python 脚本批量上传本地 GeoJSON 文件到 GEE 资产存储&#xff0c;这对…

Qt (16)【Qt 事件 —— Qt 事件简介 | 如何重写相关的 Event 函数】

阅读导航 引言一、事件介绍二、如何重写相关的 Event 函数1. 事件的处理简介2. 示例重写鼠标相关的 Event 函数&#xff08;1&#xff09;新建Qt项目&#xff0c;设计UI文件&#xff08;2&#xff09;新添加MyLabel类&#xff08;3&#xff09;重写enterEvent()方法和leaveEven…

分享一个爬虫数据挖掘 农村产权交易数据可视化平台 数据分析大数据 Java、python双版(源码、调试、LW、开题、PPT)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人 八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题可以一起交流&…

形式向好、成本较低、可拓展性较高的名厨亮灶开源了。

简介 AI视频监控平台, 是一款功能强大且简单易用的实时算法视频监控系统。愿景在最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;减少企业级应用约 95%的开发成本&#xff0c;在强大视频算法加…

建筑业首个通过算法备案的大模型发布

建筑业首个通过算法备案的大模型发布 9月10日上午&#xff0c;上海建工四建集团与中国建筑出版传媒有限公司携手推出了Construction-GPT PRO版&#xff0c;这是一款专为建筑行业设计的施工知识大模型。该模型能够理解和生成长达8000字符的内容&#xff0c;其回答速度达到毫秒级…

LLM大模型学习:NLP三大特征抽取器(CNN/RNN/TF)

NLP三大特征抽取器&#xff08;CNN/RNN/TF&#xff09; 结论&#xff1a;RNN已经基本完成它的历史使命&#xff0c;将来会逐步退出历史舞台&#xff1b;CNN如果改造得当&#xff0c;将来还是有希望有自己在NLP领域的一席之地&#xff1b;而Transformer明显会很快成为NLP里担当…

Linux 信息安全:构建坚固的防御体系

摘要&#xff1a; 本文围绕 Linux 信息安全展开。阐述了 Linux 在信息技术中的重要地位&#xff0c;强调信息安全的重要性以及 Linux 信息安全面临复杂网络环境、演变攻击手段与内部威胁等挑战。详细介绍了 Linux 系统的安全架构与机制&#xff0c;包括用户与权限管理、文件系统…

Hexo框架学习——从安装到配置

第一章 Hexo入门 Hexo 是一个快速、简洁且高效的博客框架。 1.1 Hexo的下载与安装 1.1.1 Hexo下载 在下载Hexo之前&#xff0c;我们需要确保电脑上已经安装好以下软件&#xff1a; Node.js (Node.js 版本需不低于 10.13&#xff0c;建议使用 Node.js 12.0 及以上版本) Git…

你真的懂吗系列——串口通信

你真的懂吗 文章目录 你真的懂吗前言二、什么是串口通信二、STM32的串口三、什么是数据通信 前言 串口通信是一种设备间常用的串行通信方式&#xff0c;串口按位&#xff08;bit&#xff09;发送和接收字节。尽管比字节&#xff08;byte&#xff09;的串行通信慢&#xff0c;但…

机器学习算法-决策树算法

文章目录 什么是决策树&#xff1f;决策树的基本概念决策树的构建过程决策树的优缺点优点&#xff1a;缺点&#xff1a; 决策树的优化决策树的应用决策树的实现工具 特征选择准则1. 信息增益&#xff08;Information Gain&#xff09;计算公式&#xff1a;熵&#xff08;Entrop…

ubuntu20.4安装Qt5.15.2

ubantu20.4镜像下载地址&#xff1a; https://releases.ubuntu.com/focal/ubuntu-20.04.6-desktop-amd64.iso Qt5.15.2下载地址&#xff1a; https://download.qt.io/official_releases/online_installers/ 安装步骤 1、进入地址后选择对应安装包&#xff0c;我这是ubuntu…