146. Binary Tree Postorder Traversal

来源:互联网 发布:联合利华二级销售 知乎 编辑:程序博客网 时间:2024/05/29 18:20

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

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

/** * Definition for binary tree * struct TreeNode { *     int val; *     TreeNode *left; *     TreeNode *right; *     TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */class Solution {public:    vector<int> postorderTraversal(TreeNode *root) {        // IMPORTANT: Please reset any member data you declared, as        // the same Solution instance will be reused for each test case.        vector<int>res;        if(root == NULL)return res;        stack<TreeNode *> nstack;        nstack.push(root);        TreeNode *pre = NULL;//指向上次访问的节点        while(nstack.empty() == false)        {            TreeNode *p = nstack.top();            if((p->left == NULL && p->right == NULL) ||                 (pre != NULL && (pre == p->left || pre == p->right)))            {                res.push_back(p->val);                nstack.pop();                pre = p;            }            else            {                if(p->right)                    nstack.push(p->right);                if(p->left)                    nstack.push(p->left);            }        }        return res;    }};

算法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

/** * Definition for binary tree * struct TreeNode { *     int val; *     TreeNode *left; *     TreeNode *right; *     TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */class Solution {public:    vector<int> postorderTraversal(TreeNode *root) {        // IMPORTANT: Please reset any member data you declared, as        // the same Solution instance will be reused for each test case.        vector<int>res;        if(root == NULL)return res;        TreeNode dump(0);        dump.left = root;        TreeNode *cur = &dump, *prev = NULL;        while (cur)        {            if (cur->left == NULL)            {                cur = cur->right;            }            else            {                prev = cur->left;                while (prev->right != NULL && prev->right != cur)                    prev = prev->right;                    if (prev->right == NULL)                {                    prev->right = cur;                    cur = cur->left;                }                else                {                    printReverse(cur->left, prev, res);  // visit node                    prev->right = NULL;                    cur = cur->right;                }            }        }        return res;    }    void reverse(TreeNode *from, TreeNode *to) // reverse the tree nodes 'from' -> 'to'.    {        if (from == to)            return;        TreeNode *x = from, *y = from->right, *z;        do        {            z = y->right;            y->right = x;            x = y;            y = z;        }while(x != to);    }    void printReverse(TreeNode* from, TreeNode *to, vector<int> &res) // print the reversed tree nodes 'from' -> 'to'.    {        reverse(from, to);                TreeNode *p = to;        while(true)        {            res.push_back(p->val);            if (p == from)                break;            p = p->right;        }                reverse(to, from);    }};




0 0
原创粉丝点击