模拟实现qsort()

news2024/11/25 11:46:50

𝙉𝙞𝙘𝙚!!👏🏻‧✧̣̥̇‧✦👏🏻‧✧̣̥̇‧✦ 👏🏻‧✧̣̥̇:Solitary-walk

      ⸝⋆   ━━━┓
     - 个性标签 - :来于“云”的“羽球人”。 Talk is cheap. Show me the code
┗━━━━━━━  ➴ ⷯ

本人座右铭 :   欲达高峰,必忍其痛;欲戴王冠,必承其重。

👑💎💎👑💎💎👑 
💎💎💎自💎💎💎
💎💎💎信💎💎💎
👑💎💎 💎💎👑    希望在看完我的此篇博客后可以对你有帮助哟

👑👑💎💎💎👑👑   此外,希望各位大佬们在看完后,可以互赞互关一下,看到必回
👑👑👑💎👑👑👑    

时隔多日,重出江湖! 今日给大家 share  一个关于如何实现qsort()

目录


一· 前言

二.qsort()函数的介绍

三· 函数模拟实现

 

首先想要实现此函数的模拟,我们就必须先了解qsort()

1.qsort()函数介绍

函数返回值:

 看不懂,木有关系,接下来我逐一解释

 

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

第一个参数void* base:指向要比较首元素的地址,注意因为不知道要比较数据的类型,所以这里是void*

第二个参数:size_t num,所比较数组的元素 个数

第三个参数:size_t size 每个元素 所占字节的大小

第四个参数:int (*compar)(const void*,const void*)  是一个函数指针,这是用户自己设计的一个函数,用来比较元素大小

 2.qsort()的初步使用

用此函数实现对数据的快速排序

数组:int arr[ ] = { 2,3,1,6,5,4,7,8,9,10 };

 思路:我们用户需要自己写一个函数来实现元素比较大小的

注意此函数的返回类型必须是int

其次我们需要传入2个指针

函数的形参必须是:(const void* p1, const void* p2)

完整版代码:

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

int  cmp(const void* p1, const void* p2)
{
	return (*(int*)p1) - (*(int*)p2);//没有必要进行大小比较,直接做差即可
}
void Print(int arr[], int sz)
	{
	int i = 0;
	for(i = 0;i < sz;i++)
	{
		printf("%d ", arr[i]);
	}
}int main()
{
	int arr[] = { 2,3,1,6,5,4,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort( arr, sz, sizeof(int), cmp);
	//qsort()有4个参数:待排序数组首元素地址,待排序元素个数,每个元素的大小,函数的地址(函数指针)
	Print(arr, sz);
	return 0;
}
 3.模拟实现

这里我们借助冒泡排序的思想,来模拟实现

所以我们核心逻辑还是双层for循环

那么我们就需要考虑以下问题:

1)如何从指定的数据类型(int)来实现对任意数据类型的比较?

===》这里写成 void*

2)2相邻元素也不能直接进行比较,因为数据具体类型我们是未知的

===》这里我们借助函数指针来实现队任意数据类型比较

 注意对于void*类型指针不能直接解引用,也不能直接进行指针运算

这里我们强转成char*类型指针,可以一个字节一个字节进行比较

这里我们需要把下标为j所对应元素地址传过去:又因为每个数据所占字节我们已知:size

所以下标为 j 所对应元素地址:(char*)base + j * size

同上:下标为 j+1 所对应元素地址:(char*)base + (j+1) * size

void Qsort(void* base, int num, int size, int (*cmp)(const void* p1, const  void* p2))
{

	for (int i = 0; i < num-1; i++)//确定一共进行多少趟
	{
		//一趟排序 需要交换的对数
		for (int j = 0; j < num - 1 - i; j++)
		{
			//默认是按升序进行排列
			if (cmp((char*)base + j * size, (char*)base + (j + 1) * size ) > 0)//这里必须写上>0

			{
				//进行交换
				Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);//在这里必须把要比较元素大小传过去
			}
		}
	}
}

 接下来就是如何实现2元素交换?

这里我们是一个字节一个字节来进行交换的

 

 

void Swap(char* p1, char* p2, int size)
{
	//注意这里是一个字节一个字节进行交换
	/*
	char* tmp = NULL;
	for (int i = 0; i < size; i++)
	{
	      以下只是改变了指针的位置,并没有实现我数据 的交换,注意交换你本质是内容交换,所以需要先解引用
		tmp = p1;
		p1 = p2;
		p2 = tmp;
		p1++, p2++;
	}*/
	//正确代码
	char tmp = 0;
	for (int i = 0; i < size; i++)
	{
		tmp = *p1;
		*p1 = *p2;
		*p2 = tmp;
		p1++, p2++;
	}
	

}

 

 qsort()完整版代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//                                   以冒泡排序的思想模拟实现 qsort快速排序   注意这里用户需要根据自己需要写一个比较函数
