六、树的应用
1、利用树型结构求解集合的幂
求集合{1,2,…,n}的幂集问题是一个经典的问题。解决这个问题的最典型做法就是递归调用。利用树型结构这个参照系来设计求集合{1,2,…,n}的幂集算法,对于给定的集合{1,2,3,4},按幂集集合中的元素个数和字典次序建立的树如下:
{}
{1} {2} {3} {4}
{1,2} {1,3} {1,4} {2,3}{2,4} {3,4}
{1,2,3}{1,2,4} {1,3,4}
{1,2,3,4}
为保持集合中元素的字典次序,可采用两种方法来求集合{1,2,3,4}的幂集集合,其中一是采用先序遍历树;其二是按层次遍历树。特别要注意的是在设计求集合的幂集时并不建立真正的树,而是建立这样一个虚拟的树,并以这棵树为参照系。下面给出这两种方法的算法。
方法一:先序遍历虚拟树
Power(int a[],int n,int i)
/*用数组记录集合{1,2,…,n}的一个幂集,a[0]记录当前幂集的元素个数*/ /*i+1表示将要加入到a中的元素*/
{
int i,k;
if(a[0]= =0)
{
printf(“()”);
}
else
{
printf(“{“};
for(j=1;j<a[0];j++)
{
printf(“%d,”,a[j]);
}
printf(“%d)”,a[a[0]]);
}
For(j=i+1;j<=n;j++)
{
k=a[0];
a[0]++;
a[a[0]]=j;
power(a,n,j);
a[0]=k;
}
}
方法二:按层次遍历虚拟树
#define Maxsize 4
#define QMax 32
typedef struce node
{
int set[Maxsize]; /*队列的一个元素*/
int count; /*当前层次*/
}Qelem;
power(int n)
/*用数组记录集合{1,2,…,n}的一个幂集*/
{
int i,j,k,front,rear; /*front表示队头,rear表示队位*/
Qelem a[QMax]; /*申请队列*/
printf(“{}”); /*打印空集*/
front=rear=0;
for(j=1;j<=n;j++)
{
rear=(rear+1)%QMax;
a[rear].count=1;
a[rear].set[0]=j;
}
while(rear!=front) /*队列不空*/
{
front=(front+1)%QMax;
printf(“{“};
for(j=0;j<a[front].count-1;j++) /*打印队头元素列*/
{
printf(“%d,”,a[front].set[j]);
}
printf(“%d)”,a[front].set[j]);
k=a[front].set[j];
for(j=k+1;j<=n;j++) /*下一层元素进队列*/
{
rear=(rear+1)%QMax;
a[rear].count=a[front].count+1;
for(i=0;i<a[front].count;i++)
{
a[rear].set[i]=a[front].set[i];
}
a[rear].set[i]=j;
}
}/* while(rear!=front)*/
}