您的位置:首页 > 其它

森林的双亲孩子表示法的设计与实现

2017-04-11 17:33 239 查看
问题:仿照树的双亲孩子表示法,设计森林的双亲孩子存储结构。要求实现森林的先根、中根、后根遍历,能求森林的规模(森林中树的数目)、森林的高度(森林中树的最大高度)、森林的叶子数(森林中所有树的叶子之和)。

这是笔者在学习数据结构时遇到的一个题目。

以先根遍历为例。先根遍历需要先访问第一棵树的根结点,再先根遍历第一棵树根结点的子树组成的森林,再先根遍历除第一棵树之外的其他树组成的森林。那么最重要的是就是用什么来表示一个森林呢?对于一棵树我们可以通过它的根结点来表示,但是森林是由若干个树组成的,他是没有根结点的。所以我们就可以创造一个虚拟的根结点,来代表这整个森林。我们用这个虚拟根结点的第一个孩子来表示第一棵树的子树,再设置一个虚拟结点2,并且连接上除第一棵树之外的树,以表示这个森林。那么遍历的问题就迎刃而解。

例子如下。



代码如下:

//Node.h

#ifndef NODE_H
#define NODE_H
#include <iostream>
using namespace std;

//孩子结点
template <class ElemType>
struct Child{
int data;                //数据域
Child<ElemType> *next;    //指向下一个孩子的指针
Child();        //无参数的构造函数
Child(int n=0,Child<ElemType> *nex=NULL);
};

//数组中的结点
template <class ElemType>
struct ParentChild
{
ElemType data;                //    数据域
int parent;                    //双亲结点在数组中的位置
Child<ElemType> *firstChild;                    //指向首孩子的指针

ParentChild();                //无参数的构造函数
ParentChild(ElemType val, int par=0, Child<ElemType> *fChild=NULL);    //有参数的构造函数
};

template <class ElemType>
ParentChild<ElemType>::ParentChild(){
firstChild=NULL;
}

template <class ElemType>
ParentChild<ElemType>::ParentChild(ElemType val,int par,Child<ElemType> *fChild){
data=val;
parent=par;
firstChild=fChild;
}

template <class ElemType>
Child<ElemType>::Child(){
next=NULL;
}

template <class ElemType>
Child<ElemType>::Child(int n,Child<ElemType> *nex)
{
data=n;
next=nex;
}

#endif

//ParentChildForest.h

#ifndef PARENTCHILDFOREST_H
#define PARENTCHILDFOREST_H
#include "Node.h"
#include <iostream>
using namespace std;

template<class ElemType>
class ParentChildForest
{
public:
ParentChild<ElemType> a[50];        //存储空间
ParentChild<ElemType> *root;
int num;                    //总结点个数
public:
ParentChildForest(ElemType item[],int parents[],int Num=0);        //有参数的构造函数
void PreOrder(ParentChild<ElemType> r);            //先根遍历r为的子树森林
void MidOrder(ParentChild<ElemType> r);            //中根遍历r为的子树森林
void PostOrder(ParentChild<ElemType> r);        //后根遍历r为的子树森林
int TreeNum();                //求森林中树的数目
int Height();                //求森林的高度
int Leaf();                    //叶子数
void Show();
4000
};

template<class ElemType>
ParentChildForest<ElemType>::ParentChildForest(ElemType item[],int parents[],int Num)
{
int i;
for(i=0;item[i]!=NULL;i++){            //全部存放到结点数组内
a[i+1].data = item[i];
a[i+1].parent = parents[i];
a[i+1].firstChild = NULL;
}
a[0].parent=-1;
num=Num;
a[0].data=a[2].data;
*root=a[0];
for(i=1;i<=num;i++){            //构造各个结点的孩子的单链表
Child<ElemType> *p,*q;
q = new Child<ElemType>(i,NULL);
if(a[a[i].parent].firstChild==NULL){
a[a[i].parent].firstChild=q;
}
else{
for(p=a[a[i].parent].firstChild;p->next!=NULL;p=p->next){}
p->next=q;
}
}
root->firstChild=a[0].firstChild;
}

