Given a binary tree, return the postorder traversal of its nodes' values.
For example:
Given binary tree {1,#,2,3}
,
1 \ 2 / 3
return [3,2,1]
.
Note: Recursive solution is trivial, could you do it iteratively?
--------------------------1. Morris traversal
关键点是在循环中,对每个节点的处理分两种情况
1. left节点为空:
设置当前节点为right,然后continue
2. left节点不为空:
从当前节点left节点(设为l)开始,一直向right走,走到下一个right为NULL或者等于当前节点(说明这是第二次访问当前节点)
a. 如果l->right == NULL, 设置l->right = cur, cur = cur->left, 然后continue;
b. 如果l->right == cur, 反向访问cur->left -- l , 设置l->right = NULL
前序和中序访问,思想和这个一样,只是在访问节点数据的时机不同,要比这个post的简单(不用反向访问一个串), 本质思想就是在第一次访问每个节点(假设一个A节点)的时候,先把这个节点的inorder顺序的前一个节点的right节点设置为当前节点,这样的话总有某个时刻会通过(cur=cur->rigth)的形式第二次访问A节点的时候,这时就知道A的左树已经访问完毕了,然后根据要求(前中后序)在适当位置访问节点数据就ok了。
2. Two stacks
这个没啥好说的,就是按照post visit的定义把所有节点按照顺序放入第二个栈(借助第一个栈),然后逐个弹出访问就行了。
/**
* 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) {
vector<int> ret;
// 1
TreeNode dummy(-1);
dummy.left = root;
TreeNode *cur = &dummy;
while (cur != NULL) {
if (cur->left == NULL) {
cur = cur->right;
} else {
TreeNode *l = cur->left;
while (l->right != NULL && l->right != cur) l = l->right;
if (l->right == NULL) {
l->right = cur;
cur = cur->left;
} else {
reverseVisit(cur->left, l, ret);
l->right = NULL;
cur = cur->right;
}
}
}
// 2
/*
if (root == NULL) return ret;
stack<TreeNode*> sk1, sk2;
sk1.push(root);
while (!sk1.empty()) {
TreeNode *cur = sk1.top();
sk1.pop();
sk2.push(cur);
if (cur->left != NULL) sk1.push(cur->left);
if (cur->right != NULL) sk1.push(cur->right);
}
while (!sk2.empty()) {
ret.push_back(sk2.top()->val);
sk2.pop();
}
*/
return ret;
}
private:
void reverseVisit(TreeNode *from, TreeNode *to, vector<int> &ret) {
if (from == NULL || to == NULL) return;
reverseTreeNodes(from, to);
TreeNode *cur = to;
while (true) {
ret.push_back(cur->val);
if (cur == from) break;
cur = cur->right;
}
reverseTreeNodes(to, from);
}
void reverseTreeNodes(TreeNode *from, TreeNode *to) {
if (from == to || from == NULL || to == NULL) return;
TreeNode *pre = from, *cur = from->right;
while (true) {
TreeNode *next = cur->right;
cur->right = pre;
if (cur == to) break;
pre = cur;
cur = next;
}
}
};