题解 | #二叉树的后序遍历#
二叉树的后序遍历
https://www.nowcoder.com/practice/1291064f4d5d4bdeaefbf0dd47d78541
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* };
*/
#include <stack>
#include <vector>
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @return int整型vector
*/
vector<int> postorderTraversal(TreeNode* root) {
// write code here
stack<TreeNode*> Node;
vector<int> order;
while (root != nullptr || !Node.empty()) {
while (root != nullptr) {
Node.push(root);
if(root->left!=nullptr)
root = root->left;
else
root = root->right;
}
root = Node.top();
Node.pop();
order.push_back(root->val);
if (!Node.empty()&&Node.top()->right != nullptr && Node.top()->left == root)
root = Node.top()->right;
else
root = nullptr;
}
return order;
}
};
后序遍历的非递归真的好难啊呜呜呜呜呜,看了三遍模板才写出来。
整个思路就是,如果当前节点非空,就放入栈,然后看看左边能不能往下,如果左边到头了就往右边,直到当前节点为空,也就是右边也到头了。这个时候栈里面存的就是最左边结点的右节点,也就是此时需要输出的位置(这里要注意,后序是左右根,对于最左结点来说,自己是根,如果他自己还有右节点,那需要先输出他的右结点,再输出他自己)。
将该节点从栈中弹出,作为新的root。
后面是一个比较绕的逻辑,我们现在面临的一个问题是,从当前这个弹出的root结点已经处理完了,下面回到此时的栈顶的节点,但是现在回到这个栈顶结点,是因为左边遍历完了回来的,还是因为右边遍历完了回来的,这两者的区别在于处理完当前的root,是找栈顶结点的右子树,还是root自己就是栈顶结点右子树,结束了需要直接处理此时的栈顶结点?
如果是第一种情况,也就是root是栈顶结点的左子树,那么将root赋值为Node.top()->right.如果是第二种情况,直接将root置为空,即可进入下次循环,回到上面直接处理栈顶结点的逻辑(打印栈顶结点值,将栈顶pop)
查看13道真题和解析