归并排序/计数排序

news2024/11/26 0:38:03

1:归并排序

1.1:代码

void _MergeSort(int* arr, int left, int right, int* tmp)
{
	if (left >= right)
	{
		return;
	}
	int mid = (left + right) / 2;						
	_MergeSort(arr, left, mid, tmp);					
	_MergeSort(arr, mid+1, right, tmp);					

	int begin1 = left;									
	int end1 = mid;										
	int begin2 = mid + 1;								
	int end2 = right;									

	int i = begin1;										
	while (begin1 <= end1 && begin2 <= end2)			
	{													
		if(arr[begin1] < arr[begin2])					
		{												
			tmp[i++] = arr[begin1++];					
		}												
		if (arr[begin1] > arr[begin2])					
		{												
			tmp[i++] = arr[begin2++];					
		}												
	}													
														
	while (begin1 <= end1)								
	{													
		tmp[i++] = arr[begin1++];						
	}													
	while (begin2 <= end2)								
	{													
		tmp[i++] = arr[begin2++];						
	}													

	for (int i = left; i <= right; i++)					
	{													
		arr[i] = tmp[i];								
	}										    
}


void MergeSort(int* arr, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);	
	_MergeSort(arr, 0, n - 1, tmp);
}

1.2:递归过程

图一:

	if (left >= right)
	{
		return;
	}
	int mid = (left + right) / 2;						
	_MergeSort(arr, left, mid, tmp);					
	_MergeSort(arr, mid+1, right, tmp);		

通过这三行代码,可以得到如图所示的结果,当传递的 left 和 right 满足 if 条件时,递归开始返回,

图二:

注:方框内容为自定义函数:void _MergeSort(int* arr, int left, int right, int* tmp)

注:对于新手(编者我而言)需要知道的是,每次递归,都会向系统开辟新的空间,而原先的空间会临时贮存在空间中,通过return返回重新调用该函数。

第一次返回时,来到D这个位置,接下来就将执行排序,即如下代码:该函数中 left = 0  mid = 0 right = 1,是对两个元素进行排列。

int begin1 = left;						
int end1 = mid;							
int begin2 = mid + 1;					
int end2 = right;						

int i = begin1;							
while (begin1 <= end1 && begin2 <= end2)
{										
	if(arr[begin1] < arr[begin2])		
	{									
		tmp[i++] = arr[begin1++];		
	}									
	if (arr[begin1] > arr[begin2])		
	{									
		tmp[i++] = arr[begin2++];		
	}									
}										
										
while (begin1 <= end1)					
{										
	tmp[i++] = arr[begin1++];			
}										
while (begin2 <= end2)					
{										
	tmp[i++] = arr[begin2++];			
}										

当前范围内的数组排列完毕时,需要将临时数组的值传递给原数组,以便于下一次继续比较排序,

代码如下:

for (int i = left; i <= right; i++)	
{									
	arr[i] = tmp[i];				
}									

left 和 right 分别对应数组左右临界,而left ~ right 中间的范围正是需要赋值的对象。

当D排序完毕后,系统会将其释放,此时来到B处,开始对右边数组开始递归,直至return,与左边递归类似,如图三所示:

图三:

当D中和E中的数组全部排列完毕,并且赋值给原数组时,此时会返回到B,对B中数组元素进行排列,,最后我们能够得到如下图所示的结果:

图四:

到B中函数排列完毕,并将临时数组中的值赋值给arr时,此时系统会将其空间释放,并返回到A中,开始递归右边部分函数,其过程如下图所示。

图五:

而对于右半部分的递归与左半部分相似,对于新人而言(我)注意其左临界值left的变化即可,其次通过上述过程不难发现,归并排序其实是一个后序遍历二叉树结点的过程,通过对左右子节点中的数组元素进行排列,最终在根节点处再次排列得到有序数组。

1.3:归并排序特性总结

时间复杂度:O(nlogn)

