第6章习题答案Word文档下载推荐.docx
《第6章习题答案Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《第6章习题答案Word文档下载推荐.docx(12页珍藏版)》请在冰豆网上搜索。
(4)根据以上分析,结点n有右兄弟的条件是,它不仅双亲的从右边的第一个子女,即(n-1)%k!
=0,
6.试证明,在具有n(n≥1)个结点的m叉树中,有n(m-1)+1个指针域是空的。
具有n个结点的m叉树共用n*m个指针。
除根结点外,其余n-1个结点均有指针所指,故空指针数为n*m-(n-1)=n*(m-1)+1。
7.试找出满足下列条件的二叉树:
(1)先序序列与后序序列相同;
(2)中序序列与后序序列相同;
(3)先序序列与中序序列相同;
(4)中序序列与层次遍历序列相同。
(1)若先序序列与后序序列相同,则或为空树,或为只有根结点的二叉树。
(2)若中序序列与后序序列相同,则或为空树,或为任一结点至多只有左子树的二叉树。
(3)若先序序列与中序序列相同,则或为空树,或为任一结点至多只有右子树的二叉树。
(4)若中序序列与层次遍历序列相同,则或为空树,或为任一结点至多只有右子树的二叉树。
8.设有一棵二叉树的层次遍历序列为ABCDEFGHI,J中序遍历序列为DBGEHJACI。
F请画出这棵二叉树。
按层次遍历,第一个结点(树不空)为根,该结点在中序序列中把序列分成左右两部分——左子树和右子树。
若左子树不空,层次序列中第二个结点为左子树的根;
若左子树为空,则层次序列中第二个结点为右子树的根。
对右子树分析类似。
层次序列的特点是:
从左到右每个结点或是当前情况下子树的根或是叶子。
9.用一维数组存放一棵完全二叉树:
ABCDEFGHIJK。
L请写出后序遍历该二叉树的访问结点序列。
HIDJKEBLFGC。
A
10.已知一棵二叉树的中序遍历序列为DGBAECHI,F后序遍历序列为:
GDBEIHFC。
(1)试画出该二叉树;
(2)试画出该二叉树的中序线索树;
(3)试画出该二叉树对应的森林。
(1)
2)略
3)
码最短。
字符A、B、C、D出现的次数为9、1、5、3。
其哈夫曼编码如下:
A:
1,B:
000,C:
01,D:
001。
其哈夫曼树为:
12.
T中,写出计算该算术表达式
假设一个仅包含二元运算符的算术表达式以链表形式存储在二叉树值的算法。
typedefstructNode{
ElemTypedata;
floatval;
charoptr;
//只取+、-、*、/
structNode*lchild,*rchild
}BiNode,*BiTree;
floatPostEval(BiTreet){//以后序遍历算法求以二叉树表示的算术表达式的值floatlv,rv;
if(t!
=NULL){
lv=PostEval(t->
lchild);
//rv=PostEval(t->
rchild);
//switch(t->
optr){
case'
+'
:
value=lv+rv;
break;
-'
value=lv-rv;
*'
value=lv*rv;
/'
value=lv/rv;
}
returnvalue;
13.假设二叉链表为二叉树的存储结构,编写判断给定的二叉树是否相似的算法。
所谓二叉树t1和t2相似指的是:
t1和t2都是空树;
或者t1和t2的根结点是相似的,以及t1的左子树和t2的左子树是相似的且t1的右子树和t2的右子树是相似的。
intLike(BiTreet1,BiTreet2){
intlike1,like2;
if(t1==NULL&
&
t2==NULL)return1;
elseif(t1==NULL||t2==NULL)return0;
else{
like1=Like(t1->
lchild,t2->
like2=Like(t1->
rchild,t2->
return(like1&
like2);
14.假设二叉链表为二叉树的存储结构,编写递归算法,将二叉树中所有结点的左、右子树相互交换。
voidExchange(BiTree&
t){
if(t){
BiTrees;
s=t->
lchild;
t->
lchild=t->
rchild;
rchild=s;
Exchange(t->
15.编写求双亲表示法表示的树的深度的算法。
intDepth(PTreet){
intmaxdepth=0,i,temp,f;
for(i=0;
i<
t.n;
i++){
temp=0;
f=i;
while(f>
-1){temp++;
f=t.nodes[f].parent;
}if(temp>
maxdepth)maxdepth=temp;
returnmaxdepth;
16.假设二叉链表为二叉树的存储结构,编写按层次遍历方式计算二叉树结点个数的算法。
intLevel(BiTreet){
intnum=0;
LinkQueueQ;
BiTreep;
InitQueue(Q);
EnQueue(Q,t);
while(!
QueueEmpty(Q)){
DeQueue(Q,p);
num++;
if(p->
lchild)EnQueue(Q,p->
if(p->
rchild)EnQueue(Q,p->
}//while
}//if
returnnum;
17.编写算法,利用叶子结点中的空指针域将所有叶子结点链接为一个带有头结点的双向链表,算法返回头结点的指针。
BiTreehead,pre;
//全局变量链表头指针head,pre
voidCreateLeafList(BiTreet){
CreateLeafList(t->
//中序遍历左子树if(t->
lchild==NULL&
rchild==NULL)//叶子结点
if(head==NULL){//第一个叶子结点
head=newBiTNode;
//生成头结点
head->
lchild=NULL;
head->
rchild=t;
//头结点的左链为空,右链指向第一个叶子结点t->
lchild=head;
pre=t;
//第一个叶子结点左链指向头结点,pre指向当前叶子结点
else{pre->
lchild=pre;
};
pre->
rchild=NULL;
18.假设二叉链表为二叉树的存储结构,编写算法,按照括号表示法输出二叉树的所有结点。
其过程是:
对于非空二叉树t,先输出其元素值,当存在左孩子结点或右孩子结点时,输出一个”符号,然后递归处理左子树,输出一个“,”符号,递归处理右子树,最后输出一个“)”符号。
voidDispBiTree(BiTreet){
printf("
%c"
t->
data);
if(t->
lchild!
=NULL||t->
rchild!
("
);
DispBiTree(t->
=NULL)printf("
"
)"
19.假设二叉链表为二叉树的存储结构,编写算法,输出二叉树的所有叶子结点。
voidDispLeaf(BiTreet){
rchild==NULL)printf("
%c"
DispLeaf(t->
20.假设二叉链表为二叉树的存储结构,编写算法,输出值为x的结点的所有祖先。
intAncestor(BiTreet,ElemTypex){
if(t==NULL)return0;
data==x)return1;
if(Ancestor(t->
lchild,x)||Ancestor(t->
rchild,x)){
return1;
21.假设二叉链表为二叉树的存储结构,编写算法,输出所有叶子结点到根结点的路径。
利用后序非递归遍历的特点,将其中访问结点改为判断结点是否为叶子结点,若是,输出栈中所有结点值
voidAllPathAncestor(BiTreet){
BiTNode*St[100];
BiTNode*p;
intflag,i,top=-1;
//栈指针初始化
do{
while(t){//t的所有左结点进栈
top++;
St[top]=t;
t=t->
p=NULL;
//p指向栈顶结点的前一个已访问的结点
flag=1;
//设置t的访问标记为已访问过while(top!
=-1&
flag){
t=St[top];
//出栈
rchild==p){
rchild==NULL){//若为叶子结点
for(i=top;
i>
0;
i--)printf("
%c->
"
St[i]->
//输出栈中所有结点
%c\n"
St[0]->
top--;
p=t;
//p指向刚访问过的结点
//t指向右孩子结点flag=0;
//设置未访问标记
}while(top!
=-1);
\n"
22.编写算法,将二叉树的顺序存储结构转化为二叉链表存储结构。
typedefcharElemType;
typedefstruct{//结点结构
ElemType*data;
//数据元素
intn;
//左右孩子指针
}SqBTree;
BiTreeTrans(SqBTreea,inti){//数据元素放在数组a的从下标为1开始的单元中
BiTreet;
a.n)returnNULL;
//当i大于a的结点个数if(a.data[i]=='
#'
)returnNULL;
//当i对于的结点为空t=newBiTNode;
data=a.data[i];
t->
lchild=Trans(a,2*i);
rchild=Trans(a,2*i+1);
returnt;
23.写出在中序线索二叉树中找指定结点在后序下的前驱结点的算法。
在后序序列中,若结点p有右子女,则右子女是其前驱,若无右子女而有左子女,则左子女是其前驱。
若p左右子女均无,设其中序左线索指向其祖先结点f(p是f右子树中按中序遍历的第一个结点)若f有左子女,则其右子女是p在后序下的前驱,若f无左子女,则顺其前驱找双亲的双亲,一直继续到双亲有左子女(这时左子女是p的前驱)。
还有一种情况,若p是中序遍历的第一个结点,p在中序和后序下均无前驱。
BiThrTreeInPostPre(BiThrTreet,BiThrTreep){
BiThrNode*q;
RTag==0)q=p->
//若p有右子女,则右子女是其后序前驱
elseif(p->
LTag==0)q=p->
//若p无右子女而有左子女,则左子女是其后序前驱
lchild==NULL)q=NULL;
//p是中序序列第一个结点,无后序前驱
else{//顺左线索向上找p的祖先,若存在,再找祖先的左子女while(p->
LTag==1&
p->
=NULL)p=p->
//p结点的祖先的左子女是其后序前驱
elseq=NULL;
//仅右单支树(p是叶子),已上到根结点,p结点无后序前驱
returnq;
24.写出按后序序列遍历中序线索二叉树的算法。
BiThrTreeLeftMost(BiThrTreet){//求结点t的最左子孙的左线索
BiThrTreep=t;
while(p->
LTag==0)p=p->
=NULL&
=t)return(p->
elsereturnNULL;
BiThrTreeRightMost(BiThrTreet){//求结点t的最右子孙的右线索
RTag==0)p=p->
intISRightChild(BiThrTreet,BiThrTree&
father){//若t是father的右孩子,返回1,否则返回0
father=LeftMost(t);
if(father&
father->
rchild==t)return1;
elsereturn0;
voidPostOrderInThr(BiThrTreet){//后序遍历中序线索二叉树t
BiThrTreefather,p=t->
intflag;
while(p!
=t){
//沿左分子向下if(p->
RTag==0)flag=0;
//左孩子为线索,右孩子为链,相当从左返回,p为叶子,相当从右返回elseflag=1;
while(flag==1){
p->
//访问结点if(ISRightChild(p,father)){p=father;
}//修改p指向双亲else{//p是左孩子,用最右子孙的右线索找双亲
p=RightMost(p);
if(p&
RTag==1)flag=1;
elseflag=0;
}//while(flag==1)
if(flag==0&
p!
=t)p=p->
//转向当前结点的右分支
25.已知中序线索二叉树T的右子树不空。
设计算法,将s所指结点作为T的右子树的一个叶子结点插入进去,并使之成为T的右子树的(中序序列)第一个结点。
若使新插入的结点S成T右子树中序序列的第一个结点,则应在T的右子树中最左边的结点(设
为p)处插入,使S成为结点p的左孩子。
则S的前驱是T,后继是p。
voidThrTreeInsert(BiThrTreeT,BiThrTreeS){
BiThrTreep=T->
//用p指向T的右子树中最左边的结点
S->
LTag=1;
RTag=1;
//S是叶子结点,其左右标记均为1
lchild=p->
S->
rchild=p;
//S的前驱是根结点T,后继是结点pp->
lchild=S;
p->
LTag=0;
//将p的左指针指向S,并修改左标记为0
26.写出在中序线索二叉树中找指定结点在中序下的前驱结点的算法。
BiThrTreeInorderPre(BiThrTreep){
BiThrTreeq;
LTag==1)//结点的左子树为空,结点左指针域为左线索,指向其前驱
return(p->
p结点的中序前驱
q=p->
//p结点左子树最右边结点时while(q->
RTag)q=q->