本文已参与「新人创作礼」活动,一起开启掘金创作之路。
原文链接:blog.csdn.net/roufoo/arti…
Binary Tree Postorder Traversal Given a binary tree, return the postorder traversal of its nodes’ values. Example Given binary tree {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:迭代法。 参考了下面这个链接的做法: blog.csdn.net/gatieme/art…
当前节点要被输出, 必须满足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方法。