#include<iostream>
#include<stack>
#include<queue>
using namespace std;
template <class T>
class BinTreeNode
{
private:
T data;
BinTreeNode<T> *left;
BinTreeNode<T> *right;
public:
BinTreeNode(const T& dt=NULL,BinTreeNode<T> *l=NULL,BinTreeNode<T> *r=NULL):data(dt),left(l),right(r) {};
BinTreeNode<T> * GetLeft(void)const
{
return left;
}
BinTreeNode<T> * GetRight(void)const
{
return right;
}
T GetData()const
{
return data;
}
void SetLeft(BinTreeNode<T>* l)
{
left=l; ///此处赋值,非构造函数
}
void SetRight(BinTreeNode<T>* r)
{
right=r;
}
void SetData(const T& dt)
{
data=dt;
}
};
template <class T>
class BinTree
{
private:
BinTreeNode<T> *root;
T stop;///构造二叉树时的输入结束符
int index=-1;///使用数组构造二叉树时用于遍历数组元素
public:
BinTree(BinTreeNode<T>* rt=NULL):root(rt) {};
virtual ~BinTree()
{
Del(root);
}
///二叉树的创建,通过io输入创建与通过数组创建,均为先序
BinTreeNode<T>* Create();
BinTreeNode<T>* CreateFromArr(T*a);
///节点删除
void DelSubtree(BinTreeNode<T>* t);///从树中删除结点t及其左右子树
void Del(BinTreeNode<T>* t);///删除结点t及其左右子树
///递归前中后序遍历
void PreOrder(BinTreeNode<T>* t)const;
void InOrder(BinTreeNode<T>* t)const;
void PostOrder(BinTreeNode<T>* t)const;
///非递归前中后续遍历
void NorecPreOrder()const;
void NorecInOrder()const;
void NorecPostOrder()const;
///其他操作
BinTreeNode<T>* GetRoot() const
{
return root;
}
void SetRoot(BinTreeNode<T>* t)
{
root=t;
}
T GetStop()const
{
return stop;
}
void SetStop(const T& s)
{
stop=s;
}
bool IsEmpty()const
{
return root==NULL;
}
};
///从数组创建一个二叉树
template <class T>
BinTreeNode<T>* BinTree<T>::CreateFromArr(T* a)
{
BinTreeNode<T>* root = NULL;
//cout<<index<<">>>"<<a[index]<<endl;
index++;
if (a[index] != stop)
{
root = new BinTreeNode<T>(a[index]);
root->SetLeft(CreateFromArr(a));
root->SetRight(CreateFromArr(a));
}
return root;
}
///由io流创建一个二叉树
template <class T>
BinTreeNode<T>* BinTree<T>::Create()
{
BinTreeNode<T>* t,*t1,*t2;
T item;
cin>>item;
///递归出口
if(item==stop)
{
t=NULL;
return t;
}
///先续构造二叉树
else
{
t=new BinTreeNode<T>(item,NULL,NULL);
t1=Create();
t->SetLeft(t1);
t2=Create();
t->SetRight(t2);
return t;
}
}
///递归遍历
template <class T>
void BinTree<T>::Del(BinTreeNode<T> *t)
{
if(t!=NULL)
{
Del(t->GetLeft());
Del(t->GetRight());
delete t;
}
}
template <class T>
void BinTree<T>::PreOrder(BinTreeNode<T>* t)const
{
if(t!=NULL)
{
cout<<t->GetData()<<"->";
PreOrder(t->GetLeft());
PreOrder(t->GetRight());
}
}
template <class T>
void BinTree<T>::PostOrder(BinTreeNode<T>* t)const
{
if(t!=NULL)
{
PostOrder(t->GetLeft());
PostOrder(t->GetRight());
cout<<t->GetData()<<"->";
}
}
template <class T>
void BinTree<T>::InOrder(BinTreeNode<T>* t)const
{
if(t!=NULL)
{
InOrder(t->GetLeft());
cout<<t->GetData()<<"->";
InOrder(t->GetRight());
}
}
///非递归遍历
template <class T>
void BinTree<T>::NorecPreOrder()const
{
BinTreeNode<T> *p=root;
stack<BinTreeNode<T>*> s;
while(p||!s.empty())
{
if(p)
{
cout<<p->GetData()<<"->";
s.push(p);
p=p->GetLeft();
}
else
{
p=s.top();
s.pop();
p=p->GetRight();
}
}
return;
}
template <class T>
void BinTree<T>::NorecInOrder() const
{
stack<BinTreeNode<T>*> s;
BinTreeNode<T> *p=root;
while(p||!s.empty())
{
if(p)
{
s.push(p);
p=p->GetLeft();
}
else
{
p=s.top();
cout<<p->GetData()<<"->";
s.pop();
p=p->GetRight();
}
}
return;
}
///后序遍历:这是三种遍历方法中最为复杂的一种,
///因为它的根节点是最后访问的,在我们出栈遇到该节点时,
///我们并不知道此时它的右子树是否被访问过,
///所以我们需要额外借助一个节点变量用来判断右子树的访问真值。
template <class T>
void BinTree<T>::NorecPostOrder() const
{
BinTreeNode<T> *p=root,*temp=NULL;
stack<BinTreeNode<T> *>s;
while(p||!s.empty())///只有p为空切栈为空时,退出循环
{
if(p)
{
s.push(p);
p=p->GetLeft();
}
else
{
p=s.top();
///p的右子树非空且p的右子树不为temp(标志节点)
///此时p的右子树还未遍历过
if(p->GetRight()&&p->GetRight()!=temp)
{
p=p->GetRight();
s.push(p);
p=p->GetLeft();
}
///当右子树已经遍历过时或右子树为空,此时应该进行节点的输出
else
{
s.pop();
cout<<p->GetData()<<"->";
temp=p;
p=NULL;
}
}
}
return;
}
int main()
{
char arr[]= {'A','B','D','#','G','#','#','E','#','#','C','F','#','#','#'};
/*
A Pre :ABDGECF
/ In :DGBEAFC
B C Post:GDEBFCA
/ /
D E F #
/ / /
# G # # # #
/
# #
*/
BinTree<char> *tree=new BinTree<char>;
tree->SetStop('#');
cout<<"CreatTheTree"<<endl;
///由io流创建
///BinTreeNode<char> *rt=tree->Create();
///由数组创建
BinTreeNode<char> *rt=tree->CreateFromArr(arr);
tree->SetRoot(rt);
cout<<endl;
cout<<"PreOrder>>>";
tree->PreOrder(tree->GetRoot());
cout<<endl;
cout<<"InOrder>>>";
tree->InOrder(tree->GetRoot());
cout<<endl;
cout<<"PostOrder>>>";
tree->PostOrder(tree->GetRoot());
cout<<endl;
cout<<"NorecPreOrder>>>";
tree->NorecPreOrder();
cout<<endl;
cout<<"NorecInOrder>>>";
tree->NorecInOrder();
cout<<endl;
cout<<"NorecPostOrder>>>";
tree->NorecPostOrder();
cout<<endl;
}