二叉堆
二叉堆的实质是完全二叉树。二叉堆有两种:最大堆和最小堆。最大堆是指父节点值总是大于或等于任何一个子节点的值。而最小堆恰恰相反,指的是父节点值总是小于任何一个子节点的值。
这就是应该最小堆
操作
- push 插入元素
- top 取出元素(但不删除)
- pop 删除元素
数组实现
int q[1010];
int size=0;//堆里面的元素个数
STL实现
头文件:#include<queue>
priority_queue<int> q;//大根堆q
priority_queue<int,vector<int>,greater<int> >q;//小根堆q
Push
原本存在一个(最小)二叉堆{1,2,3, 4, 4, 5, 6, 7, 8, 9};现在要往里面插入一个0。如图所示
我们的方法就是用0与他的父节点取比较大小,如果小于父节点,就交换这两个结点的值,直到到达根结点或者大于父节点为止。
void push(int x)
{
q[++size]=x;
int now=size;
while(now)
{
int nxt=now>>1;//这一步可结合上面二叉堆的图来理解,就是除2
if(q[nxt]<q[now])
swap(q[nxt],q[now]);
else break;
now=nxt;
}
}
Top
top在STL里面的优先队列才能用。
int a=q.top();//取出队首元素但不删除
如果是用数组实现就比较直接,直接取出数组第一个元素就行了
int a=q[1];
Pop
如果取出了这个元素之后这个元素就没用了想删除这个堆顶的元素该怎么办?
还是先看这个图。
比如说我取出这个 1,就直接把堆顶的元素与堆底的元素交换,然后把size–,就删掉了这个元素,再对堆顶元素实施上面元素插入一样相反的操作,也就是用堆顶元素与他下面两个结点相比,如果大就往下交换。
void pop()
{
swap(q[1],q[size]);
size--;
int now=1;
while((now<<1)<=size)
{
int nxt=now<<1;
if(nxt+1<=size&&q[nxt]>q[nxt+1])
nxt+=1;
if(q[now]>q[nxt])
swap(q[now],q[nxt]);
else break;
now=nxt;
}
}