存储方式
二叉堆用数组存储,从下标1开始,并且因为二叉堆为完全二叉树,所以除根节点外的任意节点 i 的父节点为 i / 2,除终端节点外任意节点 i 的 左孩子为 i * 2,右孩子为 i * 2 + 1(存在右孩子时)
性质
1 是一种特殊的完全二叉树。
2 根节点为优先度最大的数据,根节点的子节点优先度稍微低于根节点,以此类推,越往下优先度越低。优先度不一定为数学意义上的大小,根据实际情况选择。
3 基础的有两种堆,/根节点值最大的堆称为大根堆,反过来,根节点最小的称为小根堆。
插入
void charu(int x)
{
int f;
if(x<=1)
return;
while(x>1)
{
f=x/2;
if(s[x]<s[f])
swap(s[x],s[f]);
else
break;
x=f;
}
return;
}
删除
删除方式为直接将该结点后面所有结点的前移将其覆盖
int shanchu(int adress, int end)
{
int i;
for(i = adress; i <= end - 1; i++)
s[i] = s[i + 1];
end--;
return s[adress];
}
例题
以上两个为二叉堆的基本操作做,现在让我们来康康小初的例题吧
小初直通车
代码
这是小初晦涩的c++代码
#include <iostream>
#include <cstdio>
using namespace std;
int s[10010],n;
void xiaqu(int i)
{
int t,r,z;
while(i*2<n)
{
r=i*2;
z=i*2+1;
if(s[i]<s[r])
t=i;
else
t=r;
if(z<n&&s[t]>s[z])
t=z;
if(i!=t)
{
swap(s[i],s[t]);
i=t;
}
else
break;
}
return;
}
int quchu(void)//取出最小的数,即根结点,再将最后一个根节点并如第一个取整
{
int a;
a=s[1];
s[1]=s[n];
xiaqu(1);
n--;
return a;
}
void charu(int x)
{
int f;
if(x<=1)
return;
while(x>1)
{
f=x/2;
if(s[x]<s[f])
swap(s[x],s[f]);
else
break;
x=f;
}
return;
}
int main(void)
{
int i,j,he,a,b;
while(scanf("%d",&n)!=EOF)
{
he=0;
for(i=1; i<=n; i++)
scanf("%d",&s[i]);
for(i=n/2; i>0; i--)
xiaqu(i);
while(n>1)
{
a=quchu();
b=quchu();
he+=a+b;
n++;
s[n]=a+b;
charu(n);
}
printf("%d\n",he);
}
}