//需要解决以下 问题:1) 实现对各种数据类型的模拟        2)对于2个元素的交换不仅仅是int类型数据    


void Swap(char* p1, char* p2, int size)
{
	//注意这里是一个字节一个字节进行交换
	/*
	char* tmp = NULL;
	for (int i = 0; i < size; i++)
	{
	      以下只是改变了指针的位置,并没有实现我数据 的交换,注意交换你本质是内容交换,所以需要先解引用
		tmp = p1;
		p1 = p2;
		p2 = tmp;
		p1++, p2++;
	}*/
	//正确代码
	char tmp = 0;
	for (int i = 0; i < size; i++)
	{
		tmp = *p1;
		*p1 = *p2;
		*p2 = tmp;
		p1++, p2++;
	}
	

}
void Qsort(void* base, int num, int size, int (*cmp)(const void* p1, const  void* p2))
{

	for (int i = 0; i < num-1; i++)//确定一共进行多少趟
	{
		//一趟排序 需要交换的对数
		for (int j = 0; j < num - 1 - i; j++)
		{
			//默认是按升序进行排列
			if (cmp((char*)base + j * size, (char*)base + (j + 1) * size ) > 0)//这里必须写上>0

			{
				//进行交换
				Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);//在这里必须把要比较元素大小传过去
			}
		}
	}
}

