堆
堆是一棵完全树,堆中某个节点的值总是不大于或不小于其父节点的值。——洛谷试炼场
C++STL里面有个东西叫priority_queue,其实,这就是一个堆
正如洛谷所说,堆是一个完全树,分为两类:
大根堆:
小根堆:
堆的实现方法
主要有这样几个操作:push,top,pop (为了和STL统一)
其实如果打模板题的话直接调用priority_queue就可以了
push(插入)
以小根堆为例,我们先把要插进来的值放在堆最下面,然后一步一步的向上比较,如果这个值比他父亲节点的值要小,那么把他们交换一下,一直到这个点已经是根节点或者是它没有比他父亲节点值小,就停止
inline void push(int val){
heap[++siz]=val;
int now=siz;
while(now>1){
int rt=now/2;
if(heap[rt]>heap[now])swap(heap[rt],heap[now]);
else break;
now=rt;
}
}
pop(弹出)
主要操作是将队头元素和队尾元素交换一下,然后一步一步向下比较,如果这个点比左儿子大,就交换(右儿子同理),直到不能再交换了为止
inline void pop(){
heap[1]=heap[siz];
int rt=1;
while(rt*2<siz){
int lson=rt*2;
int rson=lson+1;
if(rson>=siz||heap[lson]<heap[rson]){
if(heap[rt]>heap[lson]){
swap(heap[rt],heap[lson]);
rt=lson;
}
else break;
}
else{
if(heap[rt]>heap[rson]){
swap(heap[rt],heap[rson]);
rt=rson;
}
else break;
}
}
siz--;
}
top(询问根元素)
这个我觉得没什么好说的,我们heap[1]就一直存的是根啊,直接返回就可以了
inline int top(){
return heap[1];
}
这样到这里我们就把C++STL中的priority_queue中几个常用函数push(val),pop(),top()讲完了,但是,接下来为大家隆重推出一个C++STL两个无法实现的操作:
size(访问堆大小)
inline int size(){
return siz;
}
depth(堆的深度)
inline int depth(){
return log(2,siz)+1;
}
最后是整个堆模板(为了贴近优先队列我是写在了结构体里)
my_priority_queue
struct Priority_queue{
int heap[N];
int siz;
Priority_queue(){
memset(heap,0,sizeof(heap));
siz=0;
}
inline void push(int val){
heap[++siz]=val;
int now=siz;
while(now>1){
int rt=now/2;
if(heap[rt]>heap[now])swap(heap[rt],heap[now]);
else break;
now=rt;
}
}
inline void pop(){
heap[1]=heap[siz];
int rt=1;
while(rt*2<siz){
int lson=rt*2;
int rson=lson+1;
if(rson>=siz||heap[lson]<heap[rson]){
if(heap[rt]>heap[lson]){
swap(heap[rt],heap[lson]);
rt=lson;
}
else break;
}
else{
if(heap[rt]>heap[rson]){
swap(heap[rt],heap[rson]);
rt=rson;
}
else break;
}
}
siz--;
}
inline int top(){
return heap[1];
}
inline int size(){
return siz;
}
inline int depth(){
return log(2,siz)+1;
}
};