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); }};
- 146. Binary Tree Postorder Traversal
- Binary Tree Postorder Traversal
- Binary Tree Postorder Traversal
- Binary Tree Postorder Traversal
- Binary Tree Postorder Traversal
- Binary Tree Postorder Traversal
- Binary Tree Postorder Traversal
- Binary Tree Postorder Traversal
- Binary Tree Postorder Traversal
- Binary Tree Postorder Traversal
- Binary Tree Postorder Traversal
- Binary Tree Postorder Traversal
- Binary Tree Postorder Traversal
- Binary Tree Postorder Traversal
- Binary Tree Postorder Traversal
- Binary Tree Postorder Traversal
- Binary Tree Postorder Traversal
- Binary Tree Postorder Traversal
- 开源ffmpeg项目记录
- HDU 5410 CRB and His Birthday(完全背包)——多校练习10
- 集合的遍历
- [Daily150820]I,java
- twistd一行服务器的方法,搭建DNS、Web文件服务器
- 146. Binary Tree Postorder Traversal
- 面向对象与面向过程的编程思想比较
- Windows Server AppFabric Caching
- ImageView与手势识别
- CRB and String(HDUOJ--5414
- poj 3233 矩阵快速幂
- css基础精华02
- css基础精华03
- Java值传递以及引用的传递、数组的传递!!