• 二叉树的后序遍历--非递归实现


    leetcode中有这么一道题,非递归来实现二叉树的后序遍历。

    二叉树的后序遍历顺序为,root->left, root->right, root,因此需要保存根节点的状态。显然使用栈来模拟递归的过程,但是难点是怎么从root->right转换到root。

    方法1:
    对于节点p可以分情况讨论
    1. p如果是叶子节点,直接输出
    2. p如果有孩子,且孩子没有被访问过,则按照右孩子,左孩子的顺序依次入栈
    3. p如果有孩子,而且孩子都已经访问过,则访问p节点
     
    如何来表示出p的孩是否都已经访问过了呢?
    最暴力的方法就是对每个节点的状态进行保存,这么做显然是可以的,但是空间复杂度太大了。
    我们可以保存最后一个访问的节点last,如果满足 (p->right==NULL && last ==p->left) || last=p->right,那么显然p的孩子都访问过了,接下来可以访问p
    代码如下
    1 vector<int> postOrder(TreeNode *root)
     2 {
     3     vector<int> res;
     4     if(root == NULL) return res;
     5 
     6     TreeNode *p = root;
     7     stack<TreeNode *> sta;
     8     TreeNode *last = root;
     9     sta.push(p);
    10     while (!sta.empty())
    11     {
    12         p = sta.top();
    13         if( (p->left == NULL && p->right == NULL) || (p->right == NULL && last == p->left) || (last == p->right) )
    14         {
    15             res.push_back(p->val);
    16             last = p;
    17             sta.pop();
    18         }
    19         else 
    20         {
    21             if(p->right)
    22                 sta.push(p->right);
    23             if(p->left)
    24                 sta.push(p->left);
    25         }
    26 
    27     }
    28 
    29 
    30     return res;
    31 }
    方法2:
    其实我们希望栈中保存的从顶部依次是root->left, root->right, root,当符合上面提到的条件时,就进行出栈操作。有一种巧妙的方法可以做到,先上代码
    1 vector<int> postOrder(TreeNode *root)
     2 {
     3     vector<int> res;
     4     if(root == NULL) return res;
     5 
     6     TreeNode *p = root;
     7     stack<TreeNode *> sta;
     8     sta.push(p);
     9     sta.push(p);
    10     while(!sta.empty())
    11     {
    12         p = sta.top(); sta.pop();
    13         if(!sta.empty() && p==sta.top())
    14         {
    15             if(p->right) sta.push(p->right), sta.push(p->right);
    16             if(p->left) sta.push(p->left), sta.push(p->left);
    17         }
    18         else
    19             res.push_back(p->val);
    20     }
    21     
    22     return res;
    23 }
    对于每个节点,都压入两遍,在循环体中,每次弹出一个节点赋给p,如果p仍然等于栈的头结点,说明p的孩子们还没有被操作过,应该把它的孩子们加入栈中,否则,访问p。也就是说,第一次弹出,将p的孩子压入栈中,第二次弹出,访问p。
     
     
  • 相关阅读:
    Educational Codeforces Round 83 --- F. AND Segments
    Educational Codeforces Round 83 --- G. Autocompletion
    SEERC 2019 A.Max or Min
    2019-2020 ICPC Southwestern European Regional Programming Contest(Gym 102501)
    Educational Codeforces Round 78 --- F. Cards
    今天我学习了一门全新的语言
    codeforces 1323D 题解(数学)
    Educational Codeforces Round 80 (Div. 2) 题解 1288A 1288B 1288C 1288D 1288E
    Educational Codeforces Round 81 (Div. 2) 题解 1295A 1295B 1295C 1295D 1295E 1295F
    Codeforces Round #617 (Div. 3) 题解 1296C 1296D 1296E 1296F
  • 原文地址:https://www.cnblogs.com/rain-lei/p/3705680.html
Copyright © 2020-2023  润新知