题目
思路
后序遍历的顺序是:左子树——右子树——根节点
相比较来说,后序遍历的非递归要比前序和中序遍历难度要高,因为当遍历完某个根节点的左子树,回到根节点的时候,对于中序遍历和前序遍历来说,可以把当前根节点直接弹出,然后转到右子树,而对于后序遍历来说,当回到根节点时,我们不知道是从左子树回到根节点,还是从右子树回到根节点,如果是从左子树回到根节点,那么我们还需要再遍历根节点的右子树,最后才能输出根节点;如果是右子树回到根节点,那么说明左子树和右子树都已经遍历完了,可以将根节点输出
思路一
我们设置一个节点记录上一次遍历的节点,如果当前节点的右节点和上次遍历的节点相同,说明当前节点是从右节点过来的,代码如下:
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> v;
stack<TreeNode*> s;
TreeNode* cur = root;
TreeNode* pre=NULL;
while (cur || !s.empty()) {//同样是不断遍历左子树
while (cur) {
s.push(cur);
cur = cur->left;
}
cur = s.top();
if (!cur->right || pre == cur->right) {//当该节点的右子树为空或者该节点的右节点是上次遍历过的节点,则直接弹出
v.push_back(cur->val);
s.pop();
pre = cur;
cur = NULL;//当弹出一个节点时,说明该树已经遍历完了,那么就要把cur设置为NULL
}
else {//否则就遍历右子树
cur = cur->right;
pre = NULL;
}
}
return v;
}
};
这种思路就是设置一个节点T,每当有节点弹出时,便将该节点T指向当前节点,这样做的目的是为了判断一个根节点是从左子树回到的还是从右子树回到的。