空间复杂度:O(n) —— 至于为什么是 n 而不是 logn 是因为以malloc 开辟了一块 n 大小的内存空间

2:计数排序

2.1:代码

void CountSort(int* arr, int n)		
{									
	int max, min;
	max = min = arr[0];

	for (int i = 0; i < n; i++)
	{
		if (arr[i] > max)
		{
			max = arr[i];
		}
		if (arr[i] < min)
		{
			min = arr[i];
		}
	}

	int range = max - min + 1;
	int* tmp = (int*)malloc(sizeof(int) * range);
	assert(tmp);
	memset(tmp, 0, sizeof(int) * range);

	for (int i = 0; i < n; i++)
	{
		tmp[arr[i] - min]++;
	}

	int index = 0;
	for (int i = 0; i < range; i++)
	{
		while (tmp[i]--)
		{
			arr[index++] = i + min;
		}
	}							
}			

2.2:思路

计数排序的思想:先找到数组中的最大值和最小值,定义 range (range = max - min +1) 个大小空间的数组 ,为了是大数据能够更好的存放进数组,同时又不会浪费太多空间。

我们需要把原数组的数据 - min 存放进新数组相应位置处,原数组中每重复一个数字,新数组相应位置处的大小就+1,这就意味着计数排序要求原数组中,各个数据相差不是很大,否则会造成空间的浪费。

计数排序的巧妙在于,我们不用去比较各个元素然后排序,而是统计原数组中,每个元素出现的次数,并将该元素 - min (这个差对应新数组下标)存入到数组中,如果两个值相差不大 ,得到的差会对应于新数组的一个下标,即新数组中,统计的是该元素在原数组中出现的次数,最后我们再进行排序时,以新数组元素个数为条件出发,同时新数组下标+min 又可以得到原数组中的元素,从而实现排列。

2.3:代码分析

下列代码我们开辟了一块 range 大小的空间区域

	int max, min;
	max = min = arr[0];

	for (int i = 0; i < n; i++)
	{
		if (arr[i] > max)
		{
			max = arr[i];
		}
		if (arr[i] < min)
		{
			min = arr[i];
		}
	}

    int range = max - min + 1;
    int* tmp = (int*)malloc(sizeof(int) * range);
    assert(tmp);
    memset(tmp, 0, sizeof(int) * range);

下列代码统计了原数组中,每个元素出现的次数,并存入到临时数组中

for (int i = 0; i < n; i++)
{
	tmp[arr[i] - min]++;
}

最后对临时数组进行访问,以临时数组中元素个数为条件,临时数组下标地址 + min 得到原数组的值:

int index = 0;
for (int i = 0; i < range; i++)
{
	while (tmp[i]--)
	{
		arr[index++] = i + min;
	}
}		

2.4:图示上述过程:

初始时如图所示:

当进入第二个for循环时,开始统计原数组中的元素个数,当循环结束时,得到如下图所示变量关系:

当进入第三个for循环时,遍历tmp中各个元素,同时内层以各个元素的值作为条件,循环的将 i + min (原数组对应值) 赋值给原数组中,当外层 for 循环完成对数组的遍历时,此时原数组也得到了正确的顺序。

2.5:计数排序的特性

适用范围:数据范围比较集中时,效率很高

时间复杂度:O(N+range)

空间复杂度:O(range)

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

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

相关文章

洗护工厂上门预约下单洗衣洗鞋门店小程序

洗护工厂上门预约下单洗衣洗鞋门店小程序定制; ​ ​用户扫码后在小程序自助下单&#xff0c;可预约上门送取件更便捷的洗衣洗鞋新体验&#xff01; 案例介绍&#xff1a; 为洗衣洗鞋门工厂开发的一个洗鞋用户自己下单的软件&#xff0c;用户在线下单即可上门送取; 洗鞋小程序是…

[产品管理-5]:NPDP新产品开发 - 3 - 企业创新战略及创新战略框架与新产品开发(从市场、商业模式、产品、技术、成本等维度划分)

