#include <iostream>
#include <stack>
#include <queue>
using namespace std;
typedef struct Node{
int data;
Node *lchild;
Node *rchild;
Node()
{
data = 0;
lchild = NULL;
rchild = NULL;
}
}BiTree,*BTree;
//前序建立二叉树
void CreatBiTree(BTree& T,char data)
{
cout<<"父节点:"<<data<<endl;
char c;
cin>>c;
if(c =='#')
{
T=NULL;
}else
{
T = new BiTree;
T->data = c;
CreatBiTree(T->lchild,T->data);
CreatBiTree(T->rchild,T->data);
}
return;
}
/* 树形
#############
1
2 5
3 4 6 7
#############
前序: 1 2 3 4 5 6 7
中序: 3 2 4 1 6 5 7
后序: 3 4 2 6 7 5 1
*/
//建立二叉树
void CreatTree(BTree& T)
{
T = new BiTree;
T->data = 1;
//左子树
BTree T1 = new BiTree;
T1->data = 2 ;
T->lchild = T1;
BTree T11 = new BiTree;
T11->data = 3;
T1->lchild = T11;
BTree T12 = new BiTree;
T12->data = 4;
T1->rchild = T12;
//右子树
BTree T2 = new BiTree;
T2->data = 5 ;
T->rchild = T2;
BTree T21 = new BiTree;
T21->data = 6;
T2->lchild = T21;
BTree T22 = new BiTree;
T22->data = 7;
T2->rchild = T22;
return;
}
//前序递归遍历
void PreOrderBiTree(BiTree* T)
{
if(T)
{
cout<<T->data <<" ";;
PreOrderBiTree(T->lchild);
PreOrderBiTree(T->rchild);
}
}
//非递归前序《1》
/*****************
先将右子树放入栈底,依次放入左子树元素
按照左节点在上右节点在下原则
遇到叶节点 即开始弹出栈内元素
******************/
void PreOredrTree1(BiTree *T)
{
BiTree* p = T;
stack<BiTree*> S; //栈空间
S.push(p);
while(!S.empty())
{
p = S.top();
S.pop();
cout<<p->data<<" ";
if(p->rchild) //右子树节点入栈底
S.push(p->rchild);
if(p->lchild) //左子树节点入栈
S.push(p->lchild);
}
return ;
}
//非递归前序《2》王道写法
/*****************
将所有的左子树的左子节点入栈 同时 输出值
栈顶的左子节点出栈,访问其右节点,
若有 输出其值 入栈 同时继续将该节点的左子树左节点入栈
若无,继续弹出下一个栈元素,访问其右节点
******************/
void PreOredrTree(BiTree *T)
{
BiTree* p = T;
stack<BiTree*> S; //栈空间
while(!S.empty()||p!=NULL)
{
if(p)
{
cout<< p->data <<" ";
S.push(p);
p = p->lchild;
}
else{
p = S.top();
S.pop();
p = p->rchild;
}
}
return ;
}
//层序遍历
void LeveOredrTree(BiTree *T)
{
BiTree* p = T;
queue<BiTree*> S;
S.push(p);
while(!S.empty())
{
p = S.front();
S.pop();
cout<<p->data<<endl;
if(p->lchild)
S.push(p->lchild);
if(p->rchild)
S.push(p->rchild);
}
return ;
}
//中序递归遍历
void InOrderBiTree(BiTree* T)
{
if(T)
{
InOrderBiTree(T->lchild);
cout<<T->data <<" ";
InOrderBiTree(T->rchild);
}
}
//非递归中序《1》王道写法 左根右
/*****************
将所有的左子树的左子节点入栈
栈顶的左子节点出栈 <<<<输出其值>>>> 访问其右节点, //区别在于此!!
若有 入栈 同时继续将该节点的左子树左节点入栈
若无,继续弹出下一个栈元素,再访问其右节点
******************/
void InOrderTree(BiTree *T)
{
BiTree* p = T;
stack<BiTree*> S; //栈空间
while(!S.empty()||p!=NULL)
{
if(p)
{
S.push(p);
p = p->lchild;
}
else{
p = S.top();
cout<< p->data <<" ";
S.pop();
p = p->rchild;
}
}
return ;
}
//后序递归遍历
void PostOrderBiTree(BiTree* T)
{
if(T)
{
PostOrderBiTree(T->lchild);
PostOrderBiTree(T->rchild);
cout<<T->data <<" ";
}
}
//非递归后序《1》王道写法 左右根
/*****************
将所有的左子树的左子节点入栈
栈顶最后一个左节点出栈,判断其是否还有右子节点,
若有,右子节点入栈 同时继续将该右子节点的左子树的所有左节点入栈
若无,弹出该节点,输出其值,同时记录该节点?
用做此节点的父节点出栈时的对比,避免此 节点(父节点的右子节点) 重复入栈
******************/
void PostOrderTree(BiTree *T)
{
BiTree* p = T;
BiTree* k = NULL;//用于标记改节点是否已经访问其右节点
stack<BiTree*> S; //栈空间
while(!S.empty()||p!=NULL)
{
if(p)
{
S.push(p);
p = p->lchild;
}
else{
p = S.top(); //先不出栈
if(p->rchild != NULL && k != p->rchild)//判断p出栈时p的右子树有无入栈(没有:p不能出栈,继续将右子树入栈。有:p可以出栈 )
{
p = p->rchild; //继续将右节点的所有子树左节点入栈
}
else{
cout<< p->data<<" ";//输出节点值
S.pop(); //节点出栈
k = p;
p = NULL;
}
}
}
return ;
}
int main()
{
BiTree* T;
CreatTree(T);
cout<<"创建二叉树完成!"<<endl;
cout<<"前序遍历二叉树: 1 2 3 4 5 6 7 "<<endl;
PreOrderBiTree(T);
cout<<endl<<"非递归前序遍历二叉树!"<<endl;
PreOredrTree(T);
cout<<endl<<"中序遍历二叉树: 3 2 4 1 6 5 7 "<<endl;
InOrderBiTree(T);
cout<<endl<<"非递归中序遍历二叉树!"<<endl;
InOrderTree(T);
cout<<endl<<"后序遍历二叉树: 3 4 2 6 7 5 1"<<endl;
PostOrderBiTree(T);
cout<<endl<<"非递归后序遍历二叉树!"<<endl;
PostOrderTree(T);
cout<<endl;
system("pause") ;
return 0;
}