Binary Tree Postorder Traversal(各种非递归实现,完美利用栈结构模拟)

本文详细介绍了二叉树的后序、中序和前序非递归遍历算法,通过使用栈和标记的方式实现了遍历过程,解决了递归带来的堆栈溢出问题。其中后序遍历是最具挑战性的。

1.后序遍历的非递归实现。(左右根)

难点:后序遍历的非递归实现是三种遍历方式中最难的一种。因为在后序遍历中,要保证左孩子和右孩子都已被访问并且左孩子在右孩子前访问才能访问根结点,这就为流程的控制带来了难题。下面介绍两种思路。

思路:有个关键的就是unUsed这个标识符。

当unUsed=1时,表示该节点未遍历过,即以该节点为根节点的左右孩子不曾遍历。

当unUsed=0时,表示该节点的左右孩子都已经被访问过。

由于入栈的顺序和出栈的顺序相反,所以若unUsed=1,则左根右节点依次入栈,且根节点的unUsed置为0.

代码:

class Solution {
public:
    vector<int> postorderTraversal(TreeNode *root) {
        vector<int> res;
        if(root==NULL) return res;
        stack<pair<TreeNode*,int>> s;
        int unUsed;
        s.push(make_pair(root,1));

        while (!s.empty())
        {
            root=s.top().first;
            unUsed=s.top().second;
            s.pop();
            if(unUsed){
                s.push(make_pair(root,0));
                if(root->right)
                    s.push(make_pair(root->right,1));
                if(root->left)
                    s.push(make_pair(root->left,1));
            }else{
                //cout<<root->val<<" ";
                res.push_back(root->val);
            }
        }
    }
};

 

2.拓展,中序遍历的非递归实现(左根右)。和以上思路类似,由于也不能先访问根节点,但是我们是从根节点出发,所以还是使用unUsed来标志根节点的状态。

往栈中放节点的顺序倒过来即:左根右,且该根节点的左右孩子访问完毕。

代码:

void inOrder(Node *p)
{
     if(!p)
         return;
     stack< pair<Node*,int> > s;
     Node *t;
     int unUsed;
     s.push(make_pair(p,1));
     while(!s.empty())
     {
         t=s.top().first;
         unUsed = s.top().second;
         s.pop();
         if(unUsed)
         {
               if(t->right)
                     s.push( make_pair(t->right,1) );
              s.push( make_pair(t,0) );
              if(t->left)
                     s.push( make_pair(t->left,1));
          }
          else printf("%d\n",t->data);
       }
}

 

3.前序非递归,直接先根节点。

void preOrder(Node *p) //非递归
{
   if(!p) return;
   stack<Node*> s;
   Node *t;
   s.push(p);
   while(!s.empty())
   {
       t=s.top();
       printf("%d\n",t->data);
       s.pop();
       if(t->right) s.push(t->right);
       if(t->left) s.push(t->left);
    }
 }

 

转载于:https://www.cnblogs.com/fightformylife/p/4089557.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值