首页 > 编程语言 >堆排序以及向上、向下调整算法的时间复杂度推导及实现(超详细)

堆排序以及向上、向下调整算法的时间复杂度推导及实现(超详细)

时间:2024-08-07 21:53:50浏览次数:15  
标签:arr parent 推导 int 复杂度 堆排序 结点 child 向下

什么是堆排序?

堆排序是由堆这种数据结构所设计的一种排序算法

堆的分类:

大根堆:每个父结点的值都大于子结点

小根堆 :每个父结点的值都小于子结点

 

在了解完堆之后,需要先了解建堆,建堆有向上建堆建大堆或者小堆,也有向下建堆建大堆或者小堆 

建大堆还是小堆看子结点和父结点的比较关系是大于还是小于

 向上调整算法

新数据插⼊到数组的尾上,再进行向上调整算法,直到满⾜堆。

• 先将元素插⼊到堆的末尾,即最后⼀个孩⼦之后 

• 插⼊之后如果堆的性质遭到破坏,将新插⼊结点顺着其双双亲往上调整到合适位置即可

void swap(int* x, int* y)
{
	int tmp = *x;
	*x = *y;
	*y = tmp;
}
 
//建大堆还是小堆将两个算法的第一个判断条件修改相反即可
//向上调整
void AdjustUp(HPDataType* arr,int child)
{
	int parent = (child - 1) / 2;//根据子结点求父结点
	while (child > 0)//直到子结点为根结点即循环停止
	{
//                     >
		if (arr[child] < arr[parent])//子结点小就交换,创建小堆
		{
			swap(&arr[child], &arr[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

 向上调整算法时间复杂度计算推导

第1层,2^0个结点,需要向上移动0层

第2层,2^1个结点,需要向上移动1层

第3层,2^2个结点,需要向上移动2层 

第4层,2^3个结点,需要向上移动3层

..............................................................

第h层,2^(h-1)个结点,需要向上移动h-1层

则需要移动结点总的移动步数为:每层结点个数  *  向上调整次数(第⼀层调整次数为0) 

由此可得:

向上调整算法建堆时间复杂度为:O(n ∗ log2 n)

因为堆是完全⼆叉树,⽽满⼆叉树也是完全⼆叉树,此处为了简化使⽤满⼆叉树来证明(时间复杂度本 来看的就是近似值,多⼏个结点不影响最终结果)

向下调整算法

堆的删除:

删除堆是删除堆顶的数据,将堆顶的数据根最后⼀个数据⼀换,然后删除数组最后⼀个数据,再进⾏向下调整算法。

• 将堆顶元素与堆中最后⼀个元素进⾏交换

• 删除堆中最后⼀个元素

• 将堆顶元素向下调整到满⾜堆特性为⽌  

//向下调整
void AdjustDown(HPDataType* arr, int parent, int n)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		//小堆:找左右孩子中找最小的
		//大堆:找左右孩子中找大的
//                                      <
		if (child + 1 < n && arr[child] > arr[child + 1])
		{
			child++;
		}
//                     >
		if (arr[child] < arr[parent])  //小堆,什么时候交换? 孩子比父亲小
		{
			swap(&arr[child], &arr[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

void HPPop(HP* php)
{
     assert(php);
     assert(php->size > 0);
     Swap(&php->a[0], &php->a[php->size - 1]);
     php->size--;
     AdjustDown(php->a, php->size, 0);
}

 向下调整算法时间复杂度计算推导

第1层,2^0个结点,需要向下移动h-1层 

第2层,2^1个结点,需要向下移动h-2层

第3层,2^2个结点,需要向下移动h-3层

第4层,2^3个结点,需要向下移动h-4层

......

第h-1层,2^(h−2)个结点,需要向下移动1层 

则需要移动结点总的移动步数为:每层结点个数  *  向下调整次数

向下调整算法建堆时间复杂度为:O(n) 

堆排序的应用

//堆排序
void HeapSort(int* arr, int n)
{
	//建堆
	//升序——大堆
	//降序——小堆
	//向上调整算法建堆
	//for (int i = 0; i < 6; i++)
	//{
	//	AdjustUp(arr, i);
	//}


	//向下调整算法建堆
	//for (int i = (n - 1- 1) / 2; i >= 0; i--)
	//{
	//	AdjustDown(arr, i, n);
	//}

	//循环将堆顶数据和最后一个数据进行交换
	int end = n - 1;
	while (end > 0)
	{
		swap(&arr[0], &arr[end]);
		AdjustDown(arr, 0, end);
		end--;
	}
}

堆排序时间复杂度计算  

第1层,2^0个结点,交换到根结点后,需要向下 移动0层

第2层,2^1个结点,交换到根结点后,需要向下 移动1层

第3层,2^2个结点,交换到根结点后,需要向下 移动2层

第4层,2^3个结点,交换到根结点后,需要向下 移动3层

......

第h层,2^(h-1)个结点,交换到根结点后,需要向 下移动h-1层

 通过分析发现,堆排序第⼆个循环中的向下调整与建堆中的向上调整算法时间复杂度计算⼀致,此处 不再赘述。因此,堆排序的时间复杂度为O(n + n ∗ log n) ,即(n log n)

标签:arr,parent,推导,int,复杂度,堆排序,结点,child,向下
From: https://blog.csdn.net/ZWW_zhangww/article/details/140949762

相关文章

  • 最小二乘法原理推导+代码实现[Python]
    0.前言本文主要介绍了最小二乘法公式推导,并且使用Python语言实现线性拟合。读者需要具备高等数学、线性代数、Python编程知识。请读者按照文章顺序阅读。绘图软件为:geogebra5。1.原理推导1.1应用最小二乘法在购房中的应用通常涉及房价预测和房屋定价方面。这种统计方法通......
  • 排序算法 堆排序 HeapSort -- C语言实现
    堆排序堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:大顶堆:每个节点的值都大于或等于其子......
  • 低代码: 系统开发准备之确定一般开发流程,需求分析,复杂度分析,标准开发流程
    概述低代码系统开发之前,我们首先要进行一些准备我们首先知道我们软件开发的一般流程同时,我们还要知道,我们整个系统平台的需求如何之后,我们要基于需求进行设计,包含UI设计与系统架构设计一般开发流程系统开发一般要经过如下几个步骤,低代码系统平台也不例外我们来看下软件开......
  • 【数据结构】一文总结算法的时间复杂度与空间复杂度
    目录一.算法的复杂度二.时间复杂度1.概念2.大O的渐进表示法3.实践练习3.1练习13.2 练习23.3 练习33.4练习43.5练习5三.空间复杂度 1.概念2.实践练习2.1练习12.2练习22.3练习32.4练习4四.编程题练习 1. 消失的数字2.轮转数组 一.......
  • 在Python中,list1[::] = list2的空间复杂度是多少?
    此代码首先迭代列表nums,更新整数0、1、2(也分别称为红色、白色和蓝色)的计数。nums保证只有整数0、1和/或2。找到计数后,代码使用[::],这是一种就地修改列表的技巧,以排序numsdefsortColors(self,nums:List[int])->None:re......
  • C++ 返回值类型推导
    C++返回值类型推导前言C++中获取函数签名可以很简单地用decltype(函数名)来获得,但是这样无法直接提取出返回值类型。有时我们需要获取函数或可调用对象的返回值类型,以便进行后续的操作,在泛型编程中很常用,特别是当不同的参数集的结果类型不同时。头文件<type_traits>:C......
  • 最大传输功率数学推导
    最大传输功率,不仅适用于低频,也适用于高频。在个人的认知里,也同样可以用来解释高速信号的匹配原理,而不仅仅只是从阻抗不匹配造成的反射来解释。电路分析图 1.由以上电路可知,负载功率表示如下2.由复功率、能量守恒可知 3.复阻抗的虚部,属于无功功率,发送等......
  • 【每日一题 | 数据结构】时间复杂度计算
    题目解题方法对于二重循环求时间复杂度:写出外层i的变化值写出内层循环语句执行次数(看j)对次数求和找到频度和n的关系笔记视频跳转:【每日一题|数据结构】时间复杂度计算......
  • 世界上速度最快的超级计算机推导出超级BC8钻石配方
    BC8超级钻石比任何已知材料都要坚硬,但它们很可能只存在于巨型系外行星的内核中。现在,世界上最强的超级计算机"前沿"已经揭开了它们形成的秘密,这一发现可能会导致在地球上生产它们。钻石不仅是夺人眼球的珠宝,而且在世界各地被广泛应用。作为世界上最坚硬的物质–得益于其......
  • 轻松拿捏python推导式
    推导式定义推导式 comprehensions(又称解析式),是Python的一种独有特性。推导式最主要的特点就是可以从一个数据序列构建另一个新的数据序列。在Python中目前常用的推导式有列表推导式、字典推导式和集合推导式。列表推导式(ListComprehensions)列表推导式是我们最常使用的......