二叉树扩展之三叉树C++类模板的实现

简介


二叉树是递归定义的,这里的三叉树同样也是。

三叉树分为左子树,中子树,右子树。

三叉树的遍历顺序方式,我把它则分为四种:

(1)先序:根->左->中->右

(1)中1序:左->->中->右

(1)中2序:->>->右

(1)后序:左->中->右->

例如以下一棵三叉树:

将其以如下方式进行存储在test.txt文件中(便于程序先序读取创建一颗树,空用#表示)

ABC###D####E#F####G#H###IJ###K###M###


对于上面这棵树,从之后的编程实现对其遍历有如下结果。



编程实现


1.首先建立一个TTNode.h

#ifndef TTNODE_H
#define TTNODE_H
template <typename T>
struct TTNode{
	T data;
	TTNode<T> *lchild,*mchild,*rchild;
};
#endif
2.建立TTree.h

#ifndef TTREE_H
#define TTREE_H
enum Tags{
	Left,Mid,Right
};
enum style{
	Pre,In01,In02,Post
};
template <typename T>
struct StackElem{
	TTNode<T> *p;
	Tags flag;
};


template <typename T>
class TTree{

	protected:
		TTNode<T> *root;
	private:
		void DestroyTTree(TTNode<T>* &t){
			if(t!=NULL){
				DestroyTTree(t->lchild);
				DestroyTTree(t->mchild);
				DestroyTTree(t->rchild);
				delete t;
				t=NULL; 
			}
			
		} 
	public:
		TTree(){
			root=NULL;
		}
		~TTree(){
			DestroyTTree(root);
		}
		void CreateTTreeFromFile(ifstream &f){
			T e;
			InputFromFile(f,e);
			if(e==Nil) return ;
			root =new TTNode<T>;
			assert(root!=NULL);
			root->data=e;
			TTree<T> left,mid,right;
			left.CreateTTreeFromFile(f);
			mid.CreateTTreeFromFile(f);
			right.CreateTTreeFromFile(f);
			
			root->lchild=left.root;
			left.root=NULL;
			
			root->mchild=mid.root;
			mid.root=NULL;
			
			root->rchild=right.root;
			right.root=NULL;
		}
		bool TTreeEmpty()const{
			return root==NULL;
		}
		int TTreeDepth(TTNode<T>* t){
			int i,j,k,bri;
			if(t==NULL) return 0;
			else{
				i=TTreeDepth(t->rchild);
				k=TTreeDepth(t->mchild);
				j=TTreeDepth(t->lchild);
				bri=i>j?i:j;
				return bri>k?bri+1:k+1;
			}
		}
		TTNode<T>* Root(){
			return root;
		}
		T Value(TTNode<T>* p)const{
			return p->data;
		}
		void Assign(TTNode<T>* p,T value){
			p->data=value;
		}

		void PreOrderTraverse(void(*visit)(TTNode<T>*))const{
			stack<TTNode<T>*> s;
			TTNode<T> *t=root;
			s.push(NULL);
			while(t!=NULL){
				visit(t);
				if(t->rchild!=NULL)
					s.push(t->rchild);
				if(t->mchild!=NULL)
					s.push(t->mchild);
				if(t->lchild!=NULL)
					t=t->lchild;
				else{
					t=s.top();
					s.pop();
				}
			}
		}
		void In01OrderTraverse(void(*visit)(TTNode<T>*))const{
			StackElem<T> se;
			stack<StackElem<T> > s;
			TTNode<T> *t=root;
			if(t==NULL) return ;
			while(!s.empty()||t!=NULL){
				while(t!=NULL){
					se.p=t;
					se.flag=Left;
					s.push(se);
					t=t->lchild;
				}
				se=s.top();
				s.pop();
				t=se.p;
				if(se.flag==Left){
					visit(t);
					se.flag=Mid;
					s.push(se);
					t=t->mchild;
				}
				else{
					if(se.flag==Mid){
						se.flag=Right;
						s.push(se);
						t=t->rchild;
					}
					else{
						t=NULL;
					}
				}
			}
			
		}
		void In02OrderTraverse(void(*visit)(TTNode<T>*))const{
			StackElem<T> se;
			stack<StackElem<T> > s;
			TTNode<T> *t=root;
			if(t==NULL) return ;
			while(!s.empty()||t!=NULL){
				while(t!=NULL){
					se.p=t;
					se.flag=Left;
					s.push(se);
					t=t->lchild;
				}
				se=s.top();
				s.pop();
				t=se.p;
				if(se.flag==Left){
					
					se.flag=Mid;
					s.push(se);
					t=t->mchild;
				}
				else{
					if(se.flag==Mid){
						visit(t);
						se.flag=Right;
						s.push(se);
						t=t->rchild;
					}
					else{
						t=NULL;
					}
				}
			}
			
		}
		void PostOrderTraverse(void(*visit)(TTNode<T>*))const{
			StackElem<T> se;
			stack<StackElem<T> > s;
			TTNode<T> *t=root;
			if(t==NULL) return ;
			
			while(!s.empty()||t!=NULL){
				while(t!=NULL){
					se.p=t;
					se.flag=Left;
					s.push(se);
					t=t->lchild;
				}
				se=s.top();
				s.pop();
				t=se.p;
				if(se.flag==Left){
					se.flag=Mid;
					s.push(se);
					t=t->mchild;
				}
				else{
					if(se.flag==Mid){
						se.flag=Right;
						s.push(se);
						t=t->rchild;
					}
					else{
						visit(t);
						t=NULL;
					}
				}
			}
		}
		void LevelOrderTraverse(void(*visit)(TTNode<T>*))const{
			queue<TTNode<T>*> q;
			TTNode<T> *a,*t=root;
			if(t!=NULL){
				q.push(t);
				while(!q.empty()){
					a=q.front();
					q.pop();
					visit(a);
					if(a->lchild!=NULL)
						q.push(a->lchild);
					if(a->mchild!=NULL)
						q.push(a->mchild);
					if(a->rchild!=NULL)
						q.push(a->rchild);
				}
			}
			cout<<endl;
		}
		void OrderTraverse
		(TTNode<T>* t,style mode,void(*visit)(TTNode<T>*))const{
			if(t!=NULL){
				if(mode==Pre)
					visit(t);
					
				OrderTraverse(t->lchild,mode,visit);
				
				if(mode==In01)
					visit(t);
				OrderTraverse(t->mchild,mode,visit);
				
				if(mode==In02)
					visit(t);
				OrderTraverse(t->rchild,mode,visit);
				
				if(mode==Post)
					visit(t);
			}
		}
		

};
#endif





3.此外习惯将头文件组合在一起也弄个头文件C.h(多可少不行)

#ifndef C_H
#define C_H
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <stack>
#include <queue>
#include <algorithm>
#include <assert.h>
using namespace std;
#endif



4.最后是测试代码

#include "C.h"
#include "TTNode.h"
typedef char T;
void Visit(TTNode<T> *c){
	cout<<c->data<<" ";
}
void InputFromFile(ifstream &f,T &c){
	f>>c;
}
void Input(T &c){
	cin>>c;
}
T Nil='#';
#include "TTree.h"

int  main()
{
	
	TTree<T> t,c;
	TTNode<T> *p, *q;
	T e;
	ifstream fin("test.txt");
	t.CreateTTreeFromFile(fin);
	fin.close();
	cout<<"由文件test.txt创建三叉树t后,树t空否?"<<boolalpha<<t.TTreeEmpty();
	cout<<"。树t的深度="<<t.TTreeDepth(t.Root())<<endl;
	cout<<endl<<"层序遍历删除后的三叉树t:";
	t.LevelOrderTraverse(Visit);
	p=t.Root();
	cout<<endl<<"t的根结点="<<t.Value(p)<<"。给根结点赋新值,请输入新值:";
	Input(e);
	t.Assign(p, e);
	cout<<endl<<"层序遍历删除后的三叉树t:";
	t.LevelOrderTraverse(Visit);
	
	cout<<endl<<"先序遍历删除后的三叉树t:";
	t.PreOrderTraverse(Visit);
	cout<<endl<<"先序递归遍历删除后的三叉树t:";
	t.OrderTraverse(t.Root(), Pre, Visit);
	cout<<endl;
	cout<<endl<<"中1序遍历删除后的三叉树t:";
	t.In01OrderTraverse(Visit);
	cout<<endl<<"中1序递归遍历删除后的三叉树t:";
	t.OrderTraverse(t.Root(), In01, Visit);
	cout<<endl;
	cout<<endl<<"中2序遍历删除后的三叉树t:";
	t.In02OrderTraverse(Visit);
	cout<<endl<<"中2序递归遍历删除后的三叉树t:";
	t.OrderTraverse(t.Root(), In02, Visit);
	cout<<endl;
	cout<<endl<<"后序遍历删除后的三叉树t:";
	t.PostOrderTraverse(Visit);
	cout<<endl<<"后序递归遍历删除后的三叉树t:";
	t.OrderTraverse(t.Root(), Post, Visit);


	return 0;
}



  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值