数据结构与算法分析--c语言描述(原书第二版)练习自答(第八章)

8.1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

8.2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

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} 2H1个节点,那么两棵树union之后则至少有 2 H 2^H 2H个节点,得证。因此,拥有N个节点的树最多深度为 O ( l o g N ) O(logN) O(logN)

8.5

待完成

8.6

1
2
3
4
5
6
7
8
9

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

  1. 只需要一个栈,每次union时就将两个根以及它们的值压栈,在执行Deunion时就出栈,并恢复两个根的值就好。
  2. 因为路径压缩会让元素移出它原本所在的子树。
  3. 待完成

8.9

待完成

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值