模拟实现qsort函数(采用冒泡的方式),超详细!!!

news2024/10/7 9:21:24

函数详解和使用

函数声明

void qsort (void* base, size_t num, size_t size,int (*cmp)(const void* e1,constvoid* e2));

头文件

stdlib.h

参数 

  • base-- 指向要排序的数组的第一个元素的指针。

  • num-- 由 base 指向的数组中元素的个数。

  • size-- 数组中每个元素的大小,以字节为单位。

  • cmp-- 用来比较两个元素的函数,即函数指针(回调函数)(qsort函数作者不知道我们具体比较的数组的类型,所以说我们要自己写这个用来比较的函数)

回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

compar参数

cmp参数指向一个比较两个元素的函数。比较函数的原型应该像下面这样。注意两个形参必须是const void *型,同时在调用cmp 函数(cmp实质为函数指针,这里称它所指向的函数也cmp)时,传入的实参也必须转换成const void *型。在compar函数内部会将const void *型转换成实际类型。

int cmp(const void *e1, const void *e2);

如果cmp返回值小于0(< 0),那么p1所指向元素会被排在p2所指向元素的左面;

如果cmp返回值等于0(= 0),那么p1所指向元素与p2所指向元素的顺序不确定;

如果cmp返回值大于0(> 0),那么p1所指向元素会被排在p2所指向元素的右面。

 

 引自:qsort_百度百科  qsort - C++ Reference

使用qsort函数对数组进行排序。

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include<stdlib.h>


void print_arr(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

int cmp_int(const void * e1,const void *e2)
{

	return(*(int*)e1 - *(int*)e2);
//因为我们要比较的数组是int类型的,我们把 void*类型指针强制转换成int* 类型,便于我们比较。
//这样我们拍出来的是升序
//如果将e1和e2位置交换排出来的就是降序了(return(*(int*)e2 - *(int*)e1))



}


void test2()
{
	int arr[] = {9,8,7,6,5,4,3,2,1,0};
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr,sz,sizeof(arr[0]),cmp_int);
//arr传递首元素的地址,com_int是我们自己写的比较函数。
	print_arr(arr,sz);
}

int main()
{
	test2();//数组
	return 0;
}

模拟实现qsort函数(采用冒泡的方式)

1.bubble_sort 中第一个参数毫无疑问是数组的地址,第二个参数和第三个参数则是要进行排序的数组的大小,和数组中每个元素的大小,以字节为单位。

2.第四个参数是我们自己定义的比较函数。

3.在 void bubble_sort 我们有不同的方式来收传递过来的参数。

4.两个循环没什么好说的,跟冒泡排序差不多。

5.内循环中if判断:qsort 接收地址的指针做成 void类型,是使其更加具有兼容性。

为了模拟其,我们将比较部分的指针强转成 char* 这样在比较的时候更加具有兼容性,是一个字节一个字节的比较。

cmp((char*)base + j * width, (char*)base + (j+1)* width) 这里我们把两个地址传过去,因为直到每个元素的大小(width)和首元素地址。(char*)base +j * width和(char*)base + (j+1)* width,便是相邻两个元素的地址了。

如果经过判断发现前一个元素大于后一个元素,这是就要进入if语句中,进行交换元素。我们需要向swap传递 需要交换元素的地址,以及元素的大小。让元素中的每个 “char” 都能交换。

指针所能解引用的单位越小,其越具有兼容性。能排序的类型越多。

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include<stdlib.h>


void print_arr(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

int cmp_int(const void * e1,const void *e2)
{

	return(*(int*)e1 - *(int*)e2);
}

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

		buf1++;
		buf2++;

	}
}

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

int main()
{
	test4(); // 模拟qsort (采用冒泡排序)
	return 0;
}

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

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

相关文章

高精度电压源的应用场合有哪些

