• 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     }

    也就短了几行而已。。

  • 相关阅读:
    开网页自动进入路由器设置界面的解决办法(腾达路由器)
    SQL基本语句
    驱动调试配置
    【转】snort
    【转】snort.conf分析(中文)
    【转】snort 笔记2 ----- 规则编写
    【转】Snort语法规则说明及实例讲解
    【转】Snort 命令参数详解
    POST教程笔记
    POST教程笔记
  • 原文地址:https://www.cnblogs.com/boring09/p/4234231.html
Copyright © 2020-2023  润新知