您的位置:首页 > 其它

LeetCode 145:Binary Tree Postorder Traversal 解题与思考

2017-09-17 22:26 399 查看

LeetCode 145:Binary Tree Postorder Traversal 解题与思考

[原题链接]

题目描述

就是非递归的二叉树后续遍历

思路

通常来讲,将递归变为循环,都会想到用栈来模拟递归的过程;本题也不例外,只是需要考虑何时入栈何时出栈。

假设我们访问到一个节点,此时它的左右子树未访问;我们按照后序遍历的顺序,先访问左子节点,此时我们应该将当前节点压栈,因为在将左子树访问完毕之后,我们需要通过当前节点去访问右子树。

而在访问右子树之前,是否需要将这个节点出栈?答案是否定的:因为根据后续遍历的顺序,根节点是最后访问的。这个问题在另外两个遍历中的答案会和本题中答案不同,原因也是和自身的遍历顺序有关。

这个时候,我们不难得出一个算法:每次访问节点,将当前节点压栈,假如左节点不为空,则访问左节点;当左节点为空时,访问右节点;当两个节点都为空时,访问当前节点,然后将当前节点出栈。

而这个时候,我们需要判断左右节点是否都已经遍历过。注意到后续遍历的顺序,访问当前节点之前的那个节点,一定是该节点的右子节点。所以我们只需要判断上个访问的是否为该节点的右子节点,就能够判断是要访问右子树还是访问当前节点。

算法

前期准备:一个节点栈,一个答案数组

1、对于一个节点,将当前节点入栈,将当前节点设为其左子节点;

2、假如当前节点为空,若

栈顶的点有右子树

上一个被输出的节点不是该栈顶节点的右节点

倘若两条都符合,则将当前节点设置为栈顶节点的右节点

3、假如两条中有一条不符合,则栈顶节点一定是如下三种之一

该节点左子树已经遍历完,且无右子树

该节点右子树已经遍历完成

该节点为叶子节点

将该节点假如答案数组中,并将上一个被输出的节点设为栈顶节点,然后将该节点出栈

代码

#include <iostream>
#include <vector>
#include <stack>

class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
TreeNode *nowNode = root;
TreeNode *lastNode = NULL;

vector<int> result;
stack<TreeNode*> treeStack;

while ( nowNode || !treeStack.empty()) {
if ( nowNode ) {
treeStack.push(nowNode);
//lastNode = nowNode;
nowNode = nowNode->left;
}
else {
TreeNode *topNode = treeStack.top();
if ( topNode->right && lastNode != topNode->right ) {
nowNode = topNode->right;
}
else {
result.push_back(topNode->val);
lastNode = topNode;
treeStack.pop();
}
}
}
return result;
}
};


思考

和前序、中序遍历不同的地方,需要考虑当前节点的右子树是否已经遍历过,否则会出现死循环(一直遍历右子树)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode 遍历 二叉树