zoukankan      html  css  js  c++  java
  • LeetCode:Binary Tree Postorder Traversal

    题目:非递归实现二叉树的后序遍历。题目链接

    算法1:非递归使用栈。首先把根节点压栈,然后循环如下操作:用一个变量来记录上次访问的节点,如果当前栈顶元素左右儿子都为空 或者 上次访问的节点非空且等于栈顶节点的左儿子或右儿子,则直接访问;否则把栈顶元素的右节点和左节点依次压栈。代码如下:

     1 /**
     2  * Definition for binary tree
     3  * struct TreeNode {
     4  *     int val;
     5  *     TreeNode *left;
     6  *     TreeNode *right;
     7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     8  * };
     9  */
    10 class Solution {
    11 public:
    12     vector<int> postorderTraversal(TreeNode *root) {
    13         // IMPORTANT: Please reset any member data you declared, as
    14         // the same Solution instance will be reused for each test case.
    15         vector<int>res;
    16         if(root == NULL)return res;
    17         stack<TreeNode *> nstack;
    18         nstack.push(root);
    19         TreeNode *pre = NULL;//指向上次访问的节点
    20         while(nstack.empty() == false)
    21         {
    22             TreeNode *p = nstack.top();
    23             if((p->left == NULL && p->right == NULL) || 
    24                 (pre != NULL && (pre == p->left || pre == p->right)))
    25             {
    26                 res.push_back(p->val);
    27                 nstack.pop();
    28                 pre = p;
    29             }
    30             else
    31             {
    32                 if(p->right)
    33                     nstack.push(p->right);
    34                 if(p->left)
    35                     nstack.push(p->left);
    36             }
    37         }
    38         return res;
    39     }
    40 };

    算法2:非递归不使用栈(Morris Traversal算法),只要在Morris Traversal中序遍历的算法基础上要做较大改动,它和中序morris遍历有所不同,在发现当前结点左子树为空时,不访问此结点(后序遍历需要保证访问完右子树后才能访问根结点),直接访问右子树。

    第二次遍历到某个结点时,将该结点左子树的最右路径(右指针所在的路径)反序输出即可。步骤如下,代码中红色部分是修改的:

    建立一个临时节点dump,令其左孩子是root,右孩子为空

    当前节点设置为临时节点dump。

    重复以下1、2直到当前节点为空。

    1. 如果当前节点的左孩子为空,则将其右孩子作为当前节点。

    2. 如果当前节点的左孩子不为空,在当前节点的左子树中找到当前节点在中序遍历下的前驱节点。

       a) 如果前驱节点的右孩子为空,将它的右孩子设置为当前节点。当前节点更新为当前节点的左孩子。

       b) 如果前驱节点的右孩子为当前节点,将它的右孩子重新设为空。倒序输出从当前节点的左孩子到前驱节点这条路径上的所有节点。当前节点更新为当前节点的右孩子。

    注意:倒序输出路径上的节点时,由于题目O(1)的空间要求不能使用栈,因此要先翻转路径,输出后,再恢复

    比如下面的树:

    当第二次访问到6时,输出8,;第二次访问2时,输出9、6、4;第二次访问1时输出7、5、2,第二次访问dump节点时输出1、3

     1 /**
     2  * Definition for binary tree
     3  * struct TreeNode {
     4  *     int val;
     5  *     TreeNode *left;
     6  *     TreeNode *right;
     7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     8  * };
     9  */
    10 class Solution {
    11 public:
    12     vector<int> postorderTraversal(TreeNode *root) {
    13         // IMPORTANT: Please reset any member data you declared, as
    14         // the same Solution instance will be reused for each test case.
    15         vector<int>res;
    16         if(root == NULL)return res;
    17         TreeNode dump(0);
    18         dump.left = root;
    19         TreeNode *cur = &dump, *prev = NULL;
    20         while (cur)
    21         {
    22             if (cur->left == NULL)
    23             {
    24                 cur = cur->right;
    25             }
    26             else
    27             {
    28                 prev = cur->left;
    29                 while (prev->right != NULL && prev->right != cur)
    30                     prev = prev->right;
    31     
    32                 if (prev->right == NULL)
    33                 {
    34                     prev->right = cur;
    35                     cur = cur->left;
    36                 }
    37                 else
    38                 {
    39                     printReverse(cur->left, prev, res);  // visit node
    40                     prev->right = NULL;
    41                     cur = cur->right;
    42                 }
    43             }
    44         }
    45         return res;
    46     }
    47     void reverse(TreeNode *from, TreeNode *to) // reverse the tree nodes 'from' -> 'to'.
    48     {
    49         if (from == to)
    50             return;
    51         TreeNode *x = from, *y = from->right, *z;
    52         do
    53         {
    54             z = y->right;
    55             y->right = x;
    56             x = y;
    57             y = z;
    58         }while(x != to);
    59     }
    60 
    61     void printReverse(TreeNode* from, TreeNode *to, vector<int> &res) // print the reversed tree nodes 'from' -> 'to'.
    62     {
    63         reverse(from, to);
    64         
    65         TreeNode *p = to;
    66         while(true)
    67         {
    68             res.push_back(p->val);
    69             if (p == from)
    70                 break;
    71             p = p->right;
    72         }
    73         
    74         reverse(to, from);
    75     }
    76 
    77 };

    【版权声明】转载请注明出处:http://www.cnblogs.com/TenosDoIt/p/3416835.html

  • 相关阅读:
    element ui 表单清空
    element ui 覆盖样式 方法
    element ui 修改表单值 提交无效
    element ui 抽屉里的表单输入框无法修改值
    element ui 抽屉首次显示 闪烁
    css 左侧高度 跟随右侧内容高度 自适应
    PICNUF框架
    elementui 抽屉组件标题 出现黑色边框
    vue 子组件跨多层调用父组件中方法
    vue 编辑table 数据 未点击提交,table里的数据就发生了改变(深拷贝处理)
  • 原文地址:https://www.cnblogs.com/TenosDoIt/p/3416835.html
Copyright © 2011-2022 走看看