高精度电压源是一种能够提供恒定、稳定电压输出的设备&#xff0c;被广泛应用于各种领域。高精度电压源是现代电力、通信、控制等领域中重要的测试仪器之一&#xff0c;其主要功能是提供稳定可靠的直流或交流电源&#xff0c;并具有高精度和高分辨率的特点。在实际应用中&#…

kotlin 解决构造函数兼容性问题

data class Person(private val head: String,val hand: String ) {} val p Person("head", "hand")Log.d("Alex", "Person $p") 打印结果&#xff1a; 2023-06-11 22:30:54.764 21840-21840 Alex com.example…

智能diy官网小程序至尊版v1.0.73+微信前端

&#x1f388; 限时活动领体验会员&#xff1a;可下载程序网创项目短视频素材 &#x1f388; &#x1f389; 有需要的朋友记得关赞评&#xff0c;文章底部来交流&#xff01;&#xff01;&#xff01; &#x1f389; ✨ 源码介绍 1、h5万*能页增加跳转小程序组件 2、功能链接弹…

智能工具Cursor安装和使用

一、Cursor介绍 Cursor.so是一个软件开发工具&#xff0c;是一个集成了 GPT的直接可以访问的&#xff0c;优秀而强大的智能AI代码生成工具&#xff0c;使用GPT-3.5免费。 它可以快速编写、编辑和聊天关于你的代码。它支持多种编程语言&#xff0c;如Python、Java、JavaScript等…

BootStrap文档

Bootstrap概念 ​ 1. 概念&#xff1a; 一个前端开发的框架&#xff0c;Bootstrap&#xff0c;来自 Twitter&#xff0c;是目前很受欢迎的前端框架。Bootstrap 是基于 HTML、CSS、JavaScript 的&#xff0c;它简洁灵活&#xff0c;使得 Web 开发更加快捷。 ​ 框架:一个半成品…

C++教程(06)——变量类型

C 变量类型 变量其实只不过是程序可操作的存储区的名称。C 中每个变量都有指定的类型&#xff0c;类型决定了变量存储的大小和布局&#xff0c;该范围内的值都可以存储在内存中&#xff0c;运算符可应用于变量上。 变量的名称可以由字母、数字和下划线字符组成。它必须以字母…

037_SS_SyncDiffusion: Coherent Montage via Synchronized Joint Diffusions

SyncDiffusion: Coherent Montage via Synchronized Joint Diffusions 1. Motivations & Arguments & Contributions 本文提出了一种即插即用的用Diffusion生成全景图的方法。 Diffusion模型通常只能生成固定大小的图像&#xff0c;为了生成分辨率比较高的全景图。现…

linux shell操作-基本脚本编写

文章目录 变量分支循环函数函数案例 变量 普通变量 声明变量&#xff0c;直接赋值&#xff0c;同python两边不能有空格‘’ 单引号表示纯字符“”双引号表示一个整体反引号表示操作命令末尾没有&#xff1b;号 # 直接赋值&#xff0c; namejack # 纯字符 pyCodeimport os\n…

Android进阶 四大组件的工作过程(一):Activity的工作过程

Android进阶 四大组件的工作过程&#xff08;一&#xff09;&#xff1a;Activity的工作过程 导语 本系列文章主要是来介绍Android中四大组件的工作过程的&#xff0c;参照书籍为Android进阶解密&#xff0c;主要还是会涉及到源码的阅读。关于源码&#xff0c;大家可以到Andro…

Linux - 第25节 - Linux高级IO(三)

目录 1.Reactor模式 1.1.Reactor模式的定义 1.2.Reactor模式的角色构成 1.3.Reactor模式的工作流程 2.epoll ET服务器&#xff08;Reactor模式&#xff09; 2.1.epoll ET服务器源代码 2.2.epoll ET服务器源代码讲解 2.2.1.设计思路 2.2.2.Connection结构 2.2.3.TcpSe…

VMware Fusion网络配置 - 设置Nat静态IP

