【探索数据结构与算法】向上调整建堆与向下调整建堆的时间复杂度

一.前言

堆排序是一种优于冒泡排序的算法, 那么在进行堆排序之前, 我们需要先创建堆,  那么这个建堆的时间复杂度是多少呢?

二.下调整算法建堆

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

假设高度为h的二叉树, 结点的个数为N, 可以计算出高度h与结点个数之间的关系如下图所示:

 

向下调整算法, 从最后一个非叶子结点开始向下调整, 也就是第h-1层, 需要向下移动一层, 第h-2层需要向下移动2层, … , 第一层则需要向下移动h-1层, 第二层的结点需要向下移动h-2层. 依次类推, 如图所示. 

 

移动的次数T(n) 

 

因此下调整建堆的时间复杂度为O(N) 

可以看出节点数量多的层调整次数少, 结点数量少的层调整次数多 . 错位相减法则可以计算出T(N) = 2^h - 1 - h, 带入h与N的关系则得出向下调整建堆的时间复杂度为O(N). 

代码实现 

void HeapSort(int* a, int n)//这里放在堆排序中建堆
{
	//降序
	//创建小堆
	//向下调整创建,从最有一个非叶子节点
	//时间复杂度O(N)
	for (int i = (n-1-1)/2; i>=0; i--)
	{
		Adjustdown(a, n, i);
	}
	//堆创建之后,交换第一个节点与最后一个节点,
	//时间复杂度为O(N*logN)
	int end = n-1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		Adjustdown(a, end, 0);
		end--;
	}
}

 

总计调整次数为 

 

使用错位相减法计算: 

 

可以看出结点数多的层, 调整次数也多, 结点数少的层, 调整次数少, 时间复杂度为O(N*logN), 所以一般建堆都采用向下调整建堆法. 

代码实现 
//放在堆排序中建堆
void Heapsort(int* a,int n)
{
	//时间复杂度为O(N*logN)
	for (int i = 1; i < n; i++)//使用for循环建堆
	{
		AdjustUP(a, i);
	}
	//时间复杂度为O(N*logN)
	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		end--;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值