一直知道个大概,没动手实现过,今天自己总结了下,以下图二叉树为例:
下面是创建二叉树,递归和非递归遍历的完整代码实现如下。
#include <iostream>
#include <stdio.h>
#include <stack>
using namespace std;
typedef struct BinNode{
char data;
bool flag; //后序非递归中的标记
struct BinNode *lchild,*rchild;
}BinNode,*BinTree;
//按先序创建树 ABD##E##CF####
void creatTree(BinTree &T)
{
char c;
cin>>c;
if(c=='#')
T=NULL;
else{
T=(BinTree)malloc(sizeof(BinNode));
T->data=c;
creatTree(T->lchild);
creatTree(T->rchild);
}
}
void visit(BinTree T)
{
if(T->data!='#')
cout<<T->data<<" ";
}
void preOrder(BinTree T) //前序递归
{
if(T)
{
visit(T);
preOrder(T->lchild);
preOrder(T->rchild);
}
}
void inOrder(BinTree T) //中序递归
{
if(T)
{
inOrder(T->lchild);
visit(T);
inOrder(T->rchild);
}
}
void postOrder(BinTree T) //后序递归
{
if(T)
{
postOrder(T->lchild);
postOrder(T->rchild);
visit(T);
}
}
void preOrderUnrec(BinTree T) //非递归前序遍历
{
BinTree p;
p=T;
stack<BinTree> s;
while(p || !s.empty())
{
while(p)
{
visit(p);
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
p=s.top();
s.pop();
p=p->rchild;
}
}
}
void inOrderUnrec(BinTree T) 非递归中序遍历
{
BinTree p;
p=T;
stack<BinTree> s;
while(p || !s.empty())
{
while(p)
{
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
p=s.top();
visit(p);
s.pop();
p=p->rchild;
}
}
}
void postOrderUnrec1(BinTree T) //非递归后序遍历 这个思路更好理解一些,下面有解释
{
BinTree p,cur;
BinTree pre=NULL;
p=T;
stack<BinTree> s;
s.push(p);
while(!s.empty())
{
cur=s.top();
if((cur->lchild==NULL && cur->rchild==NULL)||((pre!=NULL)&&(pre==cur->lchild || pre==cur->rchild)))
{
visit(cur);
s.pop();
pre=cur;
}
else
{
if(cur->rchild)
s.push(cur->rchild);
if(cur->lchild)
s.push(cur->lchild);
}
}
}
void postOrderUnrec2(BinTree T) //非递归后序遍历
{
BinTree p,cur;
p=T;
stack<BinTree> s;
p->flag=false;
s.push(p);
while(!s.empty())
{
cur=s.top();
if(cur->flag==true)
{
visit(cur);
s.pop();
}
else
{
if(cur->rchild){
cur->rchild->flag=false;
s.push(cur->rchild);
}
if(cur->lchild){
cur->lchild->flag=false; // 左右节点为NULL时,开始要出栈
s.push(cur->lchild);
}
cur->flag=true; //左右子节点入栈后,父节点标记为TRUE
}
}
}
int main()
{
BinTree T;
creatTree(T);
cout<<"preOrder :"<<endl;
preOrder(T); //前序
cout<<endl;
cout<<"preOrderUnrecursion :"<<endl;
preOrderUnrec(T);
cout<<endl;
cout<<"inOrder :"<<endl;
inOrder(T); //中序
cout<<endl;
cout<<"inOrderUnrecursion :"<<endl;
inOrderUnrec(T);
cout<<endl;
cout<<"postOrder :"<<endl;
postOrder(T); //后序
cout<<endl;
cout<<"postOrderUnrecursion :"<<endl;
postOrderUnrec1(T);
cout<<endl;
postOrderUnrec2(T);
cout<<endl;
return 0;
}
其中非递归的后序遍历第一种方法postOrderUnrec1(BinTree T) 的思想:要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。该方法摘自http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html