二叉堆
堆是一种特殊的完全二叉树,比如下面这张图
仔细观察上面的图片可以发现父节点的值都比子节点小,具有这样规律的堆,我们叫最小堆,堆顶的值最小。那么如果父节点的值都比子节点大,那么就叫做最大堆,堆顶的值最大。
二叉堆,可以帮助我们找到一组数里最大或者最小的值比我们直接暴力一个个去对比那种找法,快很多。我们一般用数组来创建一个二叉堆。
插入操作
如果我要在上面的二叉堆中插入一个3,那么我可以先在堆底插入一个3
然后发现它的父节点比它大,不符合规律,那我们则进行对调的操作
这样我们便完成了插入操作。
int h[10010];//定义一个数组来创建二叉堆
void swap(int x,int y)//交换函数
{
int t;
t=h[x];
h[x]=h[y];
h[y]=t;
}
void situp(int i)//传入插入值的位置
{
int flag=0;
if(i==1)
return;
while(i!=1&&flag==0)
{
if(h[i]<h[i/2])
swap(i,i/2);
else
flag=1;
i=i/2;
}
}
删除操作
对于删除操作,比如
我想删除堆顶元素1,那么我可以直接用堆底的元素将堆顶的元素覆盖,因为我们是存放在数组里,再执行n–,然后根据最小堆特点再进行调换,这样就完成了删除操作。
void sitdown(int i)//这是向下调的函数
{
int t,flag=0;
while(i*2<=n&&flag==0)
{
if(h[i]>h[i*2])//找左右子节点看看有没有比当前节点小的
{
t=i*2;
}
else
t=i;
if(i*2+1<=n)
{
if(h[t]>h[i*2+1])
t=i*2+1;
}
if(t!=i)//如果有就进行交换
{
swap(t,i);
i=t;
}
else
flag=1;
}
}
void xiaochu()
{
h[1]=h[n];
n--;
sitdown(1);
}
如果需要不断输出当前最小值,那么只需要在删除函数里加几行代码,就可以
int xiaochu()
{
int t;
t=h[1];
h[1]=h[n];
n--;
sitdown(1);
return t;//返回堆顶的值
}
堆的创建
void creat()
{
int i;
for(i=n/2;i>=1;i--)
{
sitdown(i);
}
}
这种创建方法是先直接把所有数放入一个二叉堆中,然后从最后一个节点开始的,然后逐渐往上判断它的父节点是否比它小,如果不满足条件则进行向上调换的操作,直到整个二叉堆满足最小堆的条件为止。