最新习题五和上机答案.docx
《最新习题五和上机答案.docx》由会员分享,可在线阅读,更多相关《最新习题五和上机答案.docx(35页珍藏版)》请在冰豆网上搜索。
最新习题五和上机答案
习题五
5.1已知一棵树边的集合为(I,M),(I,N),(E,I),(B,E),(B,D),(A,B),(G,J),(G,K),(C,G),(C,F),(TABLE,L),(C,TABLE),(A,C),画出这棵树,并回答下列问题:
⑴哪个是根结点?
⑵哪些是叶子结点?
⑶哪个是结点G的双亲?
⑷哪些是结点G的祖先?
⑸哪些是结点G的孩子?
⑹哪些是结点E的子孙?
⑺哪些是结点E的兄弟?
哪些是结点F的兄弟?
⑻结点B和N的层次号分别是什么?
⑼树的深度是多少?
⑽以结点C为根的子树的深度是多少?
解:
依题意,树的表示如图8.23所示。
(1)根结点是:
a
(2)叶子结点是:
d,m,n,f,j,k,l
(3)g的双亲是:
c
(4)g的祖先是:
a,c
(5)g的孩子是:
j,k
(6)e的子孙是:
i,m,n
(7)e的兄弟是d,f的兄弟是g,h
(8)b的层次是2,n的层次是5
(9)树的深度是5
(10)以结点c为根的子树的深度是3
(11)树的度数是3
5.2一棵度为2的树与一棵二叉树有何区别?
解:
二叉树的度也可以为1。
5.3试分别画出具有3个结点的树和3个结点的二叉树的所有不同形态。
解:
二叉树:
5.4一棵深度为N的满K叉树有如下性质:
第N层上的结点都是叶子结点,其余各层上每个结点都有K棵非空子树。
如果按层次顺序从1开始对全部结点编号,问
⑴各层的结点数目是多少?
⑵编号为n的结点的父结点(若存在)的编号是多少?
⑶编号为n的结点的第i个儿子(若存在)的编号是多少?
⑷编号为n的结点有右兄弟的条件是什么?
其右兄弟的编号是多少?
解:
(1)第i层的结点数为ki-1。
(2)编号为n的结点的双亲点为:
「(n-2)/k」+1。
(3)编号为n的结点的第i个孩子结点为:
(n-1)*k+i+1。
(4)编号为n的结点有右兄弟的条件是(n-1)%k≠0,其右兄弟的编号是n+1。
5.5已知一棵度为m的树中有n1个度为1的结点,n2个度为2的结点,...,nm个度为m的结点,问该树中有多少个叶子结点?
解:
依题意:
设n为总的结点个数,n0为叶子结点(即度为0的结点)的个数,则有:
n=n+n+n+...+n①
又有:
n-1=度的总数,即:
n-1=n*1+n*2+...+n*m②
①-②式得:
1=n-n-2n-...-(m-1)n
则有:
n=1+n+2n+...+(m-1)n
=1+
5.6试列出下列二叉树的终端结点、非终端结点以及每个结点的层次
题5.6
解:
终端结点:
E、G、H
非终端结点:
A、B、C、D、F
结点
A
B
C
D
E
F
G
H
层次
1
2
2
3
3
3
4
4
5.7对于5.6题中给出的二叉树,分别列出先根次序、中根次序、后根次序的结点序列。
解:
先根次序:
ABDGCEFH
中根次序:
DGBAECHF
后根次序:
GDBEHFCA
5.8在二叉树的顺序存储结构中,实际上隐含着双亲的信息,因此可和三叉链表对应。
假设每个指针域占4个字节的存储空间,每个信息占K个字节的存储空间。
试问对于一棵有n个结点的二叉树,且在顺序存储结构中最后一个结点的下标为m,在什么条件下顺序存储结构比二叉链表更节省空间?
解:
(K+4)*n<(m+1)*4
5.9假定用两个一维数组L(1:
n)和R(1:
n)作为有n个结点的二叉树的存储结构,L(i)和R(i)分别指示结点i的左孩子和右孩子,0表示空。
⑴试写一个算法判别结点u是否为结点v的子孙;
⑵先由L和R建立一维数组T(1:
n),使T中第i(i=1,2,...,n)个分量指示结点i的双亲,然后写判别结点u是否为结点v的子孙的算法。
解:
(1)、
intIs_Descendant_C(intu,intv)
//在孩子存储结构上判断u是否v的子孙,是则返回1,否则返回0
{
if(u==v)return1;
else
{
if(L[v])
if(Is_Descendant(u,L[v]))return1;
if(R[v])
if(Is_Descendant(u,R[v]))return1;//这是个递归算法
}
return0;
}//Is_Descendant_C
(2)、
intIs_Descendant_P(intu,intv)
//在双亲存储结构上判断u是否v的子孙,是则返回1,否则返回0
{
for(p=u;p!
=v&&p;p=T[p]);
if(p==v)return1;
elsereturn0;
}//Is_Descendant_P
5.10假设n和m为二叉树中的两结点,用“1”、“0”“Φ”(分别表示肯定、恰恰相反和不一定)填写下表:
前序遍历时
中序遍历时
后序遍历时
已知
n在m前?
n在m前?
n在m前?
n在m的左方
1
1
1
n在m的右方
0
0
0
n是m的祖先
1
Φ
0
n是m的子孙
0
Φ
1
注:
⑴如果离a和b最近的共同祖先p存在,且⑵a在p的左子树中,b在p的右子树中,则称a在b的左方(即b在a的右方)。
5.11假设以二叉链表作存储结构,试分别写出前序和后序遍历的非递归算法,可直接利用栈的基本运算。
解:
前序遍历:
依题意,使用一个栈stack实现非递归的前序遍历。
voidpreorder(b)
btree*b;
{
btree*stack[Maxsize],*p;
inttop;
if(b!
=NULL)
{
top=1;/*根结点入栈*/
stack[top]=b;
while(top>0)/*栈不为空时循环*/
{
p=stack[top];/*退栈并访问该结点*/
top--;
printf("%d",p->data);
if(p->right!
=NULL)/*右孩子入栈*/
{
top++;
stack[top]=p->right;
}
if(p->left!
=NULL)/*左孩子入栈*/
{
top++;
stack[top]=p->left;
}
}
}
}
后序遍历:
根据后序遍历二叉树的递归定义,转换成非递归函数时采用一个栈保存返回的结点,先扫描根结点的所有左结点并入栈,出栈一个结点,然后扫描该结点的右结点并入栈,再扫描该右结点的所有左结点并入栈,当一个结点的左右子树均访问后再访问该结点,如此这样,直到栈空为止。
在访问根结点的右子树后,当指针p指向右子树树根时,必须记下根结点的位置,以便在遍历右子树之后正确返回,这就产生了一个问题:
在退栈回到根结点时如何区别是从左子树返回还是从右子树返回。
这里采用两个栈stack和tag,并用一个共同的栈顶指针,一个存放指针值,一个存放左右子树标志(0为左子树,1为右子树)。
退栈时在退出结点指针的同时区别是遍历左子树返回的还是遍历右子树返回的,以决定下一步是继续遍历右子树还是访问根结点。
因此,实现本题功能的函数如下:
voidpostorder(btree*b)
{
btree*stack[Maxsize],*p;
inttag[Maxsize];
inttop=0;
p=b;
do
{
while(p!
=NULL)/*扫描左结点,入栈*/
{
top++;
stack[top]=p;
tag[top]=0;
p=p->left;
}
if(top>0)
{
if(tag[top]==1)/*左右结点均已访问过,则访问该结点*/
{
printf("%c",stack[top]->data);
top--;
}
else
{
p=stack[top];
if(top>0)
{
p=p->right;/*扫描右结点*/
tag[top]=1;/*表示当前结点的右子树已访问过*/
}
}
}
}while(p!
=NULL||top!
=0);
}
5.12假设在二叉链表中增设两个域:
双亲域(parent)以指示其双亲结点;标志域(mark):
0..2,以区分在遍历过程中到达该结点时应该继续向左或向右或访问该结点。
试以此存储结构编写不用栈的后序遍历的算法。
解:
typedefstruct{
intdata;
EBTNode*lchild;
EBTNode*rchild;
EBTNode*parent;
enum{0,1,2}mark;
}EBTNode,EBitree;//有mark域和双亲指针域的二叉树结点类型
voidPostOrder_Nonrecursive(EBitreeT)//后序遍历二叉树的非递归算法,不用栈
{
p=T;
while(p)
switch(p->mark)
{
case0:
p->mark=1;
if(p->lchild)p=p->lchild;//访问左子树
break;
case1:
p->mark=2;
if(p->rchild)p=p->rchild;//访问右子树
break;
case2:
visit(p);
p->mark=0;//恢复mark值
p=p->parent;//返回双亲结点
}
}//PostOrder_Nonrecursive
分析:
本题思路与上一题完全相同,只不过结点的mark值是储存在结点中的,而不是暂存在堆栈中,所以访问完毕后要将mark域恢复为0,以备下一次遍历.
5.13试编写算法在一棵以二叉链表存储的二叉树中求这样的结点:
它在前序序列中处第K个位置。
解:
intc,k;//这里把k和计数器c作为全局变量处理
voidGet_PreSeq(BitreeT)//求先序序列为k的结点的值
{
if(T)
{
c++;//每访问一个子树的根都会使前序序号计数器加1
if(c==k)
{
printf("Valueis%d\n",T->data);
exit
(1);
}
else
{
Get_PreSeq(T->lchild);//在左子树中查找
Get_PreSeq(T->rchild);//在右子树中查找
}
}//if
}//Get_PreSeq
main()
{
...
scanf("%d",&k);
c=0;//在主函数中调用前,要给计数器赋初值0
Get_PreSeq(T,k);
}//main
5.14试以二叉链表作存储结构,编写计算二叉树中叶子结点数目的递归算法。
解:
依题意:
计算一棵二叉树的叶子结点数的递归模型如下:
因此,实现本题功能的函数如下:
intleafs(btree*b)
{
intnum1,num2;
if(b==NULL)return(0);
elseif(b->lef