准备把主力机器从ThinkPad T460P替换到MacMini上, MacOS版本: 10.15.7 当前最新MacOS版本是13 于是面临一个问题, 很多最新的工程软件不支持我这IntelCPU的MacOS陈旧版本, 于是我准备装一个虚拟机, 把工程软件都安装到虚拟机里, 宿主机访问其中的服务, 这样还能继续保持我这…

从定义到实际应用,详解项目管理的基本概念与核心内容

项目管理是项目的管理者&#xff0c;在有限的资源约束下&#xff0c;运用系统的观点、方法和理论&#xff0c;对项目涉及的全部工作进行有效地管理。项目管理的内容包括项目范围管理&#xff0c;是为了实现项目的目标&#xff0c;对项目的工作内容进行控制的管理过程。它包括范…

mysql5安装【含mysql安装包】

mysql5安装【含mysql安装包】 安装包等资源安装流程 安装包等资源 安装包下载地址【CSDN免费】&#xff1a;https://download.csdn.net/download/qq_47168235/87881814 如果上面的个下载不了&#xff0c;就通过百度网盘吧 百度网盘连接&#xff1a;https://pan.baidu.com/s/1G…

碳排放预测模型 | Python实现基于CNN卷积神经网络的碳排放预测模型(预测未来发展趋势)

文章目录 效果一览文章概述研究内容环境准备源码设计学习总结参考资料效果一览 文章概述 碳排放预测模型 | Python实现基于CNN卷积神经网络的碳排放预测模型(预测未来发展趋势) 研究内容 这是数据集的链接:https://github.com/owid/co2-data/blob/master/owid-co2-data.csv …

zabbix之ODBC监控方式

如有错误&#xff0c;敬请谅解&#xff01; 此文章仅为本人学习笔记&#xff0c;仅供参考&#xff0c;如有冒犯&#xff0c;请联系作者删除&#xff01;&#xff01; 15.1 概述 ODBC监控对应于Zabbix前端中的 数据库监视器 监控项类型。 ODBC是C语言编写的中间件API&#xf…

uniapp 使用组件 uni-list 实现聊天列表功能

如何使用 uniapp 的组件实现聊天列表的功能呢&#xff0c;翻阅了半天文档&#xff0c;终于找到一个实用的方法&#xff0c;下面是具体的步骤 1、首先需要下载对应的插件 去uniapp的官方文档进行下载&#xff08;uni-ui - DCloud 插件市场&#xff09;&#xff0c;这里直接下载…

机器学习 day17( Tensorflow和Numpy中的数据形式 )

Numpy和Tensorflow NumPy (Numerical Python) 是 Python 语言的一个扩展程序库&#xff0c;支持大量的维度数组与矩阵运算&#xff0c;此外也针对数组运算提供大量的数学函数库。TensorFlow是Google开源的第二代用于数字计算的软件库。它是基于数据流图的处理框架&#xff0c;…

使用Docker-Compose对Docker容器集群快速编排

目录 一、Docker-Compose1、Docker-Compose使用场景2、Docker-Compose简介3、Docker-Compose安装部署4、YAML 文件格式及编写注意事项5、Docker Compose配置常用字段6、Docker Compose 常用命令7、Docker Compose 文件结构8、docker Compose撰写nginx 镜像9、docker Compose撰写…

leetcode 链表+双指针问题小结

文章目录 141. 环形链表142. 环形链表 II19. 删除链表的倒数第 N 个结点160. 相交链表 141. 环形链表 设置两个速度不一样的链表&#xff0c;如果其中他们两个在经过一定的步数(进入环之后&#xff0c;在 n ∣ 环的大小 ∣ n \times |环的大小| n∣环的大小∣ 步后会重合)之后…

Redis的复制

配置 在Redis中使用复制功能非常容易 在从Redis服务器的redis.conf中写入slaveof masterip masterport即可&#xff0c;主Redis服务器不需要做任何配置在启动Redis服务器的时候&#xff0c;指定主服务器&#xff0c;redis-server --slaveof masterip masterport在客户端指定主…