数据结构习题题目及答案树和二叉树参考答案Word格式文档下载.docx
《数据结构习题题目及答案树和二叉树参考答案Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《数据结构习题题目及答案树和二叉树参考答案Word格式文档下载.docx(29页珍藏版)》请在冰豆网上搜索。
211-1,故1025个结点的二叉树最低高为11。
6.7一棵二叉树高度为h,所有结点的度或为0,或为2,则这棵二叉树最少有多少结点。
【解答】第一层只一个根结点,其余各层都两个结点,这棵二叉树最少结点数是2h-1。
6.8将有关二叉树的概念推广到三叉树,则一棵有244个结点的完全三叉树的高度是多少。
【解答】设含n个结点的完全三叉树的高度为h,则有
<
n≤
2n<
本题n=244,故h=6。
6.9对二叉树的结点从1开始进行连续编号,要求每个结点的编号大于其左、右孩子的编号,同一结点的左、右孩子中,其左孩子的编号小于其右孩子的编号,是采用何种次序的遍历实现编号的。
【解答】后序遍历二叉树,因为后序遍历顺序为左子树-右子树-根结点。
6.10高度为h(h>
0)的满二叉树对应的森林由多少棵树构成。
【解答】因为在二叉树转换为森林时,二叉树的根结点,根结点的右子女,右子女的右子女,……,都是树的根,所以,高度为h(h>
0)的满二叉树对应的森林由h棵树构成。
6.11某二叉树结点的中序序列为BDAECF,后序序列为DBEFCA,则该二叉树对应的森林包括几棵树?
【解答】3棵树。
(本题不需画出完整的二叉树,更不需要画出森林,只需画出二叉树的右子树就可求解。
如上题所述,二叉树的根结点,根结点的右子女,右子女的右子女,……,在二叉树转为森林时,都是树的根。
)
6.12对任意一棵树,设它有n个结点,这n个结点的度数之和为多少?
【解答】n-1。
度数其实就是分支个数。
根结点无分支所指,其余结点有且只有一个分支所指。
6.13一棵左子树为空的二叉树在先序线索化后,其中空的链域的个数是多少?
【解答】对二叉树线索化时,只有空链域才可加线索。
一棵左子树为空的二叉树在先序线索化时,根结点的左链为空,应加上指向前驱的线索,但根结点无前驱,故该链域为空。
同样分析知道最后遍历的结点的右链域为空。
故一棵左子树为空的二叉树在先序线索化后,其中空的链域的个数是2个。
6.14一棵左、右子树均不空的二叉树在先序线索化后,其中空的链域的个数是多少?
【解答】1个。
6.15设B是由森林F变换得的二叉树。
若F中有n个非终端结点,则B中右指针域为空的结点有几个?
【解答】n+1。
森林中任何一个非终端结点在转换成二叉树时,其第一个子女结点成为该非终端结点的左子女,其余子女结点成为刚生成的左子女结点的右子女,右子女结点的右子女,……,最右子女结点的右链域为空。
照此分析,n个非终端结点在转换后,其子女结点中共有n个空链域。
另外,森林中各棵树的根结点可以看做互为兄弟,转换成二叉树后也产生1个空链域。
因此,本题的答案是n+1。
6.16试分别找出满足以下条件的所有二叉树:
(1)
二叉树的前序序列与中序序列相同;
(2)二叉树的中序序列与后序序列相同;
(3)
二叉树的前序序列与后序序列相同;
(4)二叉树的前序序列与层次序列相同;
(5)二叉树的前序、中序与后序序列均相同。
【解答】前序遍历二叉树的顺序是“根—左子树—右子树”,中序遍历的顺序是“左子树—根—右子树”,后序遍历顺序是:
“左子树—右子树―根",根据以上原则,本题解答如下:
若前序序列与中序序列相同,则或为空树,或为任一结点至多只有右子树的二叉树。
若中序序列与后序序列相同,则或为空树,或为任一结点至多只有左子树的二叉树。
若前序序列与后序序列相同,则或为空树,或为只有根结点的二叉树。
若二叉树的前序、中序与后序序列均相同,则或为空树,或为只有根结点的二叉树。
6.17已知一棵二叉树的前序遍历的结果是ABECDFGHIJ,中序遍历的结果是EBCDAFHIGJ,试画出这棵二叉树,对二叉树进行中序线索化,并将该二叉树转换为森林。
【解答】
6.18已知一棵二叉树的后序遍历序列为EICBGAHDF,同时知道该二叉树的中序遍历序列为CEIFGBADH,试画出该二叉树。
6.19设二叉树中每个结点均用一个字母表示,若一个结点的左子树或右子树为空,用#表示,现前序遍历二叉树,访问的结点序列为ABD##C#E##F##,写出中序和后序遍历二叉树时结点的访问序列。
【解答】中序遍历二叉树时结点的访问序列:
#D#B#C#E#A#F#
后序遍历二叉树时结点的访问序列。
##D###ECB##FA
6.20有n个结点的k叉树(k≥2)用k叉链表表示时,有多少个空指针?
【解答】k叉树(k≥2)用k叉链表表示时,每个结点有k个指针,除根结点没有指针指向外,其余每个结点都有一个指针指向,故空指针的个数为:
nk-(n-1)=n(k-1)+1
6.21一棵高度为h的满k叉树有如下性质:
根结点所在层次为0;
第h层上的结点都是叶子结点;
其余各层上每个结点都有k棵非空子树,如果按层次自顶向下,同一层自左向右,顺序从1开始对全部结点进行编号,试问:
(1)各层的结点个数是多少?
(2)编号为i的结点的双亲结点(若存在)的编号是多少?
(3)编号为i的结点的第m个孩子结点(若存在)的编号是多少?
(4)编号为i的结点有右兄弟的条件是什么?
其右兄弟结点的编号是多少?
(1)kl(l为层数,按题意,根结点为0层)
(2)因为该树每层上均有kl个结点,从根开始编号为1,则结点i的从右向左数第2个孩子的结点编号为ki。
设n为结点i的子女,则关系式(i-1)k+2<
=n<
=ik+1成立,因i是整数,故结点i的双亲的编号为ë
(i-2)/kû
+1。
(3)结点i(i>
1)的前一结点编号为i-1(其最右边子女编号是(i-1)*k+1),故结点i的第m个孩子的编号是(i-1)*k+1+m。
(4)根据以上分析,结点i有右兄弟的条件是,它不是双亲的从右数的第一子女,即(i-1)%k!
=0,其右兄弟编号是i+1。
6.22.证明任一结点个数为n(n>
0)的二叉树的高度至少为ë
(logn)û
【解答】最低高度二叉树的特点是,除最下层结点个数不满外,其余各层的结点数都应达到各层的最大值。
设n个结点的二叉树的最低高度是h,则n应满足2h-1≦n≦2h-1关系式。
解此不等式,并考虑h是整数,则有h=ë
lognû
+1,即任一结点个数为n的二叉树的高度至少为ë
6.23已知A[1..N]是一棵顺序存储的完全二叉树,如何求出A[i]和A[j]的最近的共同祖先?
【解答】根据顺序存储的完全二叉树的性质,编号为i的结点的双亲的编号是ë
i/2û
,故A[i]和A[j]的最近公共祖先可如下求出:
while(i/2!
=j/2)
if(i>
j)i=i/2;
else
j=j/2;
退出while后,若i/2=0,则最近公共祖先为根结点,否则最近公共祖先是i/2。
6.24已知一棵满二叉树的结点个数为20到40之间的素数,此二叉树的叶子结点有多少个?
【解答】结点个数在20到40的满二叉树且结点数是素数的数是31,其叶子数是16。
6.25求含有n个结点、采用顺序存储结构的完全二叉树中的序号最小的叶子结点的下标。
要求写出简要步骤。
【解答】根据完全二叉树的性质,最后一个结点(编号为n)的双亲结点的编号是ë
n/2û
,这是最后一个分枝结点,在它之后是第一个终端(叶子)结点,故序号最小的叶子结点的下标是ë
6.26试证明:
同一棵二叉树的所有叶子结点,在前序序列、中序序列以及后序序列中都按相同的相对位置出现(即先后顺序相同),例如前序abc,后序bca,中序bac。
【证明】前序遍历是“根-左-右”,中序遍历是“左-根-右”,后序遍历是“左-右-根”。
三种遍历中只是访问“根”结点的时机不同,对左右子树均是按左右顺序来遍历的,因此所有叶子都按相同的相对位置出现。
6.27设具有四个结点的二叉树的前序遍历序列为abcd;
S为长度等于4的由a,b,c,d排列构成的字符序列,若任取S作为上述算法的中序遍历序列,试问是否一定能构造出相应的二叉树,为什么?
试列出具有四个结点二叉树的全部形态及相应的中序遍历序列。
【解答】若前序序列是abcd,并非由这四个字母的任意组合(4!
=24)都能构造出二叉树。
因为以abcd为输入序列,通过栈只能得到1/(n+1)*2n!
/(n!
*n!
)=14种,即以abcd为前序序列的二叉树的数目是14。
任取以abcd作为中序遍历序列,并不全能与前序的abcd序列构成二叉树。
例如:
若取中序序列dcab就不能。
该14棵二叉树的形态及中序序列略。
6.28已知某二叉树的每个结点,要么其左、右子树皆为空,要么其左、右子树皆不空。
又知该二叉树的前序序列为:
JFDBACEHXIK;
后序序列为:
ACBEDXIHFKJ。
请给出该二叉树的中序序列,并画出相应的二叉树树形。
【解答】一般说来,仅仅知道二叉树的前序遍历序列和后序遍历序列并不能确定这棵二叉树,因为并不知道左子树和右子树两部分各有多少个结点。
但本题有特殊性,即每个结点“要么其左、右子树皆为空,要么其左、右子树皆不空”。
具体说,前序序列的第一个结点是二叉树的根,若该结点后再无其它结点,则二叉树只有根结点;
否则,该结点必有左右子树,且根结点后的第一个结点就是“左子树的根”。
到后序序列中查找这个“左子树的根”,它将后序序列分成左右两部分:
左部分(包括所查到的“左子树的根结点”)是二叉树的左子树(可能为空),右部分(除去最后的根结点)则是右子树(可能为空)。
这样,在确定根结点后,就可以将后序遍历序列(从而也将前序遍历序列)分成左子树和右子树两部分了。
本题中,先看前序遍历序列,第一个结点是J,所以J是二叉树的根,J后面还有结点,说明J有左、右子树,J后面的F必是左子树的根。
到后序遍历序列中找到F,F将后序遍历序列分成两部分:
左面ACBEDXIH,说明FACBEDXIH是根J的左子树;
右面K(K的右面J已知是根),说明K是根J的右子树。
这样,问题就转化为“以前序序列FDBACEHXI和后序序列ACBEDXIHF去构造根J的左子树”,以及“以前序序列K和后序序列K去构造根J的右子树”了。
如此构造下去,所构造的二叉树如下。
易见,中序序列为ABCDEFXHIJK。
6.29已知一个森林的先序序列和后序序列如下,请构造出该森林。
先序序列:
ABCDEFGHIJKLMNO
后序序列:
CDEBFHIJGAMLONK
【解答】森林的先序序列和后序序列对应其转换的二叉树的先序序列和中序序列,应先据此构造二叉树,再构造出森林。
6.30画出同时满足下列两条件的两棵不同的二叉树。
(1)按先根序遍历二叉树顺序为ABCDE。
(2)高度为5其对应的树(森林)的高度最大为4。
6.31用一维数组存放的一棵完全二叉树;
ABCDEFGHIJKL。
请写出后序遍历该二叉树的结点访问序列。
【解答】后序遍历该二叉树的结点访问序列为:
DECGHFBKJLIA
6.32一棵二叉树的先序、中序和后序序列如下,其中有部分未标出,试构造出该二叉树。
先序序列为:
CDE
GHI
K
中序序列为:
CB
FA_JKIG
EFDB
JIH
A
6.33设树形T在后根次序下的结点排列和各结点相应的度数如下:
后根次序:
BDEFCGJKILHA
次 数:
4
请画出T的树形结构图。
【解答】在树在后根遍历次序下,根结点在最后,任何结点的子树的所有结点都直接排在该结点之前。
例如,挨着根结点的是根结点的最右边的子女。
每棵子树的所有结点都聚集在一起,中间不会插入其它结点,也不会丢掉子树的任何结点。
按照这种理论解答本题,在遍历次序中从右到左分析,A是根,它有4个子女,H是它的最右边的子女(第4子女)。
H有2个子女,L是H的最右边的子女,L无子女,故I是H的第1子女。
I又有2个子女:
K和J,二者均无子女。
由此推断出下一个结点G是根结点A的第3子女。
……,继续构造,直至最左面的结点B,结果树形如下:
6.34若森林共有n个结点和b条边(b<
n),则该森林中有多少棵树。
【解答】n-b
森林的n个结点开始可看作是n个连通分量,加入一条边将减少一个连通分量。
因为树可以定义为无环的图,故加入b条边将减少b个连通分量,因而n个结点b条边的森林有n-b棵树。
6.35求高度为k的完全二叉树至少有多少个叶结点?
【解答】当高度为k的完全二叉树的第k层只有一个结点时,结点数达到最少,这也是高度为k的完全二叉树具有的最少叶结点数,我们知道,第k-1层有2k-2-1个叶结点,第k层只有一个叶结点,但这个结点的双亲已不再是叶子结点,故高度为k的完全二叉树至少有2k-2-1个叶结点。
6.36某通信电文由A、B、C、D、E、F六个字符组成,它们在电文中出现的次数分别是16,5,9,3,20,1。
试画出其哈夫曼树并确定其对应的哈夫曼编码。
【解答】答案不唯一,其中一个解答如下
对应的哈夫曼编码:
A—10,B—1101,
C—111,
D—11001,
E—0,F—11000
二、算法设计题
6.37以二叉链表作为存储结构,设计算法求出二叉树T中度为0、度为1和度为2的结点数。
【题目分析】结点计数可以在遍历中解决。
根据“访问根结点”在“递归遍历左子树”和“递归遍历右子树”中位置的不同,而有前序、后序和中序遍历。
【算法6.37】
int
n2,n1,n0;
∥设置三个全局变量,分别记度为2,1和0的结点个数
void
Count(BiTreet)
{if(t)
{if(t->
lchild&
&
t->
rchild)n2++;
elseif(t->
!
t->
rchild||!
rchild)n1++;
n0++;
if(t->
lchild!
=null)Count(t->
lchild);
rchild!
rchild);
}∥Count
6.38一棵n个结点的完全二叉树存放在二叉树的顺序存储结构中,试编写非递归算法对该树进行先序遍历。
【题目分析】二叉树的顺序存储是按完全二叉树的顺序存储,双亲与子女结点下标间有确定关系。
顺序存储结构的二叉树用结点下标大于n(完全二叉树)或0(对一般二叉树的“虚结点”)判空。
本题是完全二叉树。
【算法6.38】
PreOrder(ElemTypebt[],int
n)
∥对以顺序结构存储的完全二叉树bt进行前序遍历
{int
i=1,top=0,s[];
∥top是栈s的栈顶指针,栈容量足够大
while(i<
=n||top>
0)
{while(i<
=n)
{printf(bt[i]);
∥访问根结点;
if(2*i+1<
=n)s[++top]=2*i+1;
∥右子女的下标位置进栈
i=2*i;
∥沿左子女向下
}
if(top>
0)i=s[top--];
∥取出栈顶元素
}∥while
}∥结束PreOrder
6.39以二叉链表作为存储结构的二叉树,按后序遍历时输出的结点顺序为a1,a2,…,an。
试编写一算法,要求输出后序序列的逆序an,an-1…,a2
,a1
。
【题目分析】二叉树后序遍历是按“左子树-右子树-根结点”的顺序遍历二叉树,根据题意,若将遍历顺序改为“根结点-右子树-左子树”,就可以实现题目要求。
【算法6.39】
PostOrder(BiTreebt)
//对二叉树bt进行先右后左的“先根”遍历
{if(bt)
{printf(bt->
data);
//访问根结点
PostOrder(bt->
//先根遍历右子树
//先根遍历左子树
}
}
6.40以二叉链表作为存储结构,设计算法交换二叉树中所有结点的左、右子树。
【算法6.40】
exchange(BiTreebt)
∥将二叉树bt所有结点的左右子树交换
{if(bt){BiTrees;
s=bt->
lchild;
bt->
lchild=bt->
rchild;
rchild=s;
∥左右子女交换
exchange(bt->
∥交换左子树上所有结点的左右子树
∥交换右子树上所有结点的左右子树
}∥if
}∥结束
【算法讨论】将上述算法中两个递归调用语句放在前面,将交换语句放在最后,则是以后序遍历方式交换所有结点的左右子树。
中序遍历方式不适合本题。
6.41以二叉链表为存储结构,写出在二叉树中求值为x的结点在树中层次数的算法。
[题目分析]
按层次遍历,设一队列Q,用front和rear分别指向队头和队尾元素,last指向各层最右结点位置。
【算法6.41】
Level_x(BiTreebt,ElemTypex)∥求值为x的结点在树中层次数
{if(bt!
=null)
front=0,last=1,rear=1,level=1;
∥level记层次数
BiTreeQ[];
Q[1]=bt;
∥根结点入队
while(front<
=last)
{bt=Q[++front];
if(bt->
data==x)
{printf(“%3d\n”,level);
returnlevel;
}∥值为x的结点在树中层次数
=null)Q[++rear]=bt->
∥左子女入队列
∥右子女入队列
if(front==last){last=rear;
level++;
}∥本层最后一个结点已处理完
}∥算法结束
6.42已知深度为h的二叉树以一维数组作为存储结构。
试编写算法求该二叉树中叶子的个数。
【题目分析】按完全二叉树形式顺序存储二叉树时,无元素的位置要当作“虚结点”。
设虚结点取二叉树结点以外的值(这里设为0)。
设结点序号为i,则当i<
=(2h-1)/2时,若其2i和2i+1位置为虚结点,则i为叶子结点;
当i>
(2h-1)/2时,若i位置不是虚结点,则必为叶子结点。
【算法6.42】
Leaves(int
BT[],intn)
∥计算深度为h以一维数组BT作为存储结构的二叉树的叶子结点数,n为数组长度
num=0;
∥记叶子结点数
for(i=0;
i<
n;
i++)
if(BT[i]!
=0)
{if(i<
=n/2)
{if(BT[2*i]==0&
2*i+1<
=n&
BT[2*i+1]==0)num++;
∥若结点无孩子,则是叶子
elseif(BT[i]!
=0)num++;
∥存储在数组后一半的元素是叶子结点
return
num;
}∥结束Leaves
6.43已知二叉树以一维数组作为存储结构。
试编写算法求下标为i和j的两个结点的最近共同祖先结点的值。
【题目分析】二叉树顺序存储,是按完全二叉树的格式存储,利用完全二叉树双亲结点与子女结点编号间的关系,求下标为i和j的两结点的双亲,双亲的双亲,等等,直至找到最近的公共祖先。
【算法6.43】
Ancestor(ElemTypebt[],int
n,i,j,)
∥求顺序存储在bt[1..n]的二叉树中下标为i和j的两个结点的最近公共祖先结点
1||j<
1){printf(“参数错误\n”);
exit(0);
};
if(i==j)
{if(i==1){printf(“所查结点为根结点,无祖先\n”);
{printf(“结点的最近公共祖先是%d,值是%d”,i/2,A[i/2]);
exit(0)}
while(i!
=j)
∥下标为i的结点的双亲结点的下标
∥下标为j