二叉堆
二叉堆支持 插入,删除,查询最值的数据结构,它是一棵满足堆性质的完全二叉树,树上的每一个节点都有一个权值,若儿子小于等于父亲,那就是大根堆性质;若儿子大于父亲,则满足小根堆的性质。大根堆性质的是大根堆,小根堆性质的是小根堆
这么说,我就会了
其实二叉堆就是一个类似一种排序方法,堆排序,这种算法不难
一个节点编号i,左儿子节点2i,右儿子节点2i+1,这个知识点在初赛就学过了
既然我们说过它的操作有三种,那么我们就来详细地了解一下
插入
这个操作是最基本地,在了解这个操作的时候,一定明白堆这个数据结构是实现在数组里面的
进来一个节点v的时候,我们先把它放在数组的末尾,然后通过交换不断向上调整直至满足堆性质,时间复杂度为O(logN)
int head[size],n;
void up(int now)//大顶堆
{
while(now>1)
{
if(head[now]>head[now/2])
{
swap(head[now],head[now/2]);
p/=2;
}
else
break;
}
}
void insert(int v)
{
head[++n]=v;//存储到最后
up(n);//向上调整
}
查询最值
查询最值返回二叉堆顶部,直接一句话,时间复杂度为O(1)
int getop()
{
return head[1];
}
删除
删除操作就是把堆顶从二叉堆中移除,我们把堆顶与末尾的数进行交换(其实也不是什么交换,而是覆盖),然后删除最后一个点(即删除根节点),再将堆顶点向下调整,时间复杂度为O(logN)
void down(int now)
{
int l=now*2;
while(l<=n)//循环代替递归
{
if(l<n&&head[l]<head[l+1]) l++;
//左右节点取最大的与其交换
if(head[l]>head[now])
{
swap(head[l],head[now]);
now=l;//父亲变到儿子,比较难想
l=l*2;//下走
}
else break;
}
}
void shanchu()
{
head[1]=head[n];//交换
n--;//删除
down(1);
}
其实STL里面的priority_queue可以直接实现大根堆小根堆,自动进行排序,支持插入删除等一些操作,这些