数据结构与算法 树 课后习题 选择题部分

1.下列说法正确的是:C

A.二叉树中任何一个结点的度都为2.

B.二叉树的度为2.

C.一棵二叉树的度可小于2

D.任何一棵二叉树中至少有一个结点的度为2.

分析:

二叉树可以有五种基本形态:

 所以任何一个结点的度不一定为2,A错,C错;

树的度:树中各节点度的最大值。

所以二叉树的度不一定为2,也可能为0或1,B错;

2.以二叉链表作为二叉树的存储结构,在具有n个结点的二叉链表中,空链域的个数为:C

A.2n-1

B.n-1

C.n+1

D.2n+1

分析:

例举法

比如有3个结点:

有四个空指针,所以选C。

理论分析:

一个具有n个结点的二叉树用二叉链表存储,那么有2n个指针域,其中有n-1个指针域用来存储结点孩子的位置,另外n+1个结点存放的是空指针。

这有点像小学的路灯问题,有5个路灯沿马路排列,每两个路灯相距3m,那么这五个路灯总共多长?

答案是:(5-1)*3=12

有n个结点的二叉树,那么就有n-1个边去连接它们,也就是n-1个指针域。

所以有n+1个空指针

3.线索化二叉树中,某结点*p没有孩子的充要条件是:B

A.p->lchild=NULL

B.p->ltag=1 && p->rtag=1

C.p->ltag=0

D.p->lchild=NULL && p->ltag=1

分析:

线索二叉树的结构:

定义:

typedef struct TNode* BinTree;
typedef struct TNode {
    char data;
    BinTree left;
    BinTree right;
    unsigned ltag;
    unsigned rtag;
};

 ltag为0时,lchild指向结点的左孩子;

ltag为1时,lchild指向结点的前驱结点;

 rtag为0时,rchild指向结点的右孩子;

rtag为1时,rchild指向结点的后继结点;

结点*p没有孩子代表着结点p的左孩子指向该节点的前驱结点,p的右孩子指向该结点的后继结点,故ltag与rtag均为1,B对。

在 A.p->lchild=NULL 中,因为是线索二叉树,一个结点左孩子不是指向下一个结点,就是指向该结点的前驱结点,不会为空。

在 C.p->ltag=0 中,p->ltag=0 代表结点p有左孩子。

在 D.p->lchild=NULL && p->ltag=1 中,同A,不会为空。

4.如果结点A有3个兄弟,而且B是A的双亲,则B的度为:B

A.3

B.4

C.5

D.1

分析:结点A是B的孩子,A有3个兄弟,那么B有4个孩子,所以B的度为4.


5.某二叉树T有n个结点,设按某种顺序对T中的每个结点进行编号,编号值为1,2,……,n。且有如下性质: T中任意结点v,其编号等于左子树上的最小编号减1, 而V的右子树的结点中,其最小编号等于v左子树上结点的最大编号加1,这是按  (   )编号的。B
A.中序遍历序列
B.先序遍历序列
C.后序遍历序列

D. 层次顺序

分析:还是例举法。


6.设F是一个森林,B是由F转换得到的二又树,F中有n个非终端结点,B中右指
针域为空的结点有( )个。C
A. n-1
B. n
C. n+1
D. n+2

分析:

例举法

终端结点(Terminal Nodes): 度数为零的结点就是树叶(叶子结点)也叫做终端结点。

非终端结点(Nonterminal Nodes): 终端结点以外的所有结点都是非终端结点。

7.一棵完全二叉树上有1001个结点,其中叶子结点的个数是:B

A.500

B.501

C.490

D.495

分析:

完全二叉树(Complete Binary Tree): 如果该二叉树的所有叶子结点都在最后一层或者倒数第二层,而且最后一层的叶子结点在左边连续,倒数第二层的叶子结点在右边连续,我们称为完全二叉树。

 所以设这棵完全二叉树有n层,那么它的n-1层是满二叉树。

深度为k的二叉树中,最多有 (2的k次方)-1 个结点。

当k=9时,最多有 (2的9次方)-1 个结点,,即512-1=511个结点,第9层有256个结点,第1---8层共有255个结点。

那么剩下的1001-511=490个结点排列在下一层第10层。

第10层上的每两个结点是第9层的一个结点的两个孩子,所以第9层中有490/2=245个结点有两个孩子,其余结点无孩子。

所以有490+(256-245)=501个结点。

8.设森林F有3棵树,第一,,第二和第三棵树的结点个数分别为N1,N2和N3,与森林F对应的二叉树根节点的右子树的结点个数为: D

A.N1

B.N1+N2

C.N2

D.N2+N3

分析:

n叉树转化为二叉树的方法:

将一个结点的左孩子连接这个结点的长子,右孩子连接这个结点的兄弟。

森林转化为二叉树的方法:

将森林中的树转化为二叉树,

将转化后的第一个二叉树的根节点的右孩子连接第二个二叉树的根节点,第二个二叉树的根节点的右孩子连接第三个二叉树的根节点,按这个规律连接完所有二叉树。

所以森林F对应的二叉树根节点的右子树是除了第一个树以外的其他树,所以结点个数是其他树的结点个数之和。

9.任何一棵二叉树的叶节点在先序,中序和后序遍历顺序的相对次序:A

A.不发生改变

B.发生改变

C.不确定

D.以上都不对

分析:

