【问题描述】
堆在实际应用中有非常重要的作用,例如优先队列和堆排序。
堆实际上也是一个完全二叉树,而完全二叉树可以使用一个一维数组来保存,如下图a所示,对于一个具有n个节点的堆(完全二叉树), 其顶点按照从上而下从左至右的顺序排列保存到数组中,下标为i=0、1、2、...、n-1。
很显然,对于数组下标为k的元素(顶点),其子节点的下标分别为2k+1和2k+2,其父节点的下标为(k-1)/2。
对于输入的一组数据,可以将其视为一个完全二叉树的顶点,以下代码将会将该二叉树整理为一个最大堆,同时也实现了向堆中插入元素的代码。
请将相关代码补充完整,可参考教材115页有关的代码。
其中类方法shiftdown用于实现对当前位置的元素向下递推,insertElem实现向堆中插入新的节点。
【输入形式】
输入的第一行为一个整数n,表示最开始时创建的完全二叉树顶点元素的个数
接下来的一行为n个整数,表示最开始时创建的完全二叉树顶点元素,其顺序为从上而下从左至右
接下来的一行为一个整数,表示向创建的最大堆中插入的新元素。
【输出形式】
输出为两行,第一行n个数,表示创建的最大堆的顶点值,其顺序为从上而下从左至右, 第二行n+1个数,表示最大堆中插入元素后的顶点值,其顺序为从上而下从左至右
【样例输入】
10 20 12 35 15 10 80 30 17 2 1 75
【样例输出】
80 17 35 15 10 20 30 12 2 1 80 75 35 15 17 20 30 12 2 1 10
完整代码:
#include <bits/stdc++.h>
using namespace std;
class heap
{
private:
int n;
int *elem;
void shiftdown(int pos)
{
int left=leftChild(pos);
int right=rightChild(pos);
int largest=pos;
if (left<n&&elem[left]>elem[largest]) largest=left;
if (right<n&&elem[right]>elem[largest]) largest=right;
if (largest!=pos)
{
swap(elem[pos],elem[largest]);
shiftdown(largest);
}
}
public:
heap() {}
heap(int m)
{
n=m;
elem=new int[n];
}
~heap()
{
delete[] elem;
}
void initial()
{
for(int i=0; i<n; i++)
cin>>elem[i];
}
void out()
{
for(int i=0; i<n; i++)
{
cout<<elem[i];
if (i<=n-2)
cout<<" ";
else
cout<<endl;
}
}
bool isLeaf(int pos) const
{
return ((pos>=n/2) && pos<n);
}
int leftChild(int pos)
{
return 2*pos+1;
}
int rightChild(int pos)
{
return 2*pos+2;
}
void arrange()
{
for(int i=(n-1)/2; i>=0; i--)
{
shiftdown(i);
}
}
void insertElem(int x)
{
elem[n]=x;
n++;
for(int i=n-1; i>=0; i--) shiftdown(i);
}
};
int main()
{
int m;
cin>>m;
heap *ex=new heap(m);
ex->initial();
ex->arrange();
ex->out();
int insData;
cin>>insData;
ex->insertElem(insData);
ex->out();
return 0;
}