问题描述
请根据以下伪代码编写一个程序,使用给定数组生成最大堆。
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;
}