输入给一个完全二叉树,或者是一个近似完全二叉树,然后通过通过最大堆的性质,使之成为一个最大堆;
我们从倒数第二层的节点开始遍历(叶子节点那一层不用遍历),对于每个节点,比较它的左右孩子节点和自身的值的大小,把最大的值作为根,然后从底至上地遍历这个树。
当每次进行了swap操作之后,需要依次往下检查被交换的节点是否破坏了底层的节点的最大堆特性。
代码如下:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxx=500100;
int A[maxx];
int n;
void max_heap(int i){
int left=2*i,right=2*i+1,x;
if(left<=n && A[left]>A[i]) x=left;
else x=i;
if(right<=n && A[right]>A[x] ) x=right;
if(x!=i){
swap(A[x],A[i]);
max_heap(x);
}
return ;
}
int main (){
cin>>n;
for(int i=1;i<=n;i++) cin>>A[i];
for(int i=n/2;i>=1;i--) max_heap(i);
for(int i=1;i<=n;i++) cout<<" "<<A[i];
cout<<endl;
return 0;
}
错点:
1.当发生交换时,可能被交换下去的节点影响子树的堆特性,所以要递归下去检查;
2.所给的二叉树不一定是完全二叉树,可能是一个近似完全二叉树。所以在写left和right边界条件的时候不能直接让left和right都一定要小于n;
堆一定是完全二叉树或者近似完全二叉树
用STL中的make_heap函数实现最大堆,代码如下:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
vector<int> A;
int n,a;
cin>>n;
for(int i=0;i<n;i++) {
cin>>a;
A.push_back(a);
}
make_heap(A.begin(),A.end());
for(int i=0;i<n;i++) {
cout<<" "<<A[i];
}
cout<<endl;
return 0;
}