森林的双亲孩子表示法的设计与实现
2017-04-11 17:33
239 查看
问题:仿照树的双亲孩子表示法,设计森林的双亲孩子存储结构。要求实现森林的先根、中根、后根遍历,能求森林的规模(森林中树的数目)、森林的高度(森林中树的最大高度)、森林的叶子数(森林中所有树的叶子之和)。
这是笔者在学习数据结构时遇到的一个题目。
以先根遍历为例。先根遍历需要先访问第一棵树的根结点,再先根遍历第一棵树根结点的子树组成的森林,再先根遍历除第一棵树之外的其他树组成的森林。那么最重要的是就是用什么来表示一个森林呢?对于一棵树我们可以通过它的根结点来表示,但是森林是由若干个树组成的,他是没有根结点的。所以我们就可以创造一个虚拟的根结点,来代表这整个森林。我们用这个虚拟根结点的第一个孩子来表示第一棵树的子树,再设置一个虚拟结点2,并且连接上除第一棵树之外的树,以表示这个森林。那么遍历的问题就迎刃而解。
例子如下。
代码如下:
运行结果:
这是笔者在学习数据结构时遇到的一个题目。
以先根遍历为例。先根遍历需要先访问第一棵树的根结点,再先根遍历第一棵树根结点的子树组成的森林,再先根遍历除第一棵树之外的其他树组成的森林。那么最重要的是就是用什么来表示一个森林呢?对于一棵树我们可以通过它的根结点来表示,但是森林是由若干个树组成的,他是没有根结点的。所以我们就可以创造一个虚拟的根结点,来代表这整个森林。我们用这个虚拟根结点的第一个孩子来表示第一棵树的子树,再设置一个虚拟结点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; }
运行结果:
相关文章推荐
- 看数据结构写代码(30) 树的双亲孩子表示法的实现
- 数据结构之通用树(使用链表实现树的存储结构,双亲孩子表示法)
- 树的孩子兄弟表示法 及遍历实现
- 孩子兄弟表示法实现树
- 假设nn的稀疏矩阵A采用三元组表示,设计一个程序exp6-4.cpp实现如下功能:
- 树-孩子兄弟表示法的实现
- DELPHI 孩子兄弟表示法 (递归实现)
- 二叉树的查找、二叉树高度、二叉树获得双亲结点、构造二叉树、二叉树的广义表表示法、二叉树的插入删除、二叉树的非递归实现
- C++ 树-双亲表示法、孩子表示法、双亲孩子表示法
- 二叉树采用二叉链表结构表示。设计并实现如下算法:后序递归建树,先序非递归遍历该树。
- (id,pid)格式数据转树和森林结构工具类设计与实现
- 使用C++ 和 孩子兄弟表示法实现树
- 树 的 双亲表示法 及 双亲孩子表示法
- C#实现树的双亲表示法
- 树的括号表示+树的孩子表示线性结构实现
- 采用左孩子右兄弟结构实现森林
- 数的 双亲孩子 表示法结点结构定义
- 树的双亲孩子表示法
- 树的存储结构之双亲孩子表示法
- 6-6-树的孩子链表(带双亲)存储表示法-树和二叉树-第6章-《数据结构》课本源码-严蔚敏吴伟民版