冒泡排序模拟实现qsort()函数

news2024/11/22 21:40:42

冒泡排序模拟实现qsort函数

  • 前言
  • 1. 分析
  • 2. 解决一,如何接受不同数据
  • 3. 解决二,如何实现不同数据的比较
  • 4. 解决三,如何实现不同数据交换
  • 5. 模拟bubble_sort()函数排序整型所有代码实现
  • 6. 结构体排序实现
  • 7. 结尾

前言

要模拟qsort()函数,我们首先要知道qsort()函数的特点:

  1. 使用快速排序的方法。
  2. 适用于任何数据类型的排序。

但由于部分学者还没有学习快速排序算法,所以本篇博客采用冒泡排序来模拟功能类似于qsort()的函数bubble_sort。

C库对qsort()函数解释:
在这里插入图片描述

我们得到的关于qsort()函数参数信息:

void qsort(void* base, //指向排序的第一个元素
		   size_t num, //排序元素的个数
		   size_t size,//一个元素的大小,单位为字节
		   int (*cmp)(const void*, const void*)//函数指针类型 — 这个函数指针指向的函数,能够比较base指向数组的两个元素
);

1. 分析

我们首先来看一段普通的冒泡排序来排序整型数据

void bubblr_sort(int arr[], int sz)
{
	//排序趟数
	for (int i = 0; i < sz - 1; i++)
	{
		int tmp = 0;
		//每趟比较对数
		for (int j = 0; j < sz - 1 - i; j++)
		{
			//假设升序,交换元素
			if (arr[i] > arr[i + 1])
			{
				tmp = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = tmp;
			}
		}
	}
}
int main()
{
	int arr[10] = { 10,9,8,7,6,5,4,3,2,1 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	return 0;
}

既然是用冒泡排序来模拟qsort()函数,我们可以以上面这段代码为基础,需改模拟实现。但存在几个问题!!

  1. 如何接受不同的数据类型,而不仅仅是整型。
  2. 对于不同的数据,比如结构体不能简单的用>或<还比较,那如何实现呢?
  3. 对于不同的数据类型,交换略有差异

2. 解决一,如何接受不同数据

void* 是C语言中的通用指针类型,可以指向任意类型的数据。所以我们可以将参数base定义为void*类型指针,来接受不同的数据。

void*用法拓展:

  1. 在使用void* 指针时,因为它不知道指向的类型的大小,需要将其转换为具体的指针类型才能进行操作。例如,可以将void 指针转换为int 指针,然后*对其进行赋值或者解引用操作。
    2. void * 是一个无类型指针,在由于进行算术运算时,需要知道指针指向的具体数据类型的大小以便确定移动的字节数,所以它不能直接进行算术运算。

3. 解决二,如何实现不同数据的比较

由于不同的数据类型有不同的比较方法,我们可以在模拟的bubble_sort()函数参数中添加一个函数指针。将两个元素的比较方法,函数参数的形式进行传递。

Tips:

  • 目前传入的数据以整型为例,所以我们定义比较函数名为cmp_int。在文章结尾将给出传入结构体数据的实现代码。

代码实现

//bubble_sort()实参传入
bubble_sort(arr,sz, sizeof(arr[0]), cmp_int);

//bubble_sort()函数参数实现
void bubble_sort(void* base, int num, int size, int (*cmp)(const void*, const void*))

//cmp_int函数实现
int cmp_int(const void* p1, const void* p2)
{
	//强制类型转换为int* ,在进行解引用
	return (*(int*)p1 - *(int*)p2);//假设升序,则返回>0的数
	//至于为什么返回这个数据,参考qsort()函数模仿即可
}

4. 解决三,如何实现不同数据交换

对于不同的数据,我们可以交换的两个数的起始地址强制类型转化为(char*),然后计算出两个数据大小,最后两则一个一个字节交换即可。

代码实现

//数据交换我们封装一个Swap()函数
void Swap(char* buf1, char* buf2, int size)//交换arr[i]和arr[i+1]
{
	char tmp = 0;
	while (size--)
	{
		tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

5. 模拟bubble_sort()函数排序整型所有代码实现

由于是在冒泡排序的基础上来实现排序的,而排序的趟数和每趟排序的对数是不变的。所有我们只要解决上述问题,将相关代码进行替换即可。

代码实现

#include <stdio.h>

int cmp_int(const void* p1, const void* p2)
{
	return (*(int*)p1 - *(int*)p2);
}

void Swap(char* buf1, char* buf2, int size)//交换arr[i]和arr[i+1]
{
	char tmp = 0;
	while (size--)
	{
		tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

void bubble_sort(void* base, int num, int size, int (*cmp)(const void*, const void*))
{
	int i = 0;
	//趟数
	for (i = 0; i < num; i++)
	{
		//一趟比较对数
		//假设升序
		for (int j = 0; j < num - 1 - i; j++)
		{
			if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)//比较两个元素,需要将arr[j]和arr[j+1]的地址传给cmp
			{
				//交换
				Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}


//测试bubble_sort排序整型数据
void test1()
{
	int arr[] = { 4,2,5,8,3,8,34,23,1,54 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr,sz, sizeof(arr[0]), cmp_int);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}


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

运行结果:
在这里插入图片描述

6. 结构体排序实现

排序结构体时,Swap()和bubble_sort()函数实现是相同的;我们只需要改变以下int_cmp函数即可(注:int_cmp()函数的名字依据比较数据不同,博主命名不同)

代码实现

#include <stdio.h>
#include <string.h>

void Swap(char* buf1, char* buf2, int size)//交换arr[i]和arr[i+1]
{
	char tmp = 0;
	while (size--)
	{
		tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

void bubble_sort(void* base, int num, int size, int (*cmp)(const void*, const void*))
{
	int i = 0;
	//趟数
	for (i = 0; i < num; i++)
	{
		//一趟比较对数
		//假设升序
		for (int j = 0; j < num - 1 - i; j++)
		{
		    //比较两个元素,需要将arr[j]和arr[j+1]的地址传给cmp
			if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
			{
				//交换
				Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}


//测试bubble_sort排序结构体数据
struct Stu
{
	char name[20];
	int age;
};

int cmp_stu_by_name(const void* p1, const void* p2)
{
	//比较两个字符时,需要借助函数strcmp()来实现
	return strcmp(((struct Stu*)p1)->name ,((struct Stu*)p2)->name);
}

void test2()
{
	struct Stu arr[] = { {"zahngsan",20},{"lisi",12},{"wangwu",43} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
}


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

运行结果:
在这里插入图片描述

7. 结尾

本篇博客到此就结束了。如果对你有帮助,记得三连哦!感谢您的支持!!

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

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

相关文章

将字符串转为类名

使用globals函数将字符串转为类名 如下&#xff1a; class Data:def __init__(self):self.name kellydef hello(self):print(hello)#直接使用字符串报错 res Data().hello() #res Data.hello()res1 globals()[Data]().hello()#通过字符串获取变量数据&#xff08;变为类中…

【ACM】—蓝桥杯大一暑期集训Day1

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;陈童学哦&#xff0c;目前专攻C/C、Python、Java等方向&#xff0c;一个正在慢慢前行的普通人。 &#x1f3c0;系列专栏&#xff1a;陈童学的日记 &#x1f4a1;其他专栏&#xff1a;CSTL、蓝桥杯&am…

怎样优雅地增删查改(五):按组织架构查询

文章目录 原理实现应用测试 之前我们实现了Employee&#xff0c;Alarm管理模块以及通用查询应用层。 Employee的集合查询业务&#xff0c;是通过重写CreateFilteredQueryAsync方法&#xff0c;来实现按组织架构查询的过滤条件。 我们将这段逻辑代码提取到通用查询应用层中&…

【前后缀GCD】ABC125 C

C - GCD on Blackboard (atcoder.jp) 题意&#xff1a; 思路&#xff1a; 这道题&#xff0c;多看看样例大概就出来了 由样例可知&#xff0c;换成的数可以是其他N-1个数的gcd&#xff0c;这样对答案的贡献也没有影响 所以直接去枚举换的是什么数就行 因此怎么去快速求其他…

对于 Spring MVC 了解? SpringMVC 的执行流程?SpringMVC 的核心是什么?请求的流程是怎么处理的?控制反转怎么实现的?

对于 Spring MVC 了解? 之前 Model1 和 Model2 这两个没有 Spring MVC 的时代。 Model1 时代 : 整个 Web 应用几乎全部用 JSP 页面组成&#xff0c;只用少量的 JavaBean 来处理数据库连接、访问等操作。 JSP 既是控制层又是表现层&#xff0c;存在很多问题&#xff0c;如①将…

逆天!安卓正式超越 Windows 成世界第一大操作系统

导读Android是一种基于Linux的自由及开放源代码的操作系统&#xff0c;主要使用于移动设备&#xff0c;如智能手机和平板电脑&#xff0c;由Google公司和开放手机联盟领导及开发。 10 亿的用户数意味着 Windows 依然是第一大桌面操作系统&#xff0c;不过如果算上智能手机平台…

抖音seo源码矩阵系统开发规则开发者分享(一)

抖音SEO矩阵系统源码开发&#xff0c;需要遵循一下步骤 1. 确定需求和功能&#xff1a;明确系统的主要目标和需要实现的功能&#xff0c;包括关键词研究、短视频制作、外链建设、数据分析、账号设置优化等方面。 2. 设计系统架构&#xff1a;根据需求和功能确定系统的架构&am…

微信公众号错误代码:40125

微信公众号错误代码&#xff1a;40125 报错代码 错误代码&#xff1a;40125, 错误信息&#xff1a;invalid appsecret rid: 64b0ba1d-74e53e36-717abb43&#xff0c; 微信原始报文&#xff1a;{"errcode":40125,"errmsg":"invalid appsecret rid: 6…

金融数据库的战场,太平洋保险和OceanBase打了场胜仗

点击关注 文丨刘雨琦 “数据库的国产替代&#xff0c;必须经过严格的考虑&#xff0c;保证不会出错&#xff0c;所以大多数企业的领导层选择按兵不动或者简单扩容。因为不换就不会错&#xff0c;选了很久如果选错&#xff0c;还可能会出现重大事故。” 某银行数据库技术人员…

UG\NX二次开发 获取对象的边界包容盒 UF_MODL_ask_bounding_box_aligned

文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan 简介: 获取对象的边界包容盒 UF_MODL_ask_bounding_box_aligned,可以得到指定坐标系下的盒子,速度快,结果不精确 效果: 代码: //UF_MODL_ask_bounding_box_aligned #include "me.hpp" #i…

【ABAP】数据类型(六)「域的概要」

💂作者简介: THUNDER王,一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学本科在读,同时任汉硕云(广东)科技有限公司ABAP开发顾问。在学习工作中,我通常使用偏后端的开发语言ABAP,SQL进行任务的完成,对SAP企业管理系统,SAP ABAP开发和数据库具有较…

Java使用EsayExcel导出模板,涉及多个sheet

需求&#xff1a;利用excel模板导出&#xff0c;有两个sheet&#xff0c;其中一个sheet涉及固定字段导出和多数 据(List)导出 1、模板 sheet1&#xff1a; sheet2&#xff1a; 2、主要代码 public static void outputExcelForTunnelMonitor(HttpServletResponse r…

EBU5476 Microprocessor System Design 知识点总结_8 I2C

I2C 连接多个模块的传输方案&#xff1a;I2C&#xff0c;使用两根总线。 两根总线分别是时钟总线 SCL 和数据总线 SDA。 通信过程 现在我们串一遍I2C上一个模块&#xff08;master&#xff09;要给另一个模块&#xff08;slave&#xff09;发消息的过程。 MCU 使用一定的方法…

玩转代码|Linux中Thread Local Storage(线程局部存储)

目录 pthread的内存结构 __thread pthread specific API __thread和pthread specific API对比 存储区域/寻址方式不同 性能/效率不同 能存储的数据不同 支持的数据个数不同 在C/C程序中&#xff0c;全局变量默认是所有线程共享的&#xff0c;开发者需要处理多线程竞争问…

如何在短时间内提高亚马逊关键词排名?

搜索购买可以在短时间内提高亚马逊关键词排名&#xff0c;操作方法是通过独立买家账号搜索关键词&#xff0c;找到商品&#xff0c;点击购买&#xff0c;提高关键词的相关性和保留率&#xff0c;让关键词排名自然提高&#xff0c;从而达到上首页的目的。不过要操作这一个方法还…

储能协调控制器装置|储能协调控制设备|储能系统功率控制器|源网荷储互动终端这种装置是什么?应用实施方案如何?

什么是储能协调控制器装置|储能协调控制设备|储能系统功率控制器|源网荷储互动终端及其应用实施方案 一&#xff1a;新型电力系统背景 以新能源为主体的新型电力系统是以新能源为供给主体、以确保能源电力安全为基本前提、以满足经济社会发展电力需求为首要目标&#xff0c;以…

Spring - 更简单的存取 Bean 对象(使用注解)

目录 一、类注解是什么 二、使用类注解 存取 Bean 对象 1. 准备工作 2. 所以使用五大类注解的规则&#xff1a; 三、五大类注解之间的关系 1. 首先可以查看 类注解的源码如下图&#xff1a; 2. 为什么需要五个类注解&#xff1f; 3. 为什么使用类注解的方式不能使用原类…

挖矿记录+解决方案:利用GitLab组件对服务器进行挖矿导致CPU占用200%

文章目录 什么是云服务器挖矿?事件记录事件分析产生影响解决方案后期预防什么是云服务器挖矿? 云服务器挖矿是指利用云服务器从事赚取比特币的活动。比特币是一种虚拟数字货币,挖矿是将一段时间内比特币系统中发生的交易进行确认,并记录在区块链上形成新区块的过程。 用于…

青岛大学_王卓老师【数据结构与算法】Week05_06_栈的顺序表示_学习笔记

本文是个人学习笔记&#xff0c;素材来自青岛大学王卓老师的教学视频。 一方面用于学习记录与分享&#xff0c; 另一方面是想让更多的人看到这么好的《数据结构与算法》的学习视频。 如有侵权&#xff0c;请留言作删文处理。 课程视频链接&#xff1a; 数据结构与算法基础…

【数据结构】之红黑树

红黑树 红黑树的概念红黑树的性质红黑树的插入操作&#xff08;核心&#xff09;情况一&#xff1a;uncle存在且为红情况二&#xff1a;uncle不存在/存在且为黑&#xff08;在同一侧&#xff09;情况三&#xff1a;uncle不存在/存在且为黑&#xff08;在两侧&#xff09;总结 红…