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

  • 相关阅读:
    事务的基本特性和隔离级别
    mysql锁的类型
    索引设计的原则
    mysql聚簇索引和非聚簇索引的区别
    spring事务什么时候会失效?
    spring事务传播机制
    GAN的Pytorch实现
    DCGAN的Pytorch实现
    PyTorch学习教程、手册
    去噪论文合集Paper
  • 原文地址:https://www.cnblogs.com/TenosDoIt/p/3416835.html
Copyright © 2011-2022 走看看