第六章 树及二叉树
一、判断题
(√)1. 若二叉树用二叉链表作存贮结构,则在n个结点的二叉树链表中只有n—1个非空指针域。
(×)2.二叉树中每个结点的两棵子树的高度差等于1。
(√)3.二叉树中每个结点的两棵子树是有序的。
(×)4.二叉树中每个结点有两棵非空子树或有两棵空子树。
(×)5.二叉树中每个结点的关键字值大于其左非空子树(若存在的话)所有结点的关键字值,且小于其右非空子树(若存在的话)所有结点的关键字值。(应当是二叉排序树的特点)
(×)6.二叉树中所有结点个数是2k-1-1,其中k是树的深度。(应2i-1)
(×)7.二叉树中所有结点,如果不存在非空左子树,则不存在非空右子树。
(×)8.对于一棵非空二叉树,它的根结点作为第一层,则它的第i层上最多能有2i—1个结点。(应2i-1)
(√)9.用二叉链表法(link-rlink)存储包含n个结点的二叉树,结点的2n个指针区域中有n+1个为空指针。
(√)10.具有12个结点的完全二叉树有5个度为2的结点。
(( ) 11、哈夫曼树中没有度为1的结点,所以必为满二叉树。
(( )12、在哈夫曼树中,权值最小的结点离根结点最近。
(( )13、线索二叉树是一种逻辑结构。
(√ )14、深度为K的完全二叉树至少有2K-1个结点。
(√ )15、具有n个结点的满二叉树,其叶结点的个数为(n+1)/2。
(√ )16、前序和中序遍历用线索树方式存储的二叉树,不必使用栈。
(╳ )17、哈夫曼树是带权路径长度最短的树,路径上权值较大的点离根较远。
(√)18、在二叉树结点的先序序列和后序序列中,所有叶子结点的先后顺序完全相同。
(√)19、二叉树的遍历操作实际上是将非线性结构线性化的过程
(√)20、树的先根遍历序列与其所转化的二叉树的先序遍历序列相同。
(╳)21、树的后根遍历序列与其所转化的二叉树的后序遍历序列相同。
二、填空
1. 由3个结点所构成的二叉树有 5 种形态。
2. 线索二元树的左线索指向其_前驱_____,右线索指向其__后继____。
3. 一棵具有257个结点的完全二叉树,它的深度为 9 。
4、如某二叉树有20个叶子结点,有30个结点仅有一个孩子,则该二叉树的总结点数为_69_____。
5. 设一棵完全二叉树具有1000个结点,则此完全二叉树有 500 个叶子结点,有 499 个度为2的结点,有 1 个结点只有非空左子树,有 0 个结点只有非空右子树。
答:最快方法:用叶子数=[n/2]=500 ,n2=n0-1=499。 另外,最后一结点为2i属于左叶子,右叶子是空的,所以有1个非空左子树。完全二叉树的特点决定不可能有左空右不空的情况,所以非空右子树数=0.
6. 一棵含有n个结点的k叉树,可能达到的最大深度为 n ,最小深度为 2 。
7. 若已知一棵二叉树的前序序列是BEFCGDH,中序序列是FEBGCHD,则它的后序序列必是 F E G H D C B 。
8. 具有256个结点的完全二叉树的深度为__ 9 ____。
9. 在二叉树中,指针p所指结点为叶子结点的条件是_ p->lchild==null && p->rchlid==null 。
10、N个结点的二叉树采用二叉链表存放,共有空链域个数为n+1
11、深度为6(根层次为1)的二叉树至多有26 – 1 个结点。
12、平衡二叉树中某一结点左子树的深度减去右子树的深度称为该结点的__平衡因子__。
三、选择题
1.某二叉树结点的中序序列为A、B、C、D、E、F、G,后序序列为B、D、C、A、F、G、E,则其左子树中结点数目为(C)
A)3 B)2 C)4 D)5
2.二叉树是非线性数据结构,所以( C )。
A、它不能用顺序存储结构存储; B、它不能用链式存储结构存储;
C、顺序存储结构和链式存储结构都能存储; D、顺序存储结构和链式存储结构都不能使用
3.具有n(n>0)个结点的完全二叉树的深度为( C )。
(A) (log2(n)( (B) ( log2(n)( (C) ( log2(n) (+1 (D) (log2(n)+1(
4.把一棵树转换为二叉树后,这棵二叉树的形态是( A )。
(A)唯一的 (B)有多种
(C)有多种,但根结点都没有左孩子 (D)有多种,但根结点都没有右孩子
5. 下述二叉树中,哪一种满足性质:从任一结点出发到根的路径上所经过的结点序列按其关键字有序(D)。
A.二叉排序树 B.哈夫曼树 C.AVL树 D.堆
6线索二叉树是一种( C )结构。
A. 逻辑 B. 逻辑和存储 C. 物理 D.线性
7、将一棵有100个结点的完全二叉树从根这一层开始,每一层从左到右依次对结点进行编号,根结点编号为1,则编号为49的结点的左孩子的编号为( A)
A、98 B、99 C、50 D、48
8、设森林F中有三棵树,第一、第二和第三棵树的结点个数分别为M1、M2和M3。与森林F对应的二叉树根结点的右子树上的结点个数是(D)
A)M1 B)M1+M2 C)M3 D)M2+M3
9、将一棵有100个结点的完全二叉树从根开始,每一层从左到右依次对结点进行编号,根结点编号为1,则编号最大的非叶结点的编号为(C)
A、48 B、49 C、50 D、51
10、引入二叉线索树的目的是( A )
A、加快查找结点的前驱或后继的速度 B、为了能在二叉树中方便的进行插入与删除
C、为了能方便的找到双亲 D、使二叉树的遍历结果唯一
11.若一棵二叉树具有10个度为2的结点,5个度为1的结点,则度为0的结点个数是( B )
A.9 B.11 C.15 D.不确定
12. 一棵树高为K的完全二叉树至少有( C )个结点
A.2k –1 B. 2k-1 –1 C. 2k-1 D. 2k
13.设森林F中有三棵树,第一,第二,第三棵树的结点个数分别为M1,M2和M3。与森林F对应的二叉树根结点的右子树上的结点个数是( D )。
A.M1 B.M1+M2 C.M3 D.M2+M3
14.一棵二叉树的前序遍历序列为ABCDEFG,它的中序遍历序列可能是( B )
A.CABDEFG B.ABCDEFG C.DACEFBG D.ADCFEG
15. 有关二叉树下列说法正确的是( B )
A.二叉树的度为2 B.一棵二叉树的度可以小于2
C.二叉树中至少有一个结点的度为2 D.二叉树中任何一个结点的度都为2
16. 一个具有1025个结点的二叉树的高h为( C )
A.11 B.10 C.11至1025之间 D.10至1024之间
17.一棵二叉树高度为h,所有结点的度或为0,或为2,则这棵二叉树最少有( B )结点
A.2h B.2h-1 C.2h+1 D.h+1
18.对于有n 个结点的二叉树, 其高度为(D )
A.nlog2n B.log2n C.log2n|+1 D.不确定
19. 一棵具有 n个结点的完全二叉树的树高度(深度)是( A )
A.logn+1 B.logn+1 C.logn D.logn-1
20. 已知某二叉树的后序遍历序列是dabec, 中序遍历序列是debac , 它的前序遍历是( D )。
A.acbed B.decab C.deabc D.cedba
21.若二叉树采用二叉链表存储结构,要交换其所有分支结点左、右子树的位置,利用( C )遍历方法最合适。
A.前序 B.中序 C.后序 D.按层次
22.在下列存储形式中,哪一个不是树的存储形式?( D )
A.双亲表示法 B.孩子链表表示法 C.孩子兄弟表示法 D.顺序存储表示法
23. 在下列关于二叉树的叙述中,正确的是( D )
①只有一个结点的二叉树度为0; ②二叉树的度为2; ③二叉树的左右子树可任意交换;
④深度为K的完全二叉树的结点个数小于或等于深度相同的满二叉树。
A.①②③ B.②③④ C.②④ D.①④
24. 若X是二叉中序线索树中一个有左孩子的结点,且X不为根,则x的前驱为( C )
A.X的双亲 B.X的右子树中最左的结点
C.X的左子树中最右结点 D.X的左子树中最右叶结点
25. 在二叉树结点的先序序列,中序序列和后序序列中,所有叶子结点的先后顺序( B )
A.都不相同 B.完全相同 C.先序和中序相同,而与后序不同
D.中序和后序相同,而与先序不同
26在线索化二叉树中,t所指结点没有右子树的充要条件是( )。
A、t->Rtag==1 B、t->Rchild==NULL
C、t->Rtag==1且t->Rchild==NULL D、以上都不对
27、设高度为h的二叉树上只有度为0和度为2的结点,则此类二叉树中所包含的结点数至少为(B)。
A.2h B.2h-1
C.2h+1 D.h+1
28、如右图所示二叉树的中序遍历序列是(B)。
A.abcdgef B.dfebagc
C.dbaefcg D.defbagc
29、已知某二叉树的后序遍历序列是dabec,中序遍历序列是debac,
它的先序遍历序列是(A)。
A.cedba B.cdbae C.cabed D.cabde
30、设a和b为一棵二叉树上的两个结点,在中序遍历时,a在b前的条件是(D)。
A.a是b的左孩子 B.b是a的右孩子
C.a是b左子树上结点或b是a右子树上结点 D.以上三项均可
31、假定在一棵二叉树中,双分支结点数为15,单分支结点数为30,则叶子结点数为(C)个。
A. 45 B.15 C.16 D.31
32、某二叉树的先序遍历序列是abdgcefh,中序遍历序列是dgbaechf,则其后序遍历序列是(A)。
A.gdbehfca B.abcdefgh C.gdbaefch D.ghbcdefa
按照二叉树的定义,具有3个结点的二叉树有(D)种。
A.2 B.3 C.4 D.5
33、树的基本遍历策略可分为先根遍历和后根遍历;二叉树的遍历策略分为先序、中序和后序遍历。这里把由树转化得到的二叉树叫做这棵树对应的二叉树。以下结论()是正确的。
A.树的先根遍历序列与其对应的二叉树的先序遍历序列相同
B.树的后根遍历序列与其对应的二叉树的后序遍历序列相同
C.树的先根遍历序列与其对应的二叉树的中序遍历序列相同
D.以上都不对
34、如下图所示的4棵二叉树,(C)不是完全二叉树。
35、设哈夫曼树中的叶子结点总数为m,若用二叉链表作为存储结构,则该哈夫曼树中总共有(B)个空指针域。
A.2m-1 B.2m C.2m+1 D.4m
36、二叉树的第k层的结点数最多为( D )
A.2k-1 B.2K+1 C.2K-1 D.2K-1
37、设某棵二叉树中有2000个结点,则该二叉树的最小高度为( C )。
A.9 B.10 C.11 D.12
38、一棵有n个结点的树,在把它转换成对应的二叉树后,该二叉树根结点的左子树上共有( B )个结点。
A.n-2 B.n-1 C.n+1 D.n+2
39、对于一棵深度为4的三叉树,最多有( C )个结点。
A.30 B.36 C.40 D.54
40、设结点A有3个兄弟结点且结点B为结点A的双亲结点,则结点B的度数数为(B )。
(A) 3 (B) 4 (C) 5 (D) 1
四、简答题
1.给定二叉树的两种遍历序列,分别是:前序遍历序列:D,A,C,E,B,H,F,G,I; 中序遍历序列:D,C,B,E,H,A,G,I,F,试画出二叉树B。
解:方法是:由前序先确定root,由中序可确定root的左、右子树。然后由其左子树的元素集合和右子树的集合对应前序遍历序列中的元素集合,可继续确定root的左右孩子。将他们分别作为新的root,不断递归,则所有元素都将被唯一确定,问题得解。
2、已知一棵二叉树,其中序序列DBCAFGE,后序序列DCBGFEA,构造该二叉树。
解:
3、给定权值{8,12,4,5,26,16,9},构造一棵带权路径长度最短的二叉树,并计算其带权路径长度。
解:
或:
WPL=8×3+4×4+5×4+16×2+9×3+12×3+26×2 =207
[注]:哈夫曼树的左右子树可以互换。
4. (把如图所示的树转化成二叉树。
答:注意全部兄弟之间都要连线(包括度为2的兄弟),并注意原有连线结点一律归入左子树,新添连线结点一律归入右子树。
A
B
E C
K F H D
L G I
M J
5、画出和下列二叉树相应的森林。
答:注意根右边的子树肯定是森林,
而孩子结点的右子树均为兄弟。
6、假设用于通信的电文仅由8个字母组成,字母在电文中出现的频率分别为0.07,0.19,0.02,0.06,0.32,0.03,0.21,0.10。试为这8个字母设计哈夫曼编码。
解:哈夫曼编码
先将概率放大100倍,以方便构造哈夫曼树。
w={7,19,2,6,32,3,21,10},按哈夫曼规则:【[(2,3),6], (7,10)】, ……19, 21, 32
(100)
(40) (60)
19 21 32 (28)
(11)
7 10 6 (5)
2 3
WPL=2(0.19+0.32+0.21)+4(0.07+0.06+0.10)+5(0.02+0.03)=1.44+0.92+0.25=2.61
五、算法设计题
1.编写递归算法,计算二叉树中叶子结点的数目。
解:思路:输出叶子结点比较简单,用任何一种遍历递归算法,凡是左右指针均空者,则为叶子,将其打印出来。
DLR(liuyu *root) /*中序遍历 递归函数*/
{if(root!=NULL)
{if((root->lchild==NULL)&&(root->rchild==NULL)){sum++; printf("%d\n",root->data);}
DLR(root->lchild);
DLR(root->rchild); }
return(0);
}
2.写出求二叉树深度的算法,先定义二叉树的抽象数据类型。
解: int depth(liuyu*root) /*统计层数*/
{int d,p; /*注意每一层的局部变量d,p都是各自独立的*/
p=0;
if(root==NULL)return(p); /*找到叶子之后才开始统计*/
else{
d=depth(root->lchild);
if(d>p) p=d; /*向上回朔时,要挑出左右子树中的相对大的那个深度值*/
d=depth(root->rchild);
if(d>p)p=d;
}
p=p+1;
return(p);
}
3、已知一棵二叉树按顺序方式存储在数组A[1..n]中。设计算法,求出下标分别为i和j的两个结点的最近的公共祖先结点的值。
解:void Ancestor(ElemType A[],int n,i,j)
//二叉树顺序存储在数组A[1..n]中,本算法求下标分别为i和j的结点的最近公共祖先结点的值。
{while(i!=j)
if(i>j) i=i/2; //下标为i的结点的双亲结点的下标
else j=j/2; //下标为j的结点的双亲结点的下标
printf(“所查结点的最近公共祖先的下标是%d,值是%d”,i,A[i]);//设元素类型整型。
}// Ancestor
4.编写按层次顺序(同一层自左至右)遍历二叉树的算法。
解:思路:既然要求从上到下,从左到右,则利用队列存放各子树结点的指针是个好办法。
这是一个循环算法,用while语句不断循环,直到队空之后自然退出该函数。
技巧之处:当根结点入队后,会自然使得左、右孩子结点入队,而左孩子出队时又会立即使得它的左右孩子结点入队,……以此产生了按层次输出的效果。
void LayerOrder(Bitree T)//层序遍历二叉树
{ InitQueue(Q); //建立工作队列
EnQueue(Q,T);
while(!QueueEmpty(Q))
{
DeQueue(Q,p);
visit(p);
if(p->lchild) EnQueue(Q,p->lchild);
if(p->rchild) EnQueue(Q,p->rchild);
}
}//LayerOrder
5.编写算法判别给定二叉树是否为完全二叉树。
答:int IsFull_Bitree(Bitree T)//判断二叉树是否完全二叉树,是则返回1,否则返回0
{ InitQueue(Q);
flag=0;
EnQueue(Q,T); //建立工作队列
while(!QueueEmpty(Q))
{ {
DeQueue(Q,p);
if(!p) flag=1;
else if(flag) return 0;
else
{ EnQueue(Q,p->lchild);
EnQueue(Q,p->rchild); //不管孩子是否为空,都入队列
} }//while
return 1;
}//IsFull_Bitree
6、试设计算法计算一棵给定二叉树上所有结点数目。假设二叉树的存储结构描述如下:
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild;*rchild; /*左右孩子指针*/
}BiTNode,*BiTree;
解:int CountNode(BinTree bt) {
if (bt==Null)
return(0);
else {
num1=CountNode(root->lchild);
num2=CountNode(root->rchild);
return(num1+num2+1);
}}
7、计算二叉树上单分支结点数目。假设二叉树的存储结构描述如下:
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild;*rchild; /*左右孩子指针*/
} BiTNode,*BiTree;
解:FUNC nodes1(t:bitre):integer;
if t=Null then nodes1:=0
else if (t->lchild= Null) and (t->rchild= Null) then nodes1:=0
else if (t->lchild= Null) or (t->rchild= Null)
then nodes1:=1+nodes1(t->lchild)+nodes1(t->rchild)
else nodes1:=nodes1(t->lchild)+nodes1(t->rchild)
ENDF;
8、利用栈的基本操作写出先序遍历二叉树的非递归算法
[题目分析] 先序遍历二叉树的非递归算法,要求进栈元素少,意味着空指针不进栈。
void PreOrder(Bitree bt)//对二叉数bt进行非递归遍历
{int top=0; Bitree s[]; //top是栈s的栈顶指针,栈中元素是树结点指针,栈容量足够大
while(bt!=null || top>0)
{while(bt!=null)
{printf(bt->data); //访问根结点
if(bt->rchlid) s[++top]=bt->rchild; //若有右子女,则右子女进栈
bt=bt->lchild; }
if (top>0) bt=s[top--];
}