- Binary Tree Postorder Traversal
Given a binary tree, return the postorder traversal of its nodes’ values.
Example
Given binary tree {1,#,2,3},
1
2
/
3
return [3,2,1].
Challenge
Can you do it without recursion?
解法1: 简单的递归
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param root: A Tree
* @return: Postorder in ArrayList which contains node values.
*/
vector<int> postorderTraversal(TreeNode * root) {
vector<int> result;
postOrder(root, result);
return result;
}
private:
void postOrder(TreeNode * node, vector<int> &vec) {
if (!node) return;
postOrder(node->left, vec);
postOrder(node->right, vec);
vec.push_back(node->val);
}
};
解法2:迭代法。
参考了下面这个链接的做法:
https://blog.csdn.net/gatieme/article/details/51163010
当前节点要被输出, 必须满足3个条件之一:
- 其左右节点均为NULL
- 其左节点刚被输出,而其右节点为NULL
注意下面的
(pre && ((pre == cur->left) || (pre == cur->right)))) {
这里的pre == cur->left 不需要加cur->right == NULL检查,因为到了cur时,左右节点都已经被输出了。 - 其右节点刚被输出
压栈时先让父节点入栈,再右节点入栈,再左节点入栈。
class Solution {
public:
/**
* @param root: A Tree
* @return: Postorder in ArrayList which contains node values.
*/
vector<int> postorderTraversal(TreeNode * root) {
vector<int> result;
if (!root) return result;
stack<TreeNode *> s;
TreeNode * cur;
TreeNode * pre;
s.push(root);
while(!s.empty()) {
cur = s.top();
if ((!cur->left && !cur->right) ||
(pre && ((pre == cur->left) || (pre == cur->right)))) {
s.pop();
result.push_back(cur->val);
pre = cur;
} else {
if (cur->right)
s.push(cur->right);
if (cur->left)
s.push(cur->left);
}
}
return result;
}
};
解法3:参考了网上的模板。这个模板更好。
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param root: A Tree
* @return: Postorder in ArrayList which contains node values.
*/
vector<int> postorderTraversal(TreeNode * root) {
vector<int> result;
stack<TreeNode *> s;
TreeNode * current = root, * lastVisited = NULL;
while(current || !s.empty()) {
while(current) {
s.push(current);
current = current->left;
}
current = s.top();
if (!current->right || current->right == lastVisited) {
s.pop();
result.push_back(current->val);
lastVisited = current;
current = NULL;
} else {
current = current->right;
}
}
return result;
}
};
解法4:下面这个模板最好。
思路:遍历顺序为左、右、根
1) 如果root非空,将root加入到栈中。
2) 如果stack不空,取栈顶元素(暂时不弹出),
如果(左子树已访问过或者左子树为空),且(右子树已访问过或右子树为空),则弹出栈顶节点,将其值加入数组,
如果左子树不为空,且未访问过,则将左子节点加入栈中,并标左子树已访问过。
如果右子树不为空,且未访问过,则将右子节点加入栈中,并标右子树已访问过。
3) 重复2) 直到栈空。
注意:
- 怎么知道某个节点没有被访问过?
current == lastVisited.left 或 current == lastVisited.right
则说明current肯定没被访问过,因为这个节点的左节点或右节点刚被访问,这个节点作为根节点不可能被访问过。 - 怎么知道左子树已访问过?
current->left == lastVisited。
同理,current->right == lastVisited说明右子树刚被访问过。
这里的current就相当于是某个子树的根节点。 - 当左子树刚被访问过,我们必须将current的右节点放入栈中,因为postorder traversal的顺序是左右中。
- 注意这里很多else,不能省略!!! 因为要达到while()一直加左节点或右节点的效果。
代码如下:
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param root: A Tree
* @return: Postorder in ArrayList which contains node values.
*/
vector<int> postorderTraversal(TreeNode * root) {
vector<int> result;
stack<TreeNode *> s;
TreeNode * current = root, * lastVisited = NULL;
if (!root) return vector<int>();
s.push(root);
while(!s.empty()) {
current = s.top();
if (!lastVisited || current == lastVisited->left || current == lastVisited->right) {
if (current->left) {
s.push(current->left);
} else if (current->right) { //note! the else is needed here!!!
s.push(current->right);
}
} else if (current->left == lastVisited) {
if (current->right) {
s.push(current->right);
}
} else {
result.push_back(current->val);
s.pop();
}
lastVisited = current;
}
return result;
}
};
解法5:Morris方法。