关注公众号凡花花的小窝,可以获取更多的计算机相关的资源
第7 章 二叉树
7.1 选择题。
(1)前序遍历和中序遍历结果相同的二叉树为( F );前序遍历和后序遍历结果相同的
二叉树为( B )。
A.一般二叉树 B.只有根结点的二叉树
C.根结点无左孩子的二叉树 D.根结点无右孩子的二叉树
E.所有结点只有左子树的二叉树 F.所有结点只有右子树的二叉树。
(2)以下有关二叉树的说法正确的是( B )。
A.二叉树的度为2 B.一棵二叉树的度可以小于2
C.二叉树中至少有一个结点的度为2 D.二叉树中任一个结点的度均为2
(3)一棵完全二叉树上有1001 个结点,其中叶子结点的个数为( D )。
A.250 B.500 C.254 D.501
(4)一棵完全二叉树有999 个结点,它的深度为( B )。
A.9 B.10 C.11 D.12
(5)一棵具有5 层的满二叉树所包含的结点个数为( B )。
A.15 B.31 C.63 D.32
7.2 用一维数组存放完全二叉树:ABCDEFGHI,则后序遍历该二叉树的结点序列为
( HIDEBFGCA )。
7.3 有n 个结点的二叉树,已知叶结点个数为n0,则该树中度为1 的结点的个数为
( n-2n0+1 );若此树是深度为k 的完全二叉树,则n 的最小值为( 2k-1 )。
7.4 设F 是由T1、T2 和T3 三棵树组成的森林,与F 对应的二叉树为B。已知T1、T2
和T3 的结点数分别是n1、n2 和n3,则二叉树B 的左子树中有( n1-1 )个结点,二叉树
B 的右子树中有( n2+n3 )结点。
7.5 高度为k 的二叉树的最大结点数为( 2k-1 ),最小结点数为( k )。
7.6 对于一棵具有n 个结点的二叉树,该二叉树中所有结点的度数之和为( n-1 )。
7.7 已知一棵二叉树如图7.12 所示,试求:
(1)该二叉树前序、中序和后序遍历的结果;
【答】:前序:abdgecfh;中序:dgbcafhc;后序:gdebhfca
(2)该二叉树是否是满二叉树?是否是完全二叉树?
【答】:该二叉树不是满二叉树,也不是完全二叉树。
(3)将它转换成对应的树或森林;
【答】:
图7.12 一棵二叉树
63
(4)这棵二叉树的深度为多少?
【答】:该二叉树的深度为4。
(5)试对该二叉树进行前序线索化;
【答】:
a
b c
d e f
g h
`
(6)试对该二叉树进行中序线索化。
【答】:
7.8 试述树和二叉树的主要区别。
64
【答】:
(1)树的结点个数至少为1,而二叉树的结点个数可以为0。
(2)树中结点的最大度数没有限制,而二叉树结点的最大度数为2。
(3)树分为有序树与无序树,而二叉树一定是有序树,它的结点有左,右之分。
7.9 试分别画出具有3 个结点的树和具有3 个结点的二叉树的所有不同形态。
【答】:
三个结点的树有两种形态:
三个结点的二叉树具有五种形态:
7.10 已知一棵二叉树的中序遍历的结果为ABCEFGHD , 后序遍历的结果为
ABFHGEDC,试画出此二叉树。
【答】:
7.11 已知一棵二叉树的前序遍历的结果为ABCDEF,中序遍历的结果为CBAEDF,试
画出此二叉树。
【答】:
65
7.12 若一棵二叉树的左、右子树均有3 个结点,其左子树的前序序列与中序序列相同,
右子树的中序序列与后序序列相同,试画出该二叉树。
【答】:
7.13 分别采用递归和非递归方式编写两个函数,求一棵给定二叉树中叶子结点的个数。
【答】:为方便测试二叉树相关程序,定义二叉树头文件bintree.h 如下:
#include
#define N 100
extern char *a; /存放扩充二叉树的前序序列/
typedef struct node /二叉树结构定义/
{
char data;
struct node *lchild,*rchild;
}binnode;
typedef binnode *bintree;
/函数creat(根据扩充二叉树的前序序列(字符串a)建立二叉树t 的存储结构/
void creat(bintree * t)
{
char ch=*a++;
if (ch==’ ‘) *t=NULL;
else
{ *t=(bintree)malloc(sizeof(binnode));
(*t)->data=ch;
creat(&(*t)->lchild);
creat(&(*t)->rchild);
}
}
void preorder(bintree t) /前序递归遍历二叉树/
{
66
if (t)
{ printf("%c",t->data);
preorder(t->lchild);
preorder(t->rchild);
}
}
/顺序栈定义/
typedef struct
{ bintree data[N];
int top;
}seqstack;
void init(seqstack *s) /初始化空栈/
{
s->top=-1;
}
int empty(seqstack *s) /判断栈是否为空/
{
if (s->top>-1) return 0;
else return 1;
}
int full(seqstack *s) /判断栈是否为满/
{
if (s->topN-1) return 1;
else return 0;
}
void push(seqstack *s ,bintree x) /进栈/
{
if (!full(s))
s->data[++s->top]=x;
}
bintree pop(seqstack *s) /出栈/
{
if (!empty(s))
return s->data[s->top–];
}
基于上述结构,递归方法与非递归方法求二叉树中叶子结点的个数的算法分别如leaf1()
67
与leaf2()所示:
#include “bintree.h”
char *a="ABC D EF G "; /扩充二叉树序树t 的前序序列/
int leaf1(bintree t) /递归方法求二叉树叶子结点的个数/
{
if (tNULL) return 0;
else
if (!t->lchild && !t->rchild)
return 1;
else
return leaf1(t->lchild)+leaf1(t->rchild);
}
int leaf2(bintree t) /非递归方法求二叉树叶子结点的个数/
{
seqstack s; /顺序栈/
int count=0; /叶子结点计数变量/
init(&s); /初始化空栈/
while (t || !empty(&s))
{
if (t)
{if (!t->lchild && !t->rchild) count++;
push(&s,t);
t=t->lchild;
}
else
{t=pop(&s);
t=t->rchild;
}
}
return count;
}
int main()
{ bintree t;
creat(&t); /建立二叉树t 的存储结构/
printf("\n 该二叉树一共有%d 个叶子结点!\n",leaf1(t));
printf("\n 该二叉树一共有%d 个叶子结点!\n",leaf2(t));
}
7.14 试编写一个函数,将一棵给定二叉树中所有结点的左、右子女互换。
68
【答】:
#include “bintree.h”
char *a=“ABC D EF G “; /扩充二叉树序树t 的前序序列/
void change(bintree t)
{ bintree p;
if (t)
{
p=t->lchild;
t->lchild=t->rchild;
t->rchild=p;
change(t->lchild);
change(t->rchild);
}
}
int main()
{ bintree t;
creat(&t); /建立二叉树t 的存储结构/
preorder(t);
change(t);
printf(”\n”);
preorder(t);
}
7.15 试编写一个函数,返回一棵给定二叉树在中序遍历下的最后一个结点。
【答】:
#include “bintree.h”
char *a="ABC D EF G "; /扩充二叉树序树t 的前序序列/
bintree inlast(bintree t)
{ bintree p=t;
while (p && p->rchild)
p=p->rchild;
return p;
}
int main()
{ bintree t;
creat(&t); /建立二叉树t 的存储结构/
printf(“二叉树中序遍历最后一个结点是%c\n”,inlast(t)->data);
}
7.16 试编写一个函数,返回一棵给定二叉树在前序遍历下的最后一个结点。
69
【答】:
#include “bintree.h”
char *a="ABC D EF G "; /扩充二叉树序树t 的前序序列/
/求二叉树前序遍历的最后一个结点/
bintree prelast(bintree t)
{ bintree p;
if (t)
{
p=t;
while (p && p->lchild || p->rchild)
if (p->rchild)
p=p->rchild;
else
p=p->lchild;
}
return p;
}
int main()
{ bintree t;
creat(&t); /建立二叉树t 的存储结构/
printf(“二叉树前序遍历的最后一个结点是%c\n”,prelast(t)->data);
}
7.17 试编写一个函数,返回一棵给定二叉树在后序遍历下的第一个结点。
【答】:
#include “bintree.h”
char *a="ABC D EF G "; /扩充二叉树序树t 的前序序列/
/求二叉树后序遍历的第一个结点/
bintree succfirst(bintree t)
{ bintree p;
if (t)
{ p=t;
while (p && p->lchild || p->rchild)
if (p->lchild)
p=p->lchild;
else
p=p->rchild;
}
return p;
}
70
int main()
{ bintree t;
creat(&t); /建立二叉树t 的存储结构/
printf(“二叉树后序遍历的第一个结点是%c\n”,succfirst(t)->data);
}
7.18 假设二叉树采用链式方式存储,root 为其根结点,p 指向二叉树中的任意一个结点,
编写一个求从根结点到p 所指结点之间路径长度的函数。
【答】:在后序遍历非递归算法中,当访问的结点为p 时,其祖先点正好全部在栈中,此
时栈中结点的个数就是根结点到p 所指结点之间路径长度。
#include
#include
typedef char datatype;
typedef struct node /二叉树结点定义/
{ datatype data;
struct node *lchild,*rchild;
}bintnode;
typedef bintnode *bintree;
typedef struct stack
{
bintree data[100];
int tag[100];
int top;
}seqstack;
void creat(bintree t) ;
/
函数Depth,功能:求根结点到x 的路径长度
*/
int Depth(bintree t,datatype x)
{
seqstack s;
int i=0,j;
s.top=0;
while(t || s.top!=0)
{
while(t)
{
s.data[s.top]=t;
s.tag[s.top]=0;
71
s.top++;
t=t->lchild;
}
while(s.top>0 && s.tag[s.top-1])
{
s.top–;
t=s.data[s.top];
if(t->datax) return s.top; //此时栈中的结点都是x 的祖先结点
}
if(s.top>0)
{
t=s.data[s.top-1];
s.tag[s.top-1]=1;
t=t->rchild;
}
else t=NULL;
}
}
/函数creat(根据扩充二叉树的前序序列建立二叉树t 的存储结构/
void creat(bintree *t)
{
char ch;
scanf("%c",&ch);
if (ch’ ‘)
*t=NULL;
else {
*t=(bintnode *)malloc(sizeof(bintnode));
(*t)->data=ch;
creat(&(*t)->lchild);
creat(&(*t)->rchild);
}
}
int main()
{ bintree root,p=NULL;
datatype x;
int k=0;
printf(“请输入扩充二叉树的前序序列:\n”);
creat(&root);
72
printf(“请输入树中的1 个结点值:\n”);
scanf("%1s",&x);
k=Depth(root,x);
printf(“根结点到%c 的长度是%d\n”,x,k);
}
7.19 假设二叉树采用链式方式存储,root 为其根结点,p 和q 分别指向二叉树中任意两
个结点,编写一个函数,返回p 和q 最近的共同祖先。
【答】:方法同上题,利用后序遍历非递归算法分别求出p 和q 的公共祖先,然后再查找
它们的最近公共祖先结点。
#include
#include
typedef char datatype;
typedef struct node /二叉树结点定义/
{ datatype data;
struct node *lchild,*rchild;
}bintnode;
typedef bintnode *bintree;
typedef struct stack //顺序栈结构定义
{ bintree data[100];
int tag[100];
int top;
}seqstack;
void creat(bintree *t) ; //创建二叉树结构函数声明
/函数SeekAncestor 的功能是返回二叉树t 中结点x 与结点y 的最近公共祖先结点/
void SeekAncestor(bintree t,datatype x,datatype y,bintree *antor)
{ seqstack s;
bintree data[100]={0};
int i=0,j;
s.top=-1;
while(t || s.top>-1)
{ while(t)
{
s.data[++s.top]=t;
s.tag[s.top]=0;
t=t->lchild;
}
73
while(s.top>-1 && s.tag[s.top])
{
t=s.data[s.top];
if(t->datax)
while(i<=s.top) //记录x 结点的所有祖先结点
{
data[i]=s.data[i];
i++;
}
else if(t->datay)
{
while(s.top>-1)
{
j=i-1;
while(j>=0&&t!=data[j])//查找y 与x 的最近公共祖先结点
j–;
if(j>=0)
{
*antor=data[j]; //返回公共祖先结点地址
return;
}
t=s.data[–s.top];
}
}
–s.top;
}
if(s.top>-1)
{
t=s.data[s.top];
s.tag[s.top]=1;
t=t->rchild;
}
else t=NULL;
}
}
/函数creat(根据扩充二叉树的前序序列建立二叉树t 的存储结构/
void creat(bintree *t)
{
char ch;
74
scanf("%c",&ch);
if (ch==’ ')
*t=NULL;
else {
*t=(bintnode *)malloc(sizeof(bintnode));
(*t)->data=ch;
creat(&(*t)->lchild);
creat(&(*t)->rchild);
}
}
int main()
{
bintree root,p=NULL;
datatype x=‘B’,y=‘C’;
printf(“请输入扩充二叉树的前序序列:\n”);
creat(&root);
printf(“请输入树中的两个结点值:\n”);
scanf("%1s%c",&x,&y);
SeekAncestor(root,x,y,&p);
if §printf("%c 和%c 的最近公共祖先是:%c\n",x,y,p->data);
}
75