原文链接:http://blog.csdn.net/zhouzixin053/article/details/24129129
非递归后序遍历算法思想
后序遍历的非递归算法中节点的进栈次数是两个,即每个节点都要进栈两次,第二次退栈的时候才访问节点。
第一次进栈时,在遍历左子树的过程中将”根”节点进栈,待左子树访问完后,回溯的节点退栈,即退出这个”根”节点,但不能立即访问,只能借助于这个”根”去找该”根”的右子树,并遍历这棵右子树,直到该右子树全部遍历以后,再退出该”根”节点,并访问它。
所以为了记录节点是第一次还是第二次进栈,就在堆栈数据元素的结构中增加一个数据项:进栈标志。
(1)当节点非空时或堆栈非空时,执行(2),否则结束算法;
(2)当节点指针非空时,节点的进栈标志设为false,节点指针及进栈标志进栈,然后将节点指向进栈节点的左子树的根,重复(2),知道指针为空(最后一个进栈的是最左子树),节点指针为空时,转(3);
(3)堆栈非空时,从堆栈中退出一个节点的指针。如果退出的节点的进栈标志为true,说明该节点是第二次退栈,访问该接点,并将指针强制设为空,准备下一次退栈,并转(3),如果进栈标志为false,说明该节点是第一次退栈,将进栈标志设为true,然后将该节点指针及进栈标志进栈,再将指针指向它的右子树,转(1)。
代码实现
#include<stdio.h>
#include<stdlib.h>
typedef char EType;
struct BinaryTreeNode
{
EType data;
struct BinaryTreeNode *LChild;
struct BinaryTreeNode *RChild;
};
typedef BinaryTreeNode BinaryTree;
typedef struct SType
{
BinaryTreeNode *ptr;
bool status;//进栈标志
}SType;
typedef struct Stack
{
SType *element;
int top;
int MaxSize;
}Stack;
void CreatStack(Stack &S,int MaxStackSize);
bool IsEmpty(Stack &S);
bool IsFull(Stack &S);
bool GetTop(Stack &S,SType &result);
bool Pop(Stack &S,SType &result);
bool Push(Stack &S,SType &x);
void CreatBiTree(BinaryTreeNode **BT);
void PostOrderNoRecursive(BinaryTreeNode *BT);
int main()
{
BinaryTreeNode *BT = NULL;
CreatBiTree(&BT);
printf("后序遍历二叉树非递归算法输出为:");
PostOrderNoRecursive(BT);
printf("\n");
return 0;
}
void CreatStack(Stack &S,int MaxStackSize)
{
S.MaxSize = MaxStackSize;
S.element = new SType[S.MaxSize];
S.top = -1;
}
bool IsEmpty(Stack &S)
{
if(S.top == -1)
return true;
return false;
}
bool IsFull(Stack &S)
{
if(S.top >= S.MaxSize-1)
return true;
return false;
}
bool GetTop(Stack &S,SType &result)
{
if(IsEmpty(S))
return false;
result = S.element[S.top];
return true;
}
bool Pop(Stack &S,SType &result)
{
if(IsEmpty(S))
return false;
result = S.element[S.top];
S.top--;
return true;
}
bool Push(Stack &S,SType &x)
{
if(IsFull(S))
return false;
S.top++;
S.element[S.top] = x;
return true;
}
void CreatBiTree(BinaryTreeNode **BT)
{
EType tem;
scanf("%c",&tem);
if(' ' == tem)
{
*BT = NULL;
}
else
{
*BT = new BinaryTreeNode;
(*BT)->data = tem;
CreatBiTree(&(*BT)->LChild);
CreatBiTree(&(*BT)->RChild);
}
}
void PostOrderNoRecursive(BinaryTreeNode *BT)
{
Stack S;
SType temp;
BinaryTreeNode *p = BT;
int MaxStackSize = 50;
CreatStack(S,MaxStackSize);
while(p || !IsEmpty(S))
{
if(p)//找最左子树
{
temp.status = false;//设置该节点是第一次进栈
temp.ptr = p;
Push(S,temp);
p = p->LChild;
}
else
{
if(!IsEmpty(S)) /*该判断多余?*/
{
Pop(S,temp);
p = temp.ptr;
if(temp.status)//若该节点是第二次退栈,就访问,并设置p=0继续退栈
{
printf("%c\t",p->data);
p = NULL;
}
else
{
temp.status = true;//设置该节点是第二次进栈
Push(S,temp);
p = p->RChild;//遍历该节点的右子树
}
}
}
}
}