8.1
8.2
8.3
参考8.2
8.4
我们可以证明一个高H的树至少有 2 H 2^H 2H个节点。通过归纳法,很显然,当树高度为0时最少有一个节点,当树高度为1时,最少有2个节点。设T是高度为H的树的最少的节点数。那么在通过union形成这棵树的前一步,则树必然高为H-1,因为如果不是这样的话,那么这棵树的高为H二拥有的节点数比T少,与假设矛盾。同时,因为这一次union导致树的高度更新为H,所以union的另一棵树的高位也是H-1。根据归纳假设,高度为H-1的树,至少有 2 H − 1 2^{H-1} 2H−1个节点,那么两棵树union之后则至少有 2 H 2^H 2H个节点,得证。因此,拥有N个节点的树最多深度为 O ( l o g N ) O(logN) O(logN)。
8.5
待完成
8.6
8.7
//在第一行输入一个正整数作为网络中计算机的数量,接下来每一行输入如I 1 3,代表输入编号1与编号3的计算机的连接。输入C 1 3,代表检查编号1与编号3的计算机的连接。S代表程序结束,程序结束时会输出网络中存在几个联通分支。
#include <stdio.h>
#include <limits.h>
#define MaxSize 10000
int Array[MaxSize+1];
void DeleteWrap(void);
int Find(int index);
void Union(int val1,int val2);
int main(void)
{
char opt;
int index,N,val1,val2,count=0;
for(index=0;index<MaxSize+1;index++)
Array[index]=INT_MIN;
scanf("%d",&N);
DeleteWrap();
for(index=1;index<=N;index++)
Array[index]=-1;
opt=getchar();
while(opt!='S')
{
scanf("%d %d",&val1,&val2);
DeleteWrap();
if(opt=='C')
{
if(Find(val1)==Find(val2))
puts("yes");
else
puts("no");
}
else if(opt=='I')
{
Union(Find(val1),Find(val2));
}
else
fprintf(stderr,"Program error!\n");
opt=getchar();
}
for(index=1;index<=N;index++)
{
if(Array[index]<0)
count++;
}
if(count==1)
printf("The network is connected.\n");
else
printf("There are %d components.\n",count);
return 0;
}
void DeleteWrap(void)
{
char ch;
while((ch=getchar())!='\n')
;
}
int Find(int index)
{
while(Array[index]>=0)
index=Array[index];
return index;
}
void Union(int val1,int val2)
{
int root1,root2;
root1=Find(val1);
root2=Find(val2);
if(Array[root1]>Array[root2])
{
Array[root1]=root2;
}
else if(Array[root1]<=Array[root2])
{
if(Array[root1]==Array[root2])
Array[root1]--;
Array[root2]=root1;
}
}
8.8
- 只需要一个栈,每次union时就将两个根以及它们的值压栈,在执行Deunion时就出栈,并恢复两个根的值就好。
- 因为路径压缩会让元素移出它原本所在的子树。
- 待完成
8.9
待完成