树的后序遍历

101 阅读3分钟

递归算法

指针到达一个结点时,判断该结点是否为空,为空则停止遍历,不为空则将左子作为新的结点参数进行判断,打印左子。左子判断完成后,将右子作为结点参数传入判断,打印右子。左右子判断完成后打印根结点。

非递归算法

首先建立两个栈,然后定义两个常量。第一个为status,取值为0,1,2.0代表左右子都没有去过,1代表去过左子,2,代表左右子都去过,默认为0。第二个常量为flag,取值为0或者1,0代表进左栈,1代表进右栈。初始时指针指向根结点,判断根结点是否有左子,有左子则,将根结点入左栈,status置0,flag置0,若没有左子则判断结点有没有右子,有右子就把结点入右栈,status置0,flag置1,若左右子都没有,则打印该结点,并将指针指向空,此时判断flag,若flag为0,则从左栈出栈一个元素作为当前结点,重新判断;若flag为1则从右栈出栈一个元素作为当前结点,重新判断左右子是否去过,若status为1,则判断该结点有没有右子,若有右子,则将该结点入右栈,status置1,flag置1,若没有右子,则打印当前结点,并将指针置空,然后再次判断flag。若当前结点status为2,且栈为空,则遍历结束。若指针指向了左子,则将左子作为当前结点,判断其左右子情况,按上述方法处理,直至遍历结束。

程序

递归算法

void postOrder(Node *root)
{
    if(0 != root)
    {
        postOrder(root->lChild);
        postOrder(root->rChild);
        printf("%d",root->data);
    }
}

非递归算法

void postOrder(Node *root) //后序遍历 
{ 
//声明左右栈 如果当前结点有左子则进左栈 若没左子但是有右子则进右栈 
Stack msl; //声明左栈
 MyStack msr; //声明右栈
 Node curr = *root; //结点指向树的根结点 
int flag=0; //设置一个标志 0:进左栈 1:进右栈
//设置一个标志 0:没去过左右子树 1:去过左子树 2:去过右子树(两子树都去过) 
int status=0;
 init(&msl); //初始化左栈 
init(&msr); //初始化右栈 
while(curr.data!=0||isEmpty(msl)!=0||isEmpty1(msr)!=0) //当前结点不为空且左右栈都不为空 
{ 
if(status==0&&curr.lChild!=NULL) //没去过左右子树 且右子不为空
 { 
push(&msl,curr); //当前子进左栈
 curr = *curr.lChild; //当前子指向左子
 flag=0; //flag置0 
}
else if(status!=2&&curr.rChild!=NULL) //没去过右子树且右子不为空
 { 
push1(&msr,curr); //当前子进右栈
 curr=*curr.rChild //当前子指向右子 
flag=1; //flag置1
 status=0; //status 置0
 }
else 
{
 printf("%d ",curr.data); //打印当前结点内容
//指向右栈弹出的元素 //status标志置为2 //如果右栈为空 //指向右栈弹出的元素 //指向左栈弹出的元素 //status标志置为1 //若当前结点为空,结束循环
 }
 }