树二叉树和森林.docx
- 文档编号:23396841
- 上传时间:2023-05-16
- 格式:DOCX
- 页数:34
- 大小:34.50KB
树二叉树和森林.docx
《树二叉树和森林.docx》由会员分享,可在线阅读,更多相关《树二叉树和森林.docx(34页珍藏版)》请在冰豆网上搜索。
树二叉树和森林
第6章树与森林
6-1写出用广义表表示法表示的树的类声明,并给出如下成员函数的实现:
(1)operator>>()接收用广义表表示的树作为输入,建立广义表的存储表示;
(2)复制构造函数用另一棵表示为广义表的树初始化一棵树;
(3)operator==()测试用广义表表示的两棵树是否相等;
(4)operator<<()用广义表的形式输出一棵树;
(5)析构函数清除一棵用广义表表示的树。
【解答】
#include
#definemaxSubTreeNum20;//最大子树(子表)个数
classGenTree;//GenTree类的前视声明
classGenTreeNode{//广义树结点类的声明
friendclassGenTree;
private:
intutype;//结点标志:
=0,数据;=1,子女
GenTreeNode*nextSibling;//utype=0,指向第一个子女;
//utype=1或2,指向同一层下一兄弟
union{//联合
charRootData;//utype=0,根结点数据
charChilddata;//utype=1,子女结点数据
GenTreeNode*firstChild;//utype=2,指向第一个子女的指针
}
public:
GenTreeNode(inttp,charitem):
utype(tp),nextSibling(NULL)
{if(tp==0)RootData=item;elseChildData=item;}
//构造函数:
构造广义表表示的树的数据结点
GenTreeNode(GenTreeNode*son=NULL):
utype
(2),nextSibling(NULL),firstChild(son){}
//构造函数:
构造广义表表示的树的子树结点
intnodetype(){returnutype;}//返回结点的数据类型
charGetData(){returndata;}//返回数据结点的值
GenTreeNode*GetFchild(){returnfirstChild;}//返回子树结点的地址
GenTreeNode*GetNsibling(){returnnextSibling;}//返回下一个兄弟结点的地址
voidsetInfo(charitem){data=item;}//将结点中的值修改为item
voidsetFchild(GenTreeNode*ptr){firstChild=ptr;}//将结点中的子树指针修改为ptr
voidsetNsinbilg(GenTreeNode*ptr){nextSibling=ptr;}
};
classGenTree{//广义树类定义
private:
GenTreeNode*first;//根指针
charretValue;//建树时的停止输入标志
GenTreeNode*Copy(GenTreeNode*ptr);//复制一个ptr指示的子树
voidTraverse(GenListNode*ptr);//对ptr为根的子树遍历并输出
voidRemove(GenTreeNode*ptr);//将以ptr为根的广义树结构释放
friendintEqual(GenTreeNode*s,GenTreeNode*t);//比较以s和t为根的树是否相等
public:
GenTree();//构造函数
GenTree(GenTree&t);//复制构造函数
~GenTree();//析构函数
friendintoperator==(GenTree&t1,GenTree&t2);//判两棵树t1与t2是否相等
friendistream&operator>>(istream&in,GenTree&t);//输入
friendostream&operator<<(ostream&out,GenTree&t);//输出
}
(1)operator>>()接收用广义表表示的树作为输入,建立广义表的存储表示
istream&operator>>(istream&in,GenTree&t){
//友元函数,从输入流对象in接受用广义表表示的树,建立广义表的存储表示t。
t.ConstructTree(in,retValue);
returnin;
}
voidGenTree:
:
ConstructTree(istream&in,char&value){
//从输入流对象in接受用广义表表示的非空树,建立广义表的存储表示t。
Stack
GenTreeNode*p,q,r;Typech;
cin>>value;//广义树停止输入标志数据
cin>>ch;first=q=newGenTreeNode(0,ch);//建立整个树的根结点
cin>>ch;if(ch==‘(’)st.Push(q);//接着应是‘(’,进栈
cin>>ch;
while(ch!
=value){//逐个结点加入
switch(ch){
case‘(’:
p=newGenTreeNode
r=st.GetTop();st.Pop();//从栈中退出前一结点
r->nextSibling=p;//插在前一结点r之后
st.Push(p);st.Push(q);//子树结点及子树根结点进栈
break;
case‘)’:
q->nextSibling=NULL;st.pop();//子树建成,封闭链,退到上层
if(st.IsEmpty()==0)q=st.GetTop();//栈不空,取上层链子树结点
elsereturn0;//栈空,无上层链,算法结束
break;
case‘,’:
break;
default:
p=q;
if(isupper(ch))q=newGenTreeNode(0,ch);//大写字母,建根结点
elseq=newGenTreeNode(1,ch);//非大写字母,建数据结点
p->nextSibling=q;//链接
}
cin>>ch;
}
}
(2)复制构造函数用另一棵表示为广义表的树初始化一棵树;
GenTree:
:
GenTree(constGenTree&t){//共有函数
first=Copy(t.first);
}
GenTreeNode*GenTree:
:
Copy(GenTreeNode*ptr){
//私有函数,复制一个ptr指示的用广义表表示的子树
GenTreeNode*q=NULL;
if(ptr!
=NULL){
q=newGenTreeNode(ptr->utype,NULL);
switch(ptr->utype){//根据结点类型utype传送值域
case0:
q->RootData=ptr->RootData;break;//传送根结点数据
case1:
q->ChildData=ptr->ChildData;break;//传送子女结点数据
case2:
q->firstChild=Copy(ptr->firstChild);break;//递归传送子树信息
}
q->nextSibling=Copy(ptr->nextSibling);//复制同一层下一结点为头的表
}
returnq;
}
(3)operator==()测试用广义表表示的两棵树是否相等
intoperator==(GenTree&t1,GenTree&t2){
//友元函数:
判两棵树t1与t2是否相等,若两表完全相等,函数返回1,否则返回0。
returnEqual(t1.first,t2.first);
}
intEqual(GenTreeNode*t1,GenTreeNode*t2){
//是GenTreeNode的友元函数
intx;
if(t1==NULL&&t2==NULL)return1;//表t1与表t2都是空树,相等
if(t1!
=NULL&&t2!
=NULL&&t1->utype==t2->utype){//两子树都非空且结点类型相同
switch(t1->utype){//比较对应数据
case0:
x=(t1->RootData==t2->RootData)?
1:
0;//根数据结点
break;
case1:
x=(t1->ChildData==t2->ChildData)?
1:
0;//子女数据结点
break;
case2:
x=Equal(t1->firstChild,t2->firstChild);//递归比较其子树
}
if(x)returnEqual(t1->nextSibling,t2->nextSibling);
//相等,递归比较同一层的下一个结点;不等,不再递归比较
}
return0;
}
(4)operator<<()用广义表的形式输出一棵树
ostream&operator<<(ostream&out,GenTree&t){
//友元函数,将树t输出到输出流对象out。
t.traverse(out,t.first);
returnout;
}
voidGenTree:
:
traverse(ostream&out,GenTreeNode*ptr){
//私有函数,广义树的遍历算法
if(ptr!
=NULL){
if(ptr->utype==0)out<
elseif(ptr->utype==1){//子女数据结点
out<
if(ptr->nextSibling!
=NULL)out<<‘,’;
}
else{//子树结点
traverse(ptr->firstChild);//向子树方向搜索
if(ptr->nextSibling!
=NULL)out<<‘,’;
}
traverse(ptr->nextSibling);//向同一层下一兄弟搜索
}
elseout<<‘)’;
}
(5)析构函数清除一棵用广义表表示的树
GenTree:
:
~GenTree(){
//用广义表表示的树的析构函数,假定first≠NULL
Remove(first);
}
voidGenTree:
:
Remove(GenTreeNode*ptr){
GenTreeNode*p;
while(ptr!
=NULL){
p=ptr->nextSibling;
if(p->utype==2)Remove(p->firstChild);//在子树中删除
ptr->nextSibling=p->nextSibling;delete(p);//释放结点p
}
}
6-2列出右图所示二叉树的叶结点、分支结点和每个结点的层次。
【解答】
二叉树的叶结点有⑥、⑧、⑨。
分支结点有①、②、③、④、⑤、⑦。
结点①的层次为0;结点②、③的层次为1;结点④、⑤、⑥的层次为2;结点⑦、⑧的层次为3;结点⑨的层次为4。
6-3使用
(1)顺序表示和
(2)二叉链表表示法,分别画出右图所示二叉树的存储表示。
【解答】
0123456789
①
①②③④⑤⑥⑦
∧
③
②
101112131415161718
∧
⑤
∧
⑥
∧
∧
④
⑧⑨
∧
∧
∧
⑧
⑦
顺序表示
二叉链表表示
∧
∧
⑨
6-4用嵌套类写出用链表表示的二叉树的类声明。
【解答】
#include
template
private:
template
public:
BinTreeNode
Typedata;
}
TypeRefValue;
BinTreeNode
BinTreeNode
intInsert(BinTreeNode
intFind(BinTreeNode
voiddestroy(BinTreeNode
voidTraverse(BinTreeNode
public:
BinaryTree():
root(NULL){}
BinaryTree(Typevalue):
RefValue(value),root(NULL){}
~BinaryTree(){destroy(root);}
BinTreeNode():
leftChild(NULL),rightChild(NULL){}
BinTreeNode(Typeitem):
data(item),leftChild(NULL),rightChild(NULL){}
Type&GetData()const{returndata;}
BinTreeNode
BinTreeNode
voidSetData(constType&item){data=item;}
voidSetLeft(BinTreeNode
voidSetRight(BinTreeNode
intIsEmpty(){returnroot==NULL?
1:
0;}
BinTreeNode
{returnroot==NULL||root==current?
NULL:
Parent(root,current);}
BinTreeNode
{returncurrent!
=NULL?
current->leftChild:
NULL;}
BinTreeNode
{returncurrent!
=NULL?
current->rightChild:
NULL;}
intInsert(constType&item);
BinTreeNode
BinTreeNode
friendistream&operator>>(istream&in,BinaryTree
friendostream&operator<<(ostream&out,BinaryTree
}
6-5在结点个数为n(n>1)的各棵树中,高度最小的树的高度是多少?
它有多少个叶结点?
多少个分支结点?
高度最大的树的高度是多少?
它有多少个叶结点?
多少个分支结点?
【解答】
结点个数为n时,高度最小的树的高度为1,有2层;它有n-1个叶结点,1个分支结点;高度最大的树的高度为n-1,有n层;它有1个叶结点,n-1个分支结点。
6-6试分别画出具有3个结点的树和3个结点的二叉树的所有不同形态。
【解答】
具有3个结点的树具有3个结点的二叉树
6-7如果一棵树有n1个度为1的结点,有n2个度为2的结点,…,nm个度为m的结点,试问有多少个度为0的结点?
试推导之。
【解答】
总结点数n=n0+n1+n2+…+nm
总分支数e=n-1=n0+n1+n2+…+nm-1
=m*nm+(m-1)*nm-1+…+2*n2+n1
则有
6-8试分别找出满足以下条件的所有二叉树:
(1)二叉树的前序序列与中序序列相同;
(2)二叉树的中序序列与后序序列相同;
(3)二叉树的前序序列与后序序列相同。
【解答】
(1)二叉树的前序序列与中序序列相同:
空树或缺左子树的单支树;
(2)二叉树的中序序列与后序序列相同:
空树或缺右子树的单支树;
(3)二叉树的前序序列与后序序列相同:
空树或只有根结点的二叉树。
6-9若用二叉链表作为二叉树的存储表示,试针对以下问题编写递归算法:
(1)统计二叉树中叶结点的个数。
(2)以二叉树为参数,交换每个结点的左子女和右子女。
【解答】
(1)统计二叉树中叶结点个数
intBinaryTree
:
leaf(BinTreeNode
if(ptr==NULL)return0;
elseif(ptr->leftChild==NULL&&ptr->rightChild==NULL)return1;
elsereturnleaf(ptr->leftChild)+leaf(ptr->rightChild);
}
(2)交换每个结点的左子女和右子女
voidBinaryTree
:
exchange(BinTreeNode
BinTreeNode
if(ptr->leftChild!
=NULL||ptr->rightChild!
=NULL){
temp=ptr->leftChild;
ptr->leftChild=ptr->rightChild;
ptr->rightChild=temp;
exchange(ptr->leftChild);
exchange(ptr->rightChild);
}
}
6-10一棵高度为h的满k叉树有如下性质:
第h层上的结点都是叶结点,其余各层上每个结点都有k棵非空子树,如果按层次自顶向下,同一层自左向右,顺序从1开始对全部结点进行编号,试问:
(1)各层的结点个数是多少?
(2)编号为i的结点的父结点(若存在)的编号是多少?
(3)编号为i的结点的第m个孩子结点(若存在)的编号是多少?
(4)编号为i的结点有右兄弟的条件是什么?
其右兄弟结点的编号是多少?
(5)若结点个数为n,则高度h是n的什么函数关系?
【解答】
(1)ki(i=0,1,……,h)
(2)
(3)(i-1)*k+m+1
(4)(i-1)%k0或
时有右兄弟,右兄弟为i+1。
(5)h=logk(n*(k-1)+1)-1(n=0时h=-1)
6
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 二叉 森林