一种易理解的二叉树后序遍历非递归写法

       网上流传了很多二叉树的非递归写法,对于前序和中序,比较容易理解,对于后序,很多讲的不是非常明白。参考了很多资料,本人自己写了

和传统前序,中序非递归方法类似的写法。读本文前,最好先看过文末的参考文献。


首先定义基本的二叉树

struct TreeNode{
    char  c;
    TreeNode *left;
    TreeNode *right;
};

typedef struct TreeNode * BinTree;
typedef struct TreeNode  _TreeNode;


1、前序和中序。

非递归思路如下,

a. 遇到一个节点,访问它,然后把它压栈,并去遍历它的左子树;

b. 当左子树遍历结束后,从栈顶弹出该节点并将其指向右儿子,继续a步骤;

c. 当所有节点访问完即最后访问的树节点为空且栈空时,停止。

void PreOrder(BinTree T){
    stack<BinTree> s;
    BinTree P = T;
    while(P || !s.empty()){
        while(P){
            cout<<P->c;
            s.push(P);
            P = P->left;
        }
        if(!s.empty()){
            P = s.top();
            s.pop();
            P = P->right;
        }
    }
}


2、后序

其实,二叉树遍历的非递归写法,本质上仍然是根据递归写法推导出来的。按照左右根的顺序,我们自己模拟一下递归的过程,不难得出下面的过程。算法思路,(1)P=P->left,一直调用左子树,直到最底下一层调用左子树为空。此时,令P=stack.top(),即循环中最后一个不为空的左子树。根据P->right的情况,分为下面两种跳转:(2)P->right不为空,令P=P->right,跳到(1)。看到这里,是不是跟传统的前序和后序非递归思路很像?(3)P->right为空。由于(2)(3)是(1)的两种情况的不同跳转,到了这里就说明P的左右子树均为空。因此,访问P。接下来,我们需要一个prev前驱。令prev=P,然后将P出栈,重新将P只向栈顶。若P的右儿子是prev,则说明,右儿子访问完了,访问P。这里我们需要一个循环,一只判断是否需要访问。若P的左儿子是prev,则我们需要专向它的右儿子,重新从(1)开始下一轮循环。下面贴出代码

void PostOrder2(BinTree T){
    stack<BinTree> s;
    BinTree P = T,prev;
    while(P || !s.empty()){
        while(P){       //循环访问左子树,直到为空
            s.push(P);
            P = P->left;
        }
        if(!s.empty()){
            P = s.top();  //P重新只向栈中最后一个非空元素。
            if(P->right){    //右儿子非空,转向右儿子。重新开始下一轮处理。类似前序的的非递归处理。
                P = P->right;
                continue;
            }

            //若P右儿子为空,或者右儿子前面已经访问了,继续访问P
            while(P->right == NULL || P->right == prev){
                cout<<P->c<<' ';
                prev = P;
                s.pop();
                if (s.empty())
			return;
                P = s.top();
            }
            //若P的左儿子前面已经访问了,转向右儿子。重新开始下一轮处理。类似前序的的非递归处理。
            if(P->left == prev)
                P = P->right;
        }
    }
}

完整测试代码分享:链接:http://pan.baidu.com/s/1migbYWS 密码:h7x4


参考资料:
1、严蔚敏,《数据结构》,清华大学出版社
2、llhthinker。 《二叉树的遍历:先序中序后序遍历的递归与非递归实现及层序遍历》。http://www.cnblogs.com/llhthinker/p/4747962.html。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值