template<class ElemType>
void ParentChildForest<ElemType>::PreOrder(ParentChild<ElemType> r)
{    //先根遍历
if(r.firstChild!=NULL){        //若森林不为空
cout<<a[r.firstChild->data].data<<"  ";        //访问第一棵树的根结点
PreOrder(a[r.firstChild->data]);    //先根遍历第一棵树的根结点的子树森林
if(r.firstChild->next!=NULL){
ParentChild<ElemType> temp;
temp.firstChild = r.firstChild->next;
PreOrder(temp);                    //先根遍历其他树组成的森林
}
}
}

template<class ElemType>
void ParentChildForest<ElemType>::MidOrder(ParentChild<ElemType> r)
{    //中根遍历
if(r.firstChild!=NULL){        //若森林不为空
MidOrder(a[r.firstChild->data]);    //中根遍历第一棵树的根结点的子树森林
cout<<a[r.firstChild->data].data<<"  ";        //访问第一棵树的根结点
if(r.firstChild->next!=NULL){
ParentChild<ElemType> temp;
temp.firstChild = r.firstChild->next;
MidOrder(temp);                    //中根遍历其他树组成的森林
}
}
}

template<class ElemType>
void ParentChildForest<ElemType>::PostOrder(ParentChild<ElemType> r)
{    //后根遍历
if(r.firstChild!=NULL){        //若森林不为空
PostOrder(a[r.firstChild->data]);    //后根遍历第一棵树的根结点的子树森林
if(r.firstChild->next!=NULL){
ParentChild<ElemType> temp;
temp.firstChild = r.firstChild->next;
PostOrder(temp);                    //后根遍历其他树组成的森林
}
cout<<a[r.firstChild->data].data<<"  ";        //访问第一棵树的根结点
}
}

template<class ElemType>
int ParentChildForest<ElemType>::TreeNum()
{    //返回森林中树的数目

int treenum=0;
Child<ElemType> *p;
p=a[0].firstChild;
for(;p!=NULL;p=p->next){
treenum++;
}
return treenum;

}

template<class ElemType>
int ParentChildForest<ElemType>::Height()
{    //求森林的高度
if(a[0].firstChild!=NULL){
int temp=0,height=0;
Child<ElemType> *p;
p=a[0].firstChild;
for(;p->next!=NULL;p=p->next){
temp=0;
int i=p->next->data-1;
while(a[i].parent>=0){
i=a[i].parent;
temp++;
}
height=(temp>height)?temp:height;
}
temp=0;
int i=num;
while(a[i].parent>=0){
i=a[i].parent;
temp++;
}
height=(temp>height)?temp:height;
return height;
}
else{
return 0;
}
}

template<class ElemType>
int ParentChildForest<ElemType>::Leaf()
{
int leaf=0;
for(int i=0;i<=num;i++){
if(a[i].firstChild==NULL){
leaf++;
}
}
return leaf;
}

template<class ElemType>
void ParentChildForest<ElemType>::Show()
{
for(int i=0;i<=num;i++){
cout<<i;
cout<<"( "<<a[i].data<<", "<<a[i].parent<<", ";
Child<ElemType> *p;
if(a[i].firstChild==NULL){
cout<<"^)"<<endl;
}
else{
p=a[i].firstChild;
while(p){
cout<<" )->( "<<p->data<<", ";
p=p->next;
}
cout<<"^)"<<endl;
}
}
}

#endif

//main.cpp

#include "ParentChildForest.h"
#include "assistance.h"
#include <windows.h>

int main(){
char item[]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P'};
int parents[]={0,1,1,0,4,5,0,7,7,7,8,8,10,10,10,13};
ParentChildForest<char> t(item,parents,16);
t.Show();
cout<<"输入任意值以继续:";
char c;
cin>>c;
cout<<"先根遍历: ";
t.PreOrder(t.a[0]);
cout<<endl;
cout<<"中根遍历: ";
t.MidOrder(t.a[0]);
cout<<endl;
cout<<"后根遍历: ";
t.PostOrder(t.a[0]);
cout<<endl;
cout<<"该森林中树的数目为: "<<t.TreeNum()<<endl;
cout<<"该森林的高度为: "<<t.Height()<<endl;
cout<<"该森林的叶子数目为: "<<t.Leaf()<<endl;
system("pause");
return 0;
}


运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: