1、第一种方法
非递归后序遍历二叉树比非递归先序、中序遍历二叉树稍微复杂一点。因为后序遍历的顺序为:左子树、右子树、根,因此除了要利用栈来保存需要回溯的元素之外还要设置一个能表示何时能访问根节点的标志。栈中要保存的数据是一个结构体;包含指向二叉树根节点的指针和访问标志。
#include<iostream>
#define ERROR -1;
#define OK 1;
typedef char VertexType;
typedef enum{L,R} TagType; //设置一个标志,当栈顶元素的tag为R时说明二叉树的右子树已经访问完,可以访问根节点
typedef struct BinNode{
VertexType data;
struct BinNode *lchild,*rchild;
}BinNode,*bin_tree,*SElemType;
typedef struct StackNode{ //栈中的节点设置成存放指向二叉树结点的指针以及tag标志的结构
SElemType data;
TagType tag;
}StackNode;
typedef struct{
StackNode *base,*top;
}SqStack;
using namespace std;
int InitStack(SqStack &S){
S.base=(StackNode *)malloc(sizeof(StackNode));
if(!S.base)
return ERROR;
S.top=S.base;
return OK;
}
int StackEmpty(SqStack S){
return (S.base==S.top)?1:0;
}
void Push(SqStack &S,StackNode pnode){
*S.top++=pnode;
}
int Pop(SqStack &S,StackNode &pnode){
if(S.base==S.top)
return ERROR;
pnode=*--S.top;
return OK;
}
StackNode GetTop(SqStack S){
StackNode pnode;
if(S.base==S.top)
exit(0);
pnode=*--S.top;
return pnode;
}
BinNode *CreateTree(bin_tree &T){
VertexType ch;
cin>>ch;
if(!cin.eof()){
if(ch=='#')
T=NULL;
else{
T=(BinNode *)malloc(sizeof(BinNode));
if(!T)
exit(0);
T->data=ch;
T->lchild=CreateTree(T->lchild);
T->rchild=CreateTree(T->rchild);
}
}
return T;
}
void PostTraverse(bin_tree T){
StackNode pnode;
SqStack S;
BinNode *p;
p=T;
InitStack(S);
do{
while(p){ //遍历左子树,递归的将某一个结点的左孩子都入栈
pnode.data=p;
pnode.tag=L; //初始化访问标志为L
Push(S,pnode);
p=p->lchild;
}
pnode=GetTop(S);
while(!StackEmpty(S)&&pnode.tag==R){ //如果栈顶元素的tag标志位R,说明右子树已经访问完,可以访问根节点
Pop(S,pnode);
p=pnode.data;
cout<<p->data<<" ";
pnode=GetTop(S);
}
if(!StackEmpty(S)){ //此条件满足时说明二叉树的左子树已经遍历完,要开始遍历右子树
Pop(S,pnode);
pnode.tag=R;
p=pnode.data;
Push(S,pnode);
p=p->rchild;
}
}while(!StackEmpty(S));
}
void main(){
bin_tree T;
cout<<"请输入二叉树的节点值:";
CreateTree(T);
cout<<"二叉树的非递归后序遍历结果是:";
PostTraverse(T);
cout<<endl;
}
2、第二种方法
上述解决方法是在栈中保存指向指向二叉树结点的指针和访问标志,以下的解决方法是把访问标志保存在二叉树的节点之中。两种解决方法的思想是一样的,只不过栈中节点和二叉树节点所用的数据结构不一样而已。
#include<iostream> #define ERROR -1; #define OK 1; typedef char VertexType; typedef struct BinNode{ VertexType data; struct BinNode *lchild,*rchild; bool tag; //设置一个标志,当栈顶元素的tag为R时说明二叉树的右子树已经访问完,可以访问根节点 }BinNode,*bin_tree,*SElemType; typedef struct{ SElemType *base,*top; }SqStack; using namespace std; int InitStack(SqStack &S){ S.base=(SElemType *)malloc(sizeof(SElemType)); if(!S.base) return ERROR; S.top=S.base; return OK; } int StackEmpty(SqStack S){ return (S.base==S.top)?1:0; } void Push(SqStack &S,SElemType pnode){ *S.top++=pnode; } int Pop(SqStack &S,SElemType pnode){ if(S.base==S.top) return ERROR; pnode=*--S.top; return OK; } SElemType GetTop(SqStack S){ SElemType pnode; if(S.base==S.top) exit(0); pnode=*--S.top; return pnode; } BinNode *CreateTree(bin_tree &T){ VertexType ch; cin>>ch; if(!cin.eof()){ if(ch=='#') T=NULL; else{ T=(BinNode *)malloc(sizeof(BinNode)); if(!T) exit(0); T->data=ch; T->tag=0; T->lchild=CreateTree(T->lchild); T->rchild=CreateTree(T->rchild); } } return T; } void PostTraverse(bin_tree T){ SqStack S; SElemType p; p=T; InitStack(S); do{ while(p){ //遍历左子树,递归的将某一个结点的左孩子都入栈 Push(S,p); p=p->lchild; } p=GetTop(S); while(!StackEmpty(S)&&p->tag==1){ //如果栈顶元素的tag标志位1,说明右子树已经访问完,可以访问根节点 Pop(S,p); cout<<p->data<<" "; p=GetTop(S); } if(!StackEmpty(S)){ //此条件满足时说明二叉树的左子树已经遍历完,要开始遍历右子树 Pop(S,p); p->tag=1; Push(S,p); p=p->rchild; } }while(!StackEmpty(S)); } void main(){ bin_tree T; cout<<"请输入二叉树的节点值:"; CreateTree(T); cout<<"二叉树的非递归后序遍历结果是:"; PostTraverse(T); cout<<endl; }