zoukankan      html  css  js  c++  java
  • Leetcode#145 Binary Tree Postorder Traversal

    原题地址

    递归写法谁都会,看看非递归写法。

    对于二叉树的前序和中序遍历的非递归写法都很简单,只需要一个最普通的栈即可实现,唯独后续遍历有点麻烦,如果不借助额外变量没法记住究竟遍历了几个儿子。所以,最直接的想法就是在栈中记录到底遍历了几个儿子。

    代码:

     1 vector<int> postorderTraversal(TreeNode *root) {
     2         vector<int> path;
     3         stack<pair<TreeNode *, int> > st;
     4         
     5         st.push(pair<TreeNode *, int>(root, 0));
     6         while (!st.empty()) {
     7             pair<TreeNode *, int> top = st.top();
     8             st.pop();
     9             
    10             if (!top.first)
    11                 continue;
    12             
    13             if (top.second == 0) {
    14                 top.second = 1;
    15                 st.push(top);
    16                 st.push(pair<TreeNode *, int>(top.first->left, 0));
    17             }
    18             else if (top.second == 1) {
    19                 top.second = 2;
    20                 st.push(top);
    21                 st.push(pair<TreeNode *, int>(top.first->right, 0));
    22             }
    23             else if (top.second == 2) {
    24                 path.push_back(top.first->val);
    25             }
    26         }
    27         
    28         return path;
    29     }

    另外还有一种技巧性比较强的写法,只使用普通的栈就可以做到。利用到了一个后续遍历的特点,即:

    后续遍历序列中,父节点前面一定紧挨着他的儿子节点(如果有的话)

    所以,额外保存一个prev变量代表前一个遍历的节点,就可以识别出上面的情况。如果prev节点是当前节点的儿子节点(或者当前节点没有儿子),说明当前节点的儿子节点都遍历过了,可以遍历父节点了。

    如何更新维护prev呢?当一个节点输出后,将prev置为这个节点,这是因为如果prev是后续遍历序列中的前一个节点,那么这个prev节点必须是已经被输出的节点。

    代码如下:

     1     vector<int> postorderTraversal(TreeNode *root) {
     2         vector<int> path;
     3         stack<TreeNode *> st;
     4         TreeNode *prev = NULL;
     5 
     6         st.push(root);
     7         while (!st.empty()) {
     8             TreeNode *node = st.top();
     9 
    10             if (!node)
    11                 st.pop();
    12             else if ((!node->left && !node->right)
    13                   || (prev && (node->left == prev || node->right == prev))) {
    14                 path.push_back(node->val);
    15                 st.pop();
    16                 prev = node;
    17             }
    18             else {
    19                 st.push(node->right);
    20                 st.push(node->left);
    21             }
    22         }
    23 
    24         return path;
    25     }

    也就短了几行而已。。

  • 相关阅读:
    直播平台的相关技术(转载)
    各种排序算法分析总结(待整理))
    算法:60.第k个排列
    三种随机化算法:舍伍德算法 拉斯维加斯算法 蒙特卡洛算法
    随机化算法之随机数
    caffe调试
    Euclideanloss_layer层解析
    布线问题(分支限界法)
    最大堆和最小堆
    机器学习知识框架
  • 原文地址:https://www.cnblogs.com/boring09/p/4234231.html
Copyright © 2011-2022 走看看