第六章树与森林.docx

上传人:b****3 文档编号:3753946 上传时间:2022-11-25 格式:DOCX 页数:28 大小:36.62KB
下载 相关 举报
第六章树与森林.docx_第1页
第1页 / 共28页
第六章树与森林.docx_第2页
第2页 / 共28页
第六章树与森林.docx_第3页
第3页 / 共28页
第六章树与森林.docx_第4页
第4页 / 共28页
第六章树与森林.docx_第5页
第5页 / 共28页
点击查看更多>>
下载资源
资源描述

第六章树与森林.docx

《第六章树与森林.docx》由会员分享,可在线阅读,更多相关《第六章树与森林.docx(28页珍藏版)》请在冰豆网上搜索。

第六章树与森林.docx

第六章树与森林

第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。

Stackst(maxSubTreeNum);//用于建表时记忆回退地址

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(q);//建立子树,p->firstChild=q

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<RootData<<‘(’;//根数据结点

elseif(ptr->utype==1){//子女数据结点

out<ChildData;

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

templateclassBinaryTree{

private:

templateclassBinTreeNode{

public:

BinTreeNode*leftChild,*rightChild;

Typedata;

}

TypeRefValue;

BinTreeNode*root;

BinTreeNode*Parent(BinTreeNode*start,BinTreeNode*current);

intInsert(BinTreeNode*current,constType&item);

intFind(BinTreeNode*current,constType&item)const;

voiddestroy(BinTreeNode*current);

voidTraverse(BinTreeNode*current,ostream&out)const;

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*GetLeft()const{returnleftChild;}

BinTreeNode*GetRight()const{returnrightChild;}

voidSetData(constType&item){data=item;}

voidSetLeft(BinTreeNode*L){leftChild=L;}

voidSetRight(BinTreeNode*R){RightChild=R;}

intIsEmpty(){returnroot==NULL?

1:

0;}

BinTreeNode*Parent(BinTreeNode*current)

{returnroot==NULL||root==current?

NULL:

Parent(root,current);}

BinTreeNode*LeftChild(BinTreeNode*current)

{returncurrent!

=NULL?

current->leftChild:

NULL;}

BinTreeNode*RighttChild(BinTreeNode*current)

{returncurrent!

=NULL?

current->rightChild:

NULL;}

intInsert(constType&item);

BinTreeNode*Find(constType&item);

BinTreeNode*GetRoot()const{returnroot;}

friendistream&operator>>(istream&in,BinaryTree&Tree);//输入二叉树

friendostream&operator<<(ostream&out,BinaryTree&Tree);//输出二叉树

}

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*ptr){

if(ptr==NULL)return0;

elseif(ptr->leftChild==NULL&&ptr->rightChild==NULL)return1;

elsereturnleaf(ptr->leftChild)+leaf(ptr->rightChild);

}

(2)交换每个结点的左子女和右子女

voidBinaryTree:

:

exchange(BinTreeNode*ptr){

BinTreeNode*temp;

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-11

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1