目录 一、什么是创新战略 1、定义与特点 2、类型与策略 3、核心要素与实施步骤 4、重要意义 二、创新战略框架 2.1 波特的创新战略框架&#xff08;差异化战略框架&#xff09; 1. 总成本领先战略&#xff08;Overall Cost Leadership Strategy&#xff09; 2. 广度选…

合适做项目交付的物联网平台:ThingsKit

ThingsKit&#xff0c;作为一个专为项目交付设计的物联网平台&#xff0c;凭借其强大的功能和灵活性&#xff0c;成为了众多企业的首选。 一、ThingsKit的核心优势 模块化设计&#xff1a;ThingsKit采用模块化设计&#xff0c;使得用户可以根据自己的需求灵活选择和组合不同的…

【软考中级攻略站】-软件设计师(7)- 结构化开发方法(数据流图)

系统设计基本原理 抽象是一种设计技术&#xff0c;重点说明一个实体的本质方面&#xff0c;而忽略或者掩盖不是很重要或非本质的方面。模块化是指将一个待开发的软件分解成若干个小的、简单的部分——模块&#xff0c;每个模块可独立地开发、测试&#xff0c;最后组装成完整的…

线下ERP与电商平台集成:点三API深度解析——优化电商订单数据同步的实践方案

随着电商市场的快速发展&#xff0c;线上订单与线下运营的无缝衔接成为了商家和企业提升运营效率的关键环节。尤其对于依赖ERP和WMS系统的企业而言&#xff0c;如何高效、快速地实现与电商平台的数据对接&#xff0c;确保订单、库存、物流等信息的实时同步&#xff0c;是优化供…

基于Spring Boot的电子请柬私人定制销售平台的设计与实现---附源码78900

目录 摘要 1 绪论 1.1 选题背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2系统分析 2.1 可行性分析 2.1.1技术可行性 2.1.2经济可行性 2.1.3社会可行性 2.1.4法律可行性 2.2 系统流程分析 2.2.1 数据流程 2.2.2 业务流程 2.3 系统功能分析 2.3.1 功能性…

Android 11 访问/mnt/media_rw下的U盘文件,使用File.listFiles()方法列出U盘文件,始终错误返回null,已解决。

背景介绍&#xff1a;我做的launcher有一个功能&#xff0c;就是检测U盘中是否有update.zip文件&#xff0c;有的话就拉起升级程序&#xff0c;没有就弹窗提示没有。使用File.listFiles()列出/mnt/media_rw下的U盘文件列表&#xff0c;明明U盘有文件&#xff0c;代码逻辑也没错…

【JVM】类加载过程|双亲委派模型

目录 四、类加载过程 1.类加载过程 2.双亲委派模型&#xff08;经典面试题&#xff09; 什么是双亲委派模型 双亲委派模型的优点 破坏双亲委派模型 四、类加载过程 1.类加载过程 咱们写的java代码&#xff0c;是.java文件&#xff08;硬盘&#xff09;&#xff0c;一个j…

手动用梯度下降法和随机梯度下降法实现一元线性回归

手动用梯度下降法实现一元线性回归 原文链接:https://www.cnblogs.com/qimoxuan/p/18407823 实验目的 本次实验旨在通过手动实现梯度下降法和随机梯度下降法来解决一元线性回归问题。具体目标包括: 生成训练数据集,并使用matplotlib进行可视化。设计一个`LinearModel`类来…

Mac清理其他文件:释放存储空间的高效指南

每个Mac用户都可能遇到存储空间不足的问题&#xff0c;尤其是当“其他”文件积累到一定体积时。在Mac上&#xff0c;“其他”文件通常包括各种系统文件、缓存、文档以及不被归类为应用程序、照片、电影或音乐的其他类型的文件。这些文件往往不易被注意&#xff0c;但逐渐占用了…

Java-idea小锤子图标

这一版的idea小锤子图标其实就在这里 点进去就找到了~