int  cmp(const void*p1, const  void*p2)//用户自己设计的
{
	return (*(int*)p1) - (*(int*)p2);
}
void Print(int* p, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *p);
		p++;
	}
}
int main()
{
	int arr[] = { 7,4,1,2,5,8,3,6,9,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	Qsort(arr, sz, sizeof(arr[0]), cmp);
	Print(arr, sz);
  	return 0;
}

 运行结果:

 ok~~以上就是今日我要为各位老铁的分享,要是感觉还不错的话,点个赞,互关一下呗

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

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

相关文章

24年PMP考试如何安排?怎么备考?

24年pmp考试不出意外的话就是3、6、9、12月了。&#xff08;PMP干货文末&#xff09; PMP如何备考 24年的PMP考试还有3个多月&#xff0c;现在开始备考&#xff0c;再合适不过&#xff0c;我这里提出四点备考建议&#xff0c;希望能帮到备考的大家&#xff1a; 一、要看的三份…

openGauss学习笔记-119 openGauss 数据库管理-设置数据库审计-设置文件权限安全策略

文章目录 openGauss学习笔记-119 openGauss 数据库管理-设置数据库审计-设置文件权限安全策略119.1 背景信息119.2 数据库程序目录及文件权限119.3 建议 openGauss学习笔记-119 openGauss 数据库管理-设置数据库审计-设置文件权限安全策略 119.1 背景信息 数据库在安装过程中…

Python算法:动态规划解决0-1背包问题

动态规划&#xff08;Dynamic Programming&#xff0c;简称DP&#xff09;是一种在数学、计算机科学和经济学中使用的&#xff0c;通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题&#xff0c;它能够将问题…

js将图片文件转为base64格式

/***图片文件转换成BASE64字符串&#xff0c;异步任务*param {File} file图片文件对象*return {String} BASE64字符串*/ const getBase64 (file: File) > new Promise((resolve: (url: string) > void, reject) > {const reader new FileReader();reader.onload ()…

一款基于.Net开发、开源、支持多平台云存储文件管理器

目录 01 项目简介02 项目代码03 部分截图04 项目地址 今天给大家推荐一款基于基于.Net开发、开源的&#xff0c;支持多平台的云存储文件管理器。 01 项目简介 Camelotia是一款云存储文件管理器&#xff0c;基于.Net UI框架和ReactiveUI框架开发的&#xff0c;目前支持的平台有…

GTDB-Tk基因组物种注释

文章目录 安装GTDB-Tk v2.3.3 and gtdbtk_r214_data.tar.gzGTDB-Tk v2.1.1 and gtdbtk_r207_v2_data.tar.gzGTDB-Tk 1.3.0 数据库classify_wf 物种注释一步使用分步使用批量dRep以及GTDB注释注意报错由于基因组存在重复id导致Pfam报错 查看已经安装的数据库iTOL可视化问题pplac…

时间序列预测(1) — 时间序列预测研究综述

目录 1 什么是时间序列预测? 2 时间序列预测的应用场景与分类 3 时间序列数据的特性 4 时序预测评价指标 5 基于深度学习的时间序列预测方法 5.1 卷积神经网络 5.2 循环神经网络 5.3 Transformer类模型 1 什么是时间序列预测? 时间序列&#xff1a;指对某种事物发展…

LabVIEW在OPC中使用基金会现场总线

LabVIEW在OPC中使用基金会现场总线 本文讨论了如何使用开放的OPC&#xff08;用于过程控制的OLE&#xff09;接口访问基金会现场总线网络和设备。 NI-FBUS通信管理器随附了一个OPC数据访问服务器。 &#xff08;NI-FBUS Configurator自动包含NI-FBUS通信管理器。&#xff09…

JVM-虚拟机的故障处理与调优案例分析

案例1&#xff1a;大内存硬件上的程序部署策略 一个15万PV/日左右的在线文档类型网站最近更换了硬件系统&#xff0c;服务器的硬件为四路志强处理器、16GB物理内存&#xff0c;操作系统为64位CentOS 5.4&#xff0c;Resin作为Web服务器。整个服务器暂时没有部署别的应用&#…

深度学习pytorch之hub模块

pytorchhub模块里面有很多模型 https://pytorch.org/hub/ github网址&#xff1a;https://github.com/pytorch/pytorch import torch model torch.hub.load(pytorch/vision:v0.10.0, fcn_resnet50, pretrainedTrue) # or # model torch.hub.load(pytorch/vision:v0.10.0, fc…

Linux C语言进阶-D15递归函数和函数指针

递归函数 指一个函数的函数体中直接或间接调用了该函数本身 执行过程分为两个过程&#xff1a; 递推过程&#xff1a;从原问题出发&#xff0c;按递归公式递推从未知到已知&#xff0c;最终达到递推终止条件 回归阶段&#xff1a;按递归终止条件求出结果&#xff0c;逆向逐步…

Linux 基本语句_10_进程

进程和程序的区别&#xff1a; 程序是一段静态的代码&#xff0c;是保存在非易失储存器上的制令和数据的有序集合&#xff0c;没有任何执行的概念&#xff1b;而进程是一个动态的概念&#xff0c;它是程序的一次执行过程&#xff0c;包括了动态创建、调度、执行和消亡的整个过程…

Unity中Shader雾效的原理

文章目录 前言一、我们先看一下现实中的雾二、雾效的混合公式最终的颜色 lerp(雾效颜色&#xff0c;物体颜色&#xff0c;雾效混合因子) 三、雾效的衰减1、FOG_LINEAR&#xff08;线性雾衰减&#xff09;2、FOG_EXP(指数雾衰减1)3、FOG_EXP(指数雾衰减2) 前言 Unity中Shader雾…

linux espeak语音tts;pyttsx3 ubuntu使用

整体使用espeak声音很机械不太自然 1、linux espeak语音tts 安装&#xff1a; sudo apt install espeak使用&#xff1a; #中文男声 espeak -v zh 你好 #中文女声 espeak -v zhf3 你好 #粤语男声 espeak -v zhy 你好注意&#xff1a;espeak -v zh 你好 &#xff08;Full d…

由于找不到msvcp140_1.dll无法继续执行代码怎么解决

msvcp140_1.dll是Microsoft Visual C库文件之一&#xff0c;丢失后可能导致程序无法正常运行。以下是一些关于解决msvcp140_1.dll丢失问题的方法以及丢失原因的介绍。 一、msvcp140_1.dll是什么&#xff1f; 作用&#xff1a;msvcp140_1.dll是Microsoft Visual C库文件&#…

Linux开发工具之软件包管理器 yum

文章目录 1.了解yum1.1yum的介绍1.2yum的作用 2.了解软件包3.yum三板斧3.1查看软件包3.2安装软件3.3移除软件3.4centos7有趣的软件 1.了解yum 1.1yum的介绍 一般原生的Linux系统&#xff0c;内置的下载链接基本都是配套的国外的网址 上图中的软件发布平台是国外的 因为我们国家…

LeetCode算法题解(回溯,难点)|LeetCode37. 解数独

LeetCode37. 解数独 题目链接&#xff1a;37. 解数独 题目描述&#xff1a; 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分…

【获取cookie的真实到期时间】

获取cookie的真实到期时间 from datetime import datetime print(datetime.fromtimestamp(1734148606))

客户服务中可能造成客户流失的 5 个错误

在商业活动中&#xff0c;客户服务是影响企业的重要因素之一。一位不满意的客户可能会带来不良的口碑&#xff0c;影响其他潜在客户的购买决策&#xff0c;甚至导致客户流失。因此&#xff0c;提高客户满意度和降低客户流失率成为企业非常关注的问题。这篇文章将从五个方面&…

安卓编译命令mm和mmm的区别(mm编译当前工作目录,mmm可编译指定目录)

文章目录 1. mm示例 2. mmm示例 注意 在Android操作系统的源代码编译过程中&#xff0c; mm和 mmm是两个用于构建部分代码的常用命令。它们都属于Android build system提供的命令集合&#xff0c;但用途略有不同&#xff1a; 1. mm mm&#xff08;make module&#xff09;命…