最大/最小堆 | Maximum Heap | C/C++实现

问题描述

请根据以下伪代码编写一个程序,使用给定数组生成最大堆。

maxHeapify(A, i)用于从根结点 i 向叶结点方向寻找A[i]值的恰当位置,从而使以 i 为根结点的子树成为最大堆。这里我们设堆的大小为H。

maxHeapify(A, i)
	l = left(i)
	r = right(i)
	//从左子结点、自身、右子结点中选出值最大的结点
	if l <= H && A[l] > A[i]
		largest = l
	else
		largest = i
	if r <= H && A[r] > A[largest]
		largest = r
	
	if largest != i //i的子结点值更大时
		交换A[i]与A[largest]
		maxHeapify(A, largest)//递归调用

下面的buildMaxHeap(A)通过自底向上地套用mapHeapify,从而将数组A变换为最大堆。

buildMaxHeap(A)
	for i = H/2 downto 1
		maxHeapify(A, i)

输入: 第1行输入数组的长度H。接下来1行输入H个整数,依次表示堆中1至H号结点的值,相邻两整数之间用空格隔开。
输出: 按顺序输出最大堆中1至H号结点的值,整个输出占1行。请在各个值之前输出1个空格。
限制:
1 ≤ H ≤ 500000
-2000000000 ≤ 结点的值 ≤ 2000000000

输入示例

10
4 1 3 2 16 9 10 14 8 7

输出示例

 16 14 10 8 7 9 3 2 4 1

讲解

maxHeapify(A, i)会将A[i]的值一直向叶结点移动,直至满足最大堆的性质。

maxHeapify(A, i)先在 i 的左右子结点中选出较大的的一个,如果其键值大于当前结点键值则进行交换,然后向下循环执行该处理。

buildMaxHeap用来将给定的数组转换为最大堆,所以要从下标最大的非叶结点s开始自底向上地执行maxHeapify(A, i)。s的下标为H/2。

我们让 i 以H/2为起点1为终点,顺次对以 i 为根的子树执行maxHeapify(A, i)。每次执行maxHeapify(A, i)时,i 的左子树和右子树已经都是最大堆了,因此只需将根 i 的值通过maxHeapify(A, i)移动至恰当位置即可。

AC代码如下

#include<iostream>
using namespace std;
#define MAX 2000000

int H, A[MAX + 1];

void maxHeapify(int i){
	int l, r, largest;
	l = 2 * i;
	r = 2 * i + 1;
	
	//从左子结点、自身、右子结点中选出最大的结点
	if(l <= H && A[l] > A[i]) largest = l;
	else largest = i;
	if(r <= H && A[r] > A[largest]) largest = r;
	
	if(largest != i){
		swap(A[i], A[largest]);
		maxHeapify(largest);
	} 
} 

int main(){
	cin>>H;
	
	for(int i = 1; i <= H; i++) cin>>A[i];
	
	for(int i = H/2; i >= 1; i--) maxHeapify(i);
	
	for(int i = 1; i <= H; i++){
		cout<<" "<<A[i];
	}
	
	cout<<endl;
	
	return 0;
}
  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值