代码运行一遍就记住了

在这里用了一下这个的代码来创建树,并用迭代法进行遍历:

4-14 还原二叉树&&4-15 根据后序和中序遍历输出先序遍历

生成的树是这样的:

#include<iostream>
#include<vector>
#include<stack>
using namespace std;

typedef struct TNode* BinTree;
typedef struct TNode {
    char data;
    BinTree left;
    BinTree right;

    TNode(char(x)) :data(x), left(NULL), right(NULL) {};
    TNode(char(x), BinTree(l), BinTree(r)) :data(x), left(l), right(r) {};
};

BinTree get(char preod[], char inod[], int len) {
    int i;
    if (len <= 0) {
        return NULL;
    }
    BinTree t = new TNode(preod[0]);
    for (i = 0; inod[i] != preod[0]; i++);
    t->left = get(preod + 1, inod, i);
    t->right = get(preod + i + 1, inod + i + 1, len - i - 1);
    return t;
}

vector<char> preod(BinTree BT) {
    vector<char> result;
    stack<BinTree> st;
    if (BT != NULL) {
        st.push(BT);
    }

    while (!st.empty()) {

        BinTree temp = st.top();
        if (temp != NULL) {
            st.pop();
            if (temp->right) {
                st.push(temp->right);
            }
            if (temp->left) {
                st.push(temp->left);
            }

            st.push(temp);
            st.push(NULL);
        }
        else {
            st.pop();
            temp = st.top();
            st.pop();
            result.push_back(temp->data);
        }
    }
    return result;
}

vector<char> midod(BinTree BT) {
    vector<char> result;
    stack<BinTree> st;
    if (BT != NULL) {
        st.push(BT);
    }

    while (!st.empty()) {

        BinTree temp = st.top();
        if (temp != NULL) {
            st.pop();
            if (temp->right) {
                st.push(temp->right);
            }

            st.push(temp);
            st.push(NULL);

            if (temp->left) {
                st.push(temp->left);
            } 
        }
        else {
            st.pop();
            temp = st.top();
            st.pop();
            result.push_back(temp->data);
        }
    }
    return result;
}

vector<char> rearod(BinTree BT) {
    vector<char> result;
    stack<BinTree> st;
    if (BT != NULL) {
        st.push(BT);
    }

    while (!st.empty()) {

        BinTree temp = st.top();
        if (temp != NULL) {
            st.pop();

            st.push(temp);
            st.push(NULL);

            if (temp->right) {
                st.push(temp->right);
            }

            if (temp->left) {
                st.push(temp->left);
            }

        }
        else {
            st.pop();
            temp = st.top();
            st.pop();
            result.push_back(temp->data);
        }
    }
    return result;
}


int main()
{
    int n;
    scanf("%d", &n);
    char s1[200], s2[200];
    scanf("%s", &s1);
    scanf("%s", &s2);

    BinTree root = get(s1, s2, n);

    printf("先序:");
    vector<char> result1 = preod(root);
    for (int i = 0; i < result1.size(); i++) {
        if (result1[i] == 'F' || result1[i] == 'H' || result1[i] == 'I' || result1[i] == 'E' || result1[i] == 'C') {
            cout << '*' << result1[i] << '*' << " ";
        }
        else {
            cout << result1[i] << " ";
        }
    }

    printf("\n中序:");
    vector<char> result2 = midod(root);
    for (int i = 0; i < result2.size(); i++) {
        if (result2[i] == 'F' || result2[i] == 'H' || result2[i] == 'I' || result2[i] == 'E' || result2[i] == 'C') {
            cout << '*' << result2[i] << '*' << " ";
        }
        else {
            cout << result1[i] << " ";
        }
    }

    printf("\n后序:");
    vector<char> result3 = rearod(root);
    for (int i = 0; i < result3.size(); i++) {
        if (result3[i] == 'F' || result3[i] == 'H' || result3[i] == 'I' || result3[i] == 'E' || result3[i] == 'C') {
            cout << '*' << result3[i] << '*' << " ";
        }
        else {
            cout << result1[i] << " ";
        }
    }

    return 0;
}

 运行结果:

10.若一棵二叉树的后序遍历序列为dabec,中序遍历序列为debac,则先序遍历序列为:D

A.cbed

B.decab

C.deabc

D. cedba

11.若一棵二叉树的先序遍历序列为abdgcefh,中序遍历序列为dgbaechf,则后序遍历序列为:D

A.gcefha

B.gdbecfha

C.bdgaechf

D.gdbehfca

分析:第10题和第11题一样的,可以参考这个:

4-14 还原二叉树&&4-15 根据后序和中序遍历输出先序遍历

12.一棵非空二叉树的先序遍历序列与后序遍历序列正好相反,则该二叉树一定满足:C

A.所有结点均无左孩子

B.所有结点均无右孩子

C.只有一个叶子结点

D.是一棵满二叉树

分析:

这个我还不明白咋求出来的。。。

以后补上

13.设高度为h的二叉树上只有度为0和度为2的结点,则此类二叉树中所包含的结点个数至少为:B

A.2*h

B.2*h-1

C.2*h+1

D.h+1

14.一个具有567个结点的二叉树的高h为:D

A.9

B.10

C.9--566

D.10--567

15.给一个整数集合{3,5,6,7,9},与该整数集合对应的哈夫曼树为:B

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值