用二叉树的思想解释堆
下面有一个二叉树,这个二叉树非常特殊。因为它每一片叶子上的数值与叶子的深度正相关(即上面的永远小于下面的,左右无关),这样的树我们称为堆。我们把这一堆值放入数组里:a[15]={1,2,3,4,5,6,7,8,9...}
现在我们有一个新的叶子20
现在我们要删除最小的叶片,并插入这个新叶片,再找最小的叶片。
但对于数组,接下来就不好操作了,一般的方法是把新叶片放入原本1
所i在的位置,再遍历一遍找到最小的数。这里我们有15次循环才能结束。
但如果用二叉树就可以走捷径。
怎么用二叉树走捷径?
还是这张图,我们先把1
去掉并把20
放入:
20
与下面较小的2
作比较发现2
更小,交换20
与2
:
其实到这里就已经结束了,但为了保证这还是一个堆,我们继续比较下面较小的,经过几次操作我们得到了最终结果:
这样明显比之前的方法简单而且清楚。
首先构造这个堆并,输入要替换的数:
int i=0,num;
do{
n++;
i++;
scanf("%d",&a[i]);
}while(a[i]!=-1);
scanf("%d",&num);
a[1]=num;
之后将这个数一个一个向下比较:
int t,flag=0;
while(i*2<=n&&flag==0){
if(a[i]>a[i*2])
t=i*2;
else
t=i;
if(i*2+1<=n){
if(a[t]>a[i*2+1])
t=i*2+1;
}
if(t!=i){
swap(t,i);
i=t;
}
else
flag=1;
}
最后printf
就能看到结果。
下面是完整代码:
#include<stdio.h>
int a[101],n=-1;
void swap(int x,int y)
{
int t;
t=a[x];
a[x]=a[y];
a[y]=t;
}
void tree(int i)
{
int t,flag=0;
while(i*2<=n&&flag==0){
if(a[i]>a[i*2])
t=i*2;
else
t=i;
if(i*2+1<=n){
if(a[t]>a[i*2+1])
t=i*2+1;
}
if(t!=i){
swap(t,i);
i=t;
}
else
flag=1;
}
}
int main()
{
int i=0,num;
do{
n++;
i++;
scanf("%d",&a[i]);
}while(a[i]!=-1);
scanf("%d",&num);
a[1]=num;
tree(1);
for(i=1;i<=n;i++){
printf("%d ",a[i]);
}
}