树和二叉树练习题及解答

标签:
杂谈 |
一、下面是有关二叉树的叙述,请判断正误(每小题1分,共10分)
(
(
(
(
(
(
(
(
(
(正确。用二叉链表存储包含n个结点的二叉树,结点共有2n个链域。由于二叉树中,除根结点外,每一个结点有且仅有一个双亲,所以只有n-1个结点的链域存放指向非空子女结点的指针,还有n+1个空指针。)即有后继链接的指针仅n-1个。
(
最快方法:用叶子数=[n/2]=6,再求n2=n0-1=5
二、填空(每空1分,共15分)
1.
2.
注:满二叉树没有度为1的结点,所以分支结点数就是二度结点数。
3.
(
4.
答:最快方法:用叶子数=[n/2]=350
5.
答:最快方法:用叶子数=[n/2]=500
6.
答:当k=1(单叉树)时应该最深,深度=n(层);当k=n-1(n-1叉树)时应该最浅,深度=2(层),但不包括n=0或1时的特例情况。教材答案是“完全k叉树”,未定量。)
7.
法2:不画图也能快速得出后序序列,只要找到根的位置特征。由前序先确定root,由中序先确定左子树。例如,前序遍历BEFCGDH中,根结点在最前面,是B;则后序遍历中B一定在最后面。
法3:递归计算。如B在前序序列中第一,中序中在中间(可知左右子树上有哪些元素),则在后序中必为最后。如法对B的左右子树同样处理,则问题得解。
8.【全国专升本统考题】中序遍历的递归算法平均空间复杂度为
答:即递归最大嵌套层数,即栈的占用单元数。精确值应为树的深度k+1,包括叶子的空域也递归了一次。
9.
解:先构造哈夫曼树,得到各叶子的路径长度之后便可求出WPL=(4+5+3)×2+(1+2)×3=33
(9)
1
(注:原题为选择题:A.32
三、单项选择题(每小题1分,共11分)
(
(A)是一棵树;
(C)是一棵树也是一棵二叉树;
答:以前的标答是B,因为那时树的定义是n≥1
(
(A)它不能用顺序存储结构存储;
(C)顺序存储结构和链式存储结构都能存储;
(
(A)
注1:éx
注2:选(A)是错误的。例如当n为2的整数幂时就会少算一层。似乎ë
(
(A)唯一的
(C)有多种,但根结点都没有左孩子
5.
树是结点的有限集合,它A
的集合T1,T2,…,Tm,每个集合又都是树,此时结点T称为Ti的父结点,Ti称为T的子结点(1≤i≤m)。一个结点的子结点个数为该结点的
供选择的答案
A:
B:
C:
答案:ABC=1,1,3
6.
二叉树
供选择的答案
A:
B:
C~D:
答案:A=
答案:ABCDE=2,1,1,3
四、简答题(每小题4分,共20分)
1.
答:度为2的树从形式上看与二叉树很相似,但它的子树是无序的,而二叉树是有序的。即,在一般树中若某结点只有一个孩子,就无需区分其左右次序,而在二叉树中即使是一个孩子也有左右之分。
2.〖01年计算机研题〗设如下图所示的二叉树B的存储结构为二叉链表,root为根指针,结点结构为:(lchild,data,rchild)。其中lchild,rchild分别为指向左右孩子的指针,data为字符型,root为根指针,试回答下列问题:
1.
2.
二叉树B
解:这是“先根再左再根再右”,比前序遍历多打印各结点一次,输出结果为:A
特点:①每个结点肯定都会被打印两次;②但出现的顺序不同,其规律是:凡是有左子树的结点,必间隔左子树的全部结点后再重复出现;如A,B,D等结点。反之马上就会重复出现。如C,E,F,G等结点。
时间复杂度以访问结点的次数为主,精确值为2*n,时间渐近度为O(n).
3.
前序遍历序列:D,A,C,E,B,H,F,G,I;
试画出二叉树B,并简述由任意二叉树B的前序遍历序列和中序遍历序列求二叉树B的思想方法。
解:方法是:由前序先确定root,由中序可确定root的左、右子树。然后由其左子树的元素集合和右子树的集合对应前序遍历序列中的元素集合,可继续确定root的左右孩子。将他们分别作为新的root,不断递归,则所有元素都将被唯一确定,问题得解。
E G
B
4.【计算机研2000】给定如图所示二叉树T,请画出与其对应的中序线索二叉树。
解:要遵循中序遍历的轨迹来画出每个前驱和后继。
中序遍历序列:55
25
55
五、阅读分析题(每题5分,共20分)
1.
答:DLR:A
LDR:
LRD:J
2.
答:注意全部兄弟之间都要连线(包括度为2的兄弟),并注意原有连线结点一律归入左子树,新添连线结点一律归入右子树。
![树和二叉树练习题及解答 树和二叉树练习题及解答]()
![树和二叉树练习题及解答 树和二叉树练习题及解答]()
K F H D
4.【严题集6.21②】画出和下列二叉树相应的森林。
答:注意根右边的子树肯定是森林,
而孩子结点的右子树均为兄弟。
六、算法设计题(前5题中任选2题,第6题必做,每题8分,共24分)
1.【严题集6.42③】编写递归算法,计算二叉树中叶子结点的数目。
解:思路:输出叶子结点比较简单,用任何一种遍历递归算法,凡是左右指针均空者,则为叶子,将其打印出来。
法一:核心部分为:
DLR(li
{if(root!=NULL)
}
法二:
int
{
上右子树的叶子数
}//LeafCount_BiTree
注:上机时要先建树!例如实验二的方案一。
①
思路:先建树,再从遍历过程中打印结点值并统计。
步骤1
7
编程:
说明部分为:
#include
#include
typedef
liuyu
int
void
{
s=(test*)malloc(m);
s->data=x;
s->lchild=NULL;
s->rchild=NULL;
if(!root){root=s;
p=root;
while(p)
if(p->data==x){printf("data
else
if(x<q->data)q->lchild=s;
else
}
DLR(liuyu
{if(root!=NULL)
}
{int
i=1;
root=NULL;
do{printf("please
i++;
scanf("%d",&x);
if(x==-9999){
while(x!=-9999);
return(0);}
若一开始运行就输入-9999,则无叶子输出,sum=0。
2.【全国专升本统考题】写出求二叉树深度的算法,先定义二叉树的抽象数据类型。
或【严题集6.44④】编写递归算法,求二叉树中以元素值为x的结点为根的子树的深度。
答;设计思路:只查后继链表指针,若左或右孩子的左或右指针非空,则层次数加1;否则函数返回。
但注意,递归时应当从叶子开始向上计数,否则不易确定层数。
int
{int
p=0;
if(root==NULL)return(p);
else{
d=depth(root->lchild);
if(d>p)
d=depth(root->rchild);
if(d>p)p=d;
}
p=p+1;
return(p);
}
法二:
int
{
}//Get_Sub_Depth
int
{
}//Get_Depth
附:上机调试过程
步骤1
步骤2:
完整程序如下:
#include
#include
typedef
liuyu
int
void
{
s=(test*)malloc(m);
s->data=x;
s->lchild=NULL;
s->rchild=NULL;
if(!root){root=s;
p=root;
while(p)
if(p->data==x){printf("data
else
if(x<q->data)q->lchild=s;
else
}
int
{int
p=0;
if(root==NULL)return(p);
else{
d=depth(root->lchild);
if(d>p)
d=depth(root->rchild);
if(d>p)p=d;
}
p=p+1;
return(p);
}
void
{int
i=1;
root=NULL;
do{printf("please
i++;
scanf("%d",&x);
if(x==-9999){
while(x!=-9999);
return;}
执行结果:
3.
或:按层次输出二叉树中所有结点;
解:思路:既然要求从上到下,从左到右,则利用队列存放各子树结点的指针是个好办法。
这是一个循环算法,用while语句不断循环,直到队空之后自然退出该函数。
技巧之处:当根结点入队后,会自然使得左、右孩子结点入队,而左孩子出队时又会立即使得它的左右孩子结点入队,……以此产生了按层次输出的效果。
level(liuyu*T)
{int
f=0;
r=(r+1)%max;
q[r]=T;
while(f!=r)
{f=(f+1%max);
p=q[f];
printf("%d",p->data);
if(p->lchild){r=(r+1)%max;
if(p->rchild){r=(r+1)%max;
}
return(0);
}
法二:
void
{
}//LayerOrder
可以用前面的函数建树,然后调用这个函数来输出。
完整程序如下(已上机通过)
#include
#include
#define
typedef
liuyu
int
void
{
s=(test*)malloc(m);
s->data=x;
s->lchild=NULL;
s->rchild=NULL;
if(!root){root=s;
p=root;
while(p)
if(p->data==x){printf("data
else
if(x<q->data)q->lchild=s;
else
}
level(liuyu*T)
{int
f=0;
r=(r+1)%max;
q[r]=T;
while(f!=r)
{f=(f+1%max);
p=q[f];
printf("%d",p->data);
if(p->lchild){r=(r+1)%max;
if(p->rchild){r=(r+1)%max;
}
return(0);
}
void
{int
i=1;
root=NULL;
do{printf("please
i++;
scanf("%d",&x);
if(x==-9999){
while(x!=-9999);
return;}
4.
答:首先,由于是完全二叉树,不必担心中途会出现孩子为null的情况。
其次分析:结点i的左孩子为2i,右孩子为2i+1;直接打印即可。
Printf(“Left_child=”,
但其双亲是i/2,需先判断i为奇数还是偶数。若i为奇数,则应当先i--
If(i/2!=0)i--;
Printf(“Parents=”,
5.【严题集6.49④】编写算法判别给定二叉树是否为完全二叉树。
答:int
{
}//IsFull_Bitree
分析:该问题可以通过层序遍历的方法来解决.与6.47相比,作了一个修改,不管当前结点
是否有左右孩子,都入队列.这样当树为完全二叉树时,遍历时得到是一个连续的不包含空
指针的序列.反之,则序列中会含有空指针.
6.
解:方案1;哈夫曼编码
先将概率放大100倍,以方便构造哈夫曼树。
(100)
(40)
19
(17)
方案比较:
方案1的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
方案2的WPL=3(0.19+0.32+0.21+0.07+0.06+0.10+0.02+0.03)=3
结论:哈夫曼编码优于等长二进制编码