C++树(兄弟孩子结构实现)

树转换为二叉树,森林转换为二叉树,都是基于树的兄弟孩子结构实现的。

树有三种遍历:先根遍历,后根遍历,层次遍历。前两种分别对应于二叉树的前序遍历和中序遍历。层次遍历和二叉树的层次遍历也很相似。

下面是代码:

文件"tree.h"

#include<iostream> #include<stack> using namespace std; //循环队列模版 template<class T> class My_queue; template<class T> class Node { private: T data; Node<T> *next; public: Node() { next=0; } Node(T d) { data=d; next=0; } friend My_queue<T>; }; template<class T> class My_queue { private: Node<T> *tail; public: My_queue() { tail=new Node<T>(); tail->next=tail; } bool empty() { return (tail->next==tail); } void push(T d) { Node<T> *p=new Node<T>(d); p->next=tail->next; tail->next=p; tail=p; } T front() { if(empty()) { cout<<"queue is empty!"<<endl; exit(0); } Node<T> *p=tail->next; T data=p->next->data; return data; } void pop() { Node<T> *p=tail->next; Node<T> *q=p->next; p->next=q->next; if(q==tail) tail=p; delete q; } }; class CStree; class CSnode { private: char data; CSnode *firstchild; CSnode *nextsibling; friend CStree; }; class CStree { public: void Create_Tree(CSnode *&T) //创建树 { //按照从上到下,从左往右的顺序输入“双亲——孩子”的有序对,建立树的孩子兄弟存储结构 //输入时,以('#','#')为结束标志,根结点双亲为空,也是以'#'来表示 T=NULL; My_queue<CSnode *> q; char parent,child; cout<<"输入双亲,孩子有序对,以'#','#'作为输入结束标志"<<endl; for(cin>>parent>>child;child!='#';cin>>parent>>child) { CSnode *p=new CSnode; p->data=child; p->firstchild=p->nextsibling=NULL; //暂时现将它们置空 q.push(p); if(parent=='#') T=p; else { CSnode *r; CSnode *s=q.front(); while(s->data!=parent) { q.pop(); s=q.front(); } if(!s->firstchild) //链接第一个孩子结点 { s->firstchild=p; r=p; } else { r->nextsibling=p; r=p; } } }//end_for }//end_void void Get_Children(CSnode *T) //找结点孩子 { //在T的还在兄弟表示法中,求输入结点的孩子 cout<<"输入你要找的结点的值:"; char x; cin>>x; My_queue<CSnode *> q; if(!T) { cout<<"这是一棵空树!"<<endl; return ; } q.push(T); CSnode *r=NULL; if(T->data==x) r=T; else { do { CSnode *p=q.front(); q.pop(); if(p->firstchild && p->firstchild->data==x) { r=p->firstchild; break; } if(p->firstchild && p->firstchild->data!=x) q.push(p->firstchild); if(p->nextsibling && p->nextsibling->data==x) { r=p->nextsibling; break; } if(p->nextsibling && p->nextsibling->data!=x) q.push(p->nextsibling); }while(!q.empty()); } if(r==NULL) { cout<<"树T中没有结点"<<x<<endl; return; } else Print_children(r); } void Print_children(CSnode *p) { CSnode *q=p->firstchild; if(!q) { cout<<"结点"<<p->data<<"没有孩子"<<endl; return ; } cout<<"结点"<<p->data<<"的所有孩子是:"; while(q) { cout<<q->data<<" "; q=q->nextsibling; } cout<<endl; } void OutPath(CSnode *T,stack<char> &s) //求路径 { //输出树T中从根节点到所有叶子结点的路径,用栈暂存路径 while(T) { s.push(T->data); //将当前层访问的结点记入路径 if(!T->firstchild) Print_stack(s); //输出从栈底到栈顶的元素 else OutPath(T->firstchild,s); //继续遍历左子树 s.pop(); //将当前层访问的结点从路径中删除 T=T->nextsibling; //继续访问右子树 } } void Print_stack(stack<char> s) { char temp[100]; int i=0; while(!s.empty()) { temp[i]=s.top(); s.pop(); i++; } cout<<"从根节点到叶子结点的一条路径:"; for(int j=i-1;j>0;j--) cout<<temp[j]<<"->"; cout<<temp[0]<<endl; } void PreRoot_Traverse(CSnode *T) //先根遍历 { if(T) { cout<<T->data<<" "; PreRoot_Traverse(T->firstchild); PreRoot_Traverse(T->nextsibling); } } void PostRoot_Traverse(CSnode *T) //后根遍历 { if(T) { PostRoot_Traverse(T->firstchild); cout<<T->data<<" "; PostRoot_Traverse(T->nextsibling); } } void LevelOrder_Traverse(CSnode *T) //层次遍历 { My_queue<CSnode *> q; CSnode *t; q.push(T); do { t=q.front(); do { cout<<t->data<<" "; if(t->firstchild) q.push(t->firstchild); t=t->nextsibling; }while(t); q.pop(); }while(!q.empty()); } };
测试文件"main.cpp"

#include"tree.h" int main() { CStree tree; CSnode *T; tree.Create_Tree(T); tree.Get_Children(T); stack<char> s; tree.OutPath(T,s); cout<<"树的先根遍历为:"; tree.PreRoot_Traverse(T); cout<<endl; cout<<"树的后根遍历为:"; tree.PostRoot_Traverse(T); cout<<endl; cout<<"层次遍历树为:"; tree.LevelOrder_Traverse(T); cout<<endl; return 0; }
输入 # A A B A C A D C E C F C G C H E I E J G K # # 后生成的树和转换为二叉树后就是下面这种效果:

C++树(兄弟孩子结构实现)


输出结果为:输入双亲,孩子有序对,以'#','#'作为输入结束标志 # A A B A C A D C E C F C G C H E I E J G K # # 输入你要找的结点的值:C 结点C的所有孩子是:E F G H 从根节点到叶子结点的一条路径:A->B 从根节点到叶子结点的一条路径:A->C->E->I 从根节点到叶子结点的一条路径:A->C->E->J 从根节点到叶子结点的一条路径:A->C->F 从根节点到叶子结点的一条路径:A->C->G->K 从根节点到叶子结点的一条路径:A->C->H 从根节点到叶子结点的一条路径:A->D 树的先根遍历为:A B C E I J F G K H D 树的后根遍历为:B I J E F K G H C D A 层次遍历树为:A B C D E F G H I J K Press any key to continue