第五章 树和二叉树
一、单项选择题
1.关于二叉树的下列说法正确的是 (1)。
(1):A.二叉树的度为2 B.二叉树的度可以小于2
C.每一个结点的度都为2 D.至少有一个结点的度为
2.设深度为h(h>0)的二叉树中只有度为0和度为2的结点,则此二叉树中所含的结点总数至少为 (2)。
(2)A.2h B.2h-1 C.2h+1 D.h+1
3.在树中,若结点A有4个兄弟,而且B是A的双亲,则B的度为 (3) 。
(3):A.3 B.4 C.5 D.6
4.若一棵完全二叉树中某结点无左孩子,则该结点一定是 (4) 。
(4):A.度为1的结点 B.度为2的结点 C.分支结点 D.叶子结点
5.深度为k的完全二叉树至多有 (5) 个结点,至少有 (6) 个结点。
(5)-(6):A.2k-1-1 B.2k-1 C.2k-1 D.2k
6.前序序列为ABC的不同二叉树有 (7) 种不同形态。
(7):A.3 B.4 C.5 D.6
7.若二叉树的前序序列为DABCEFG,中序序列为BACDFGE,则其后序序列为 (8) ,层次序列为 (9) 。
(8)-(9):A.BCAGFED B.DAEBCFG C.ABCDEFG D.BCAEFGD
8.在具有200个结点的完全二叉树中,设根结点的层次编号为1,则层次编号为60的结点,其左孩子结点的层次编号为 (10) ,右孩子结点的层次编号为 (11) ,双亲结点的层次编号为 (12)。
(10)-(12):A.30 B.60 C.120 D.121
9.遍历一棵具有n个结点的二叉树,在前序序列、中序序列和后序序列中所有叶子结点的相对次序 (13) 。
(13):A.都不相同 B.完全相同 C.前序和中序相同 D.中序与后序相同
10.在由4棵树组成的森林中,第一、第二、第三和第四棵树组成的结点个数分别为30,10,20,5,当把森林转换成二叉树后,对应的二叉树中根结点的左子树中结点个数为 (14) ,根结点的右子树中结点个数为 (15) 。
(14)—(15):A.20 B.29 C.30 D.35
11.具有n个结点(n>1)的二叉树的前序序列和后序序列正好相反,则该二叉树中除叶子结点外每个结点 (16) 。
(16):A.仅有左孩子 B.仅有右孩子 C.仅有一个孩子 D.都有左、右孩子
12.判断线索二叉树中p结点有右孩子的条件是 (17) 。
(17):A.p!=NULL B.p->rchild!=NULL C.p->rtag=0 D.p->rtag=1
13.将一棵树转换成二叉树,树的前根序列与其对应的二叉树的 (18) 相等。树的后根序列与其对应的二叉树的 (19)相同。
(18)—(19):A.前序序列 B.中序序列 C.后序序列 D.层次序列
14.设数据结构(D,R),D={dl,d2,d3,d4,d5,d6},R={<d4,d2>,<d2,d1>,<d2,d3>,<d4,d6>,<d6,d5>},这个结构的图形是 (20) ;用 (21) 遍历方法可以得到序列{d1,d2,d3,d4,d5,d6}。
(20):A.线性表 B.二叉树C.队列 D.栈
(21):人前序 B.中序 C.后序 D.层次
15.对于树中任一结点x,在前根序列中序号为pre(x),在后根序列中序号为post(x),若树中结点x是结点y的祖先,下列 (22) 条件是正确的。
(22):A.pre(x)<pre(y)且post(x)<post(y)
B.pre(x)<pre(y)且post(x)>post(y)
C. pre(x)>pre(y)且post(x)<post(y)
D.pre(x)>pre(y)且post(x)>post(y)
16.每棵树都能惟一地转换成对应的二叉树,由树转换的二叉树中,一个结点N的左孩子是它在原树对应结点的 (23) ,而结点N的右孩子是它在原树里对应结点的 (24) 。
(23)—(24):A.最左孩子 B.最右孩子 C.右邻兄弟 D.左邻兄弟
17.二叉树在线索化后,仍不能有效求解的问题是 (25) 。
(25):A.前序线索树中求前序直接后继结点
B.中序线索树中求中序直接前驱结点
C.中序线索树中求中序直接后继结点
D.后序线索树中求后序直接后继结点
18.一棵具有124个叶子结点的完全二叉树,最多有 (26)个结点。
(26):A.247 B.248 C.249 D.250 。
19.实现任意二叉树的后序遍历的非递归算法而不使用栈结构,最有效的存储结构是采用 (27) 。
(27):A. 二叉链表 B.孩子链表 C.三叉链表 D.顺序表
二、填空题
1.树中任意结点允许有 (1)孩子结点,除根结点外,其余结点 (2) 双亲结点。
2.若一棵树的广义表表示为A(B(E,F),C(C(H,I,J,K),L),D(M(N)))。则该树的度为 (3) ,树的深度为 (4) ,树中叶子结点个数为 (5) 。
3.若树T中度为1、2、3、4的结点个数分别为4、3、2、2,则T中叶子结点的个数是 (6) 。
4.一棵具有n个结点的二叉树,若它有m个叶子结点,则该二叉树中度为1的结点个数是 (7) 。
5.深度为k(k>0)的二叉树至多有 (8) 个结点,第i层上至多有 (9) 个结点。
6.已知二叉树有52个叶子结点,度为1的结点个数为30则总结点个数为 (10) 。
7.已知二叉树中有30个叶子结点,则二叉树的总结点个数至少是 (11) 。
8.高度为6的完全二叉树至少有 (12) 个结点。
9.一个含有68个结点的完全二叉树,它的高度是 (13) 。
10.已知一棵完全二叉树的第6层上有6个结点(根结点的层数为1),则总的结点个数至少是 (14) ,其中叶子结点个数是 (15) 。
11.已知完全二叉树第6层上有10个叶子结点,则这棵二叉树的结点总数最多是 (16) 。
12.一棵树转换成二叉树后,这棵二叉树的根结点一定没有 (17) 孩子,若树中有m个分支结点,则与其对应的二叉树中无右孩子的结点个数为 (18) 。
13.若用二叉链表示具有n个结点的二叉树,则有 (19) 个空链域。
14.具有m个叶子结点的哈夫曼树,共有 (20)个结点。
15.树的后根遍历序列与其对应的二叉树的 (21) 遍历序列相同。
16.线索二叉树的左线索指向其 (22) ,右线索指向其 (23) 。
三、应用题
1.具有n个结点的满二叉树的叶子结点个数是多少?
2.列出前序遍历序列是ABC的所有不同的二叉树。
3.已知二叉树的层次遍历序列为ABCDEFGHIJK,中序序列为DBGEHJACIKF,请构造一棵二叉树。
4.已知二叉树的中序遍历序列是ACBDGHFE,后序遍历序列是ABDCFHEG,请构造一棵二叉树。
5.已知二叉树的前序、中序和后序遍历序列如下,其中有一些看不清的字母用表示,请先填写处的字母,再构造一棵符合条件的二叉树,最后画出带头结点的中序线索链表。
(1)前序遍历序列是:BCG
(2)中序遍历序列是:CBEAGH*
(3)后序遍历序列是:*EDB**FA
6.将下图所示的森林转换成一棵二叉树,并画出这棵二叉树的顺序存储结构。
7.将下图所示的二叉树还原成森林。
8.对于给定的一组权值{3,5,6,7,9},请构造相应的哈夫曼树,并计算其带权路径长度。
四、算法设计题
1.请设计一个算法,求以孩子兄弟链表表示的树中叶子结点个数。
2.请编写一个算法,实现将以二叉链表存储的二叉树中所有结点的左、右孩子进行交换。
3.请编写一个算法,将以二叉链表存储的二叉树输出其广义表表示形式。
4.请编写一个算法,判断以二叉链表存储的二叉树是否为完全二叉树。
5.假设二叉树采用链接存储方式存储,编写一个二叉树先序遍历和后序遍历的非递归算法。…
6.已知一棵二叉树用二叉链表存储,t指向根结点,p指向树中任一结点。请编写一个非递归算法,实现求从根结点t到结点p之间的路径。
参考答案
第五章
一、单项选择题
(1)-(5)BBCDC (6)-(10)BCABC (11)—(15)DABBD (16)-(19)CCABB
(20)-(24) BBBAC (25)-(27)DBC
二、填空题
(1)有零个或多个 (2)有且仅有一个
(3)根据树的广义表表示,可以画出这棵村,该树的度为4。
(4)树的深度为4
(5)树中叶子结点个数为8
(6)n0=14 (7)n-2m+1 (8)2k-1 (9)2i-1 (10)133 (11)59
(12)25=32 (13)log2(n+1)=log269=7 (14) 25-1+6=37 (15) 19
(16)27-1-20=107 (17)右 (18)m+1 (19)n+1 (20) 2m-1
(21)中序 (22)直接前驱结点 (23)直接后继结点
三、应用题
1.具有n个结点的满二叉树中只有度为2和度为0的结点,故n=2n0-1,n0=(n+1)/2。
5.构造一棵二叉树应该先确定根结点,由后序序列最后一个字母A确定根结点,可将前序序列的第一个字母改为A。在中序遍历序列中A的左子树中含4个字母,右子树中含3个字母,在后序遍历序列中左子树的后序遍历子序列为EDB,可将左子树的后序遍历序列和中序遍历序列互相补足,分别是CEDB和CBDE。由这两个子序列可知左子树的根结点为B,D又为以B为根结点的右子树的根结点,E为D的右孩子,所以在前序序列中A的左子树的前序序列为:BCDE,在根结点A的右子树中,由后序遍历序列可确定其根结点为F,再确定其中序序列为GHF,进一步确定其前序序列为FGH,补足*处后,三个遍历序列为:
(1)前序遍历序列是:ABCDEFGH
(2)中序遍历序列是:CBDEAGHF
(3)后序遍历序列是:CEDBHGFA
由前序遍历序列和中序遍历序列可构造一棵二叉树如右图。
四、算法设计题
1.求叶子结点个数。
算法描述如下:
int leafnum(Csnode *t,int n)
{Gsnode *p;
if(tNULL) return 0;
p=t->fc;
if(pNULL)
n++;
while§
{n=leaf(p,n);
p=p->ns;
}
return n;
}
2.交换左右孩子。算法如下:
void exchange(Btnode *t)
{Btnode *p;
if(t)
{exchange(t->lchild);
exchange(t->rchild);
if(t->lchild||t->rchild)
{p=t->lchild;
t->lchild=t->rchild;
t->rchild=p;}
}
}
3.void printbtree(Btnode *r)
{if®
{printf(“%c”,r->data);
if(r->lchild||r->rchild)
printf(“(”);
printbtree(r->lchild);
if(r->rchild)
printf(“,”);
printbtree(t->rchild);
printf(“)”);
}
}
4. #define MAX 100
int checkt(Btnode t)
{Btnode s[MAX];
int i,n=0;
for(i=0;i<MAX,i++)
s[i]=NULL;
if(t==NULL)
return 0;
i=0;
S[0]=t;
While(I<=n)
{if(!s[i])
return 0;
if(s[i]->lchild)
{n=2i+1;
s[n]=s[i]->lchild;
}
if(s[i]->rchild)
{n=2i+2;
s[n]=s[i]->rchild;
}
i++;
}
return 1;
}
5.(1)前序遍历二叉树的非递归算法的基本思想是:从二叉树的根结点开始,沿左支一直走到没有左孩子的结点为止,在走的过程中访问所遇结点,并把非空右孩子进栈。当找到没有左孩子的结点时,从栈顶退出某结点的右孩子,此时该结点的左子树已遍历结束,然后按上述过程遍历该结点的右子树,如此重复,直到二叉树中所有结点都访问完毕为上。算法如下:
void preorder(Btnode *t)
{ int I=0;
Btnode *p,*s[M];
P=t;
Do
{ while§
{printf(“%c\t”,p->data);
if(p->rchild!=NULL)
s[i++]=p->rchild;
p=p->lchild;
}
if(i>0)
p=s[–i];
}while(i>0||p!=NULL);
}
(2)后序遍历二叉树的非递归算法的基本思想:采用一个栈保存返回的结点,先遍历根节点的所有结节点并入栈,出栈一个结点,然后遍历该结点的右结点并入栈,再遍历该右结点的所有左结点并入栈,当一个结点的左右子树均访问后再访问该结点,如此这样,直到栈为空为止。其中的难点是如何判断一个结点t的右结点已访问过,为此用p保存已访问过的结点(初值为NULL),若t->right=p成立(在后序遍历中,t的右节点一定是在t之前访问),说明t的左右子树均已访问,现在应访问t。算法如下:
void postorder(Btree *t)
{ Btree s[maxsize];
Btree p;
int flag,top=-1;
Do
{ while(t)
{ top++;
s[top]=t;
t=t->left;
}
p=NULL;
flag=1;
while(top=-1&&flag)
{ t=s[top];
if(t->rightp)
{ printf(“%d””,t->data);
top–;
p=t;
}
else
{ t=t->right;
flag=1;
}
}
}while(top!=-1)
}
6.求二叉树中从根结点到p结点之间路径长度的算法描述如下:
#define MAX 100
void path(Btnode *t,Btnode *p)
{ Btnode *s[MAX],*q=t;
int b[MAX],top=-1;
do {
while(q)
{s[++top]=q;
b[top]=0;
q=q->lchild;
}
if(top->-1&&b[top]1)
{q=s[top];
if(qp)
{printf(“根结点到q结点的路径是:”);
for(I=0;I<=top;I++)
printf(“%c”,s[I]->data);
return;
}
else top–;
}
if(top>-1)
{ p=s[top]->rchild;
b[top]=1;
}
}while(top>0);
}
7.判断以二叉链表存储的二叉树是否为完全二叉树的算法描述如下:
#define MAX 100
void checkt(BTnode *t)
{ Btnode *s[MAX];
int i,n=0;
for(i=0;i<MAX;i++)
s[i]=MAX;
if(tNULL)
return 0;
s[0]=t;
while(i<=n)
{ if(!s[i])
return 0;
if(s[i]->lchild)
{ n=2i+1;
s[n]=s[i]->lchild;
}
if(s[i]->rchild)
{ n=2i+2;
s[n]=s[i]->rchild;
}
i++;
}
return 1;
}