摘要:顺序二叉树占用空间大而又插入删除不便,讨论二叉树压缩存储的文章并不多见。但顺序二叉树的查找非常方便。本文提供了一种基于叶结点的位置对二叉树的压缩存储,称为叶结点位置法。
这种算法依据了二叉树的以下基本性质:
2、如果对一棵有N个结点的完全二叉树的结点按层序排列,从1开始编号,则对任一编号为i的结点,如果其左、右孩子结点,则它们的编号分别为2i,2i+1。
这个方法的基本思路是:二叉树的任一结点都是叶结点或叶结点的的父结点/祖父结点。把一棵任意的二叉树补充为完全二叉树后并按层序从1开始编号,则原二叉树中任一结点的编号都可以根据叶子结点的编号计算出来。
例如,下图是一棵简单二叉树。
其用叶结点位置法压缩的结果是:
a[6]=[a,b,c,d,e,f];
b[3]=[2,6,15]
a[]为结点的data信息,b[]中的2,6,14分别为叶结点b,d,f在将该二叉树补充为完全二叉树时的层次遍历编号。结点a,c,e的编号可以通过其叶结点的编号计算出来。例如,结点e的编号为int (15/2)=7。
下面的算法实现了将压缩存储的二叉树还原成出非空结点的序号。根据叶结点的位置信息a[]计算出二叉树中非空结点的位置信息,并按倒序存储在数组b[]中。
下面编码在TurboC2.0中测试通过。
#include <stdio.h>
void main()
{
int a[6]={0,4,5,13,24,60};
int b[15]={0};
int j=0;
int left,middle,right,k;
int n=5;
clrscr();
b[0]=a[n];
j++;
while(n>1)
{
a[n]=a[n]/2;
a[0]=a[n];
left=1;right=n-1;
while(left<=right)
{
middle=(left+right)/2;
if (a[0]<a[middle])
right=middle-1;
else
left=middle+1;
}
if (a[n]==a[left-1]&&left!=1)
{
n--;
}
else
{
for(k=n-1;k>=left;k--)
a[k+1]=a[k];
a[left]=a[0];
}
b[j]=a[n];
j++;
}
for(j=0;j<15;j++)
printf("%d\n",b[j]);
}