堆的定义
堆是一个树型的数据结构,是一个二叉树,每个节点都比他的字节的小(小根堆)/大(大根堆)。
堆的存储方式
由于堆是一个满二叉树,所以可以使用数组的方式进行存储,如图我们可以观察到,如果当前节点的下标是i,则父节点为i / 2,子节点为 i * 2和i * 2 +1;这样每个节点就可找到父节点和子节点。
图解
堆的操作
堆主要包含5个操作:
- 判断对是否为空:empty();
- 返回堆的大小:size();
- 往队中加入元素:push();
- 返回堆头元素:top();
- 删除堆头袁术:pop();
实现堆的操作:
class heap //小根堆
{
protected:
int n;//表示堆中的元素个数
int h[N];
public:
int size()
{
return n;
}
int empty()
{
return n==0;
}
void down(int u)//将以u为根节点的树变成推 ,使用前提是:左右子树都是推。
{
int t=u;
if(u*2<=n&&h[u*2]<h[t]) t=u*2;
if(u*2+1<=n&&h[u*2+1]<h[t]) t=u*2+1;//先在当前节点和左右节点中找到最小的节点
if(t!=u)//如果最小的节点为子节点
{
swap(h[t],h[u]);//交换两个节点
down(t);//由于子节点的值发生变化,所以需要将子节点的子树转化为堆。
}
}
void up(int u)
{
while(u/2>=1&&h[u/2]>h[t]) //如果父节点比当前节点小
{
swap(h[t],h[u]);//交换两个节点
u>>=1;//父节点继续操作
}
}
int push(int x)
{
h[++n]=x;
up(n);
}
int top()
{
return h[1];
}
void pop()
{
h[1]=h[n--];
down(1);
}
}