基于C#+SQL Server2008 开发三层架构(CS界面)图书管理系统

图书管理系统 一、项目背景及意义 当今由于信息技术的飞速发展&#xff0c;图书馆作为社会知识信息媒介的功能日益重要&#xff0c;网络环境下的信息资源建设知识仓库的设计&#xff0c;开放存取学术交流模式&#xff0c;知识管理系统&#xff0c;智能检索&#xff0c;数字参…

unocss 一直热更新打印[vite] hot updated: /__uno.css

控制台持续打印了几千条这条信息&#xff0c;页面逐渐卡死 client.ts:450 [vite] hot updated: /__uno.css 找出的原因是&#xff1a;依赖出问题了&#xff0c;重新安装unocss&#xff0c; 执行命令 npm i unocss 后修复。 但奇怪的是&#xff0c;删除node_modules重新全部安装…

一个简约的uniapp登录界面,基于uniapp+vue3+uview-plus

uniapp-vue3-template 一个简约的uniapp登录界面&#xff0c;基于uniappvue3uview-plus 页面主要包括&#xff1a;用户登录&#xff0c;手机验证码登录&#xff0c;用户注册&#xff0c;重置密码等页面 登录进去后为空白模板 源码在文末 界面 源码 uniapp登录界面源码

CyberDAO·S级市场旅游研讨会:川西之行圆满落幕

穿越人海 走进川西 在这个特别的秋天&#xff0c;CyberDAO组织了一场集结S级精英的“川西之旅”。此次研讨会不仅是DAO成员的一次盛大聚会&#xff0c;更是一场集会议、团队凝聚力提升和文化生活体验为一体的全方位旅程。2024年9月7日-10日&#xff0c;这支团队横跨山川湖海&a…

AttackGen - AI 网络安全事件响应测试工具,附下载链接

为了提高我们团队在安全活动中的响应效率&#xff0c;我关注到了一款叫 AttackGen 的工具&#xff0c;我们需要的是一个既能快速生成场景又能准确反映现实威胁的工具。 在红蓝对抗中&#xff0c;我们经常要模拟各种攻击场景&#xff0c;以测试我们的防御水平。这不仅仅是为了“…

【 C++ 】模板初阶

目录 ​编辑 一、泛型编程 二、函数模板 1.概念 2.格式 3.原理 4.匹配原则 三、类模板 1.定义格式 2.类模板的实例化 一、泛型编程 泛型编程是一种编程范式&#xff0c;它允许在编写代码时使用一种通用的数据类型或算法&#xff0c;以便在不同的数据类型上进行操作&…

如何将QAD系统EDI模块无缝迁移到知行之桥?

什么是QAD系统&#xff1f; QAD&#xff08;Quality, Applications, Development&#xff09;系统&#xff0c;是专为制造业设计的一款ERP软件&#xff0c;主要包含供应链管理、生产管理、财务和客户管理等业务功能&#xff0c;这家公司1979年成立于美国&#xff0c;目前在汽车…

STM32高级定时器实现:两路互补PWM输出,精准死区时间控制

目录 1. 实验目的&#xff1a; 2. 理论知识储备 2.1什么是互补输出&#xff1f; 2.2什么是死区控制&#xff0c;有什么用&#xff1f; 2.3参考手册的介绍 2.4了解死区寄存器(TIMx_BDTR) 3. 软件实现 3.1GPIO配置&#xff1a; 3.2TIM1初始化: 3.3主函数(main) 4. 实验…

NASA数据集:ASTER L2 地表辐射率 - VNIR 和串扰校正 SWIR V003

目录 简介 摘要 代码 引用 网址推荐 0代码在线构建地图应用 机器学习 ASTER L2 Surface Radiance - VNIR and Crosstalk Corrected SWIR V003 简介 ASTER 地表辐射度可见近红外和串扰校正 SWIR (AST_09XT) 是一个多文件产品 (https://lpdaac.usgs.gov/documents/996/A…