对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问, 因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就 保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶(即访问左孩子后回到该节点和访问右孩子后回到该节点),只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是 否是第一次出现在栈顶。这里用一个unordered_set来表明是否是第二次出现,如果是第一次出现,则集合里没有这个节点,然后将它插入。若是第二次出现,则集合里已经出现这个节点了。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
unordered_set<TreeNode*>hash;
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*>s;
TreeNode* p=root;
vector<int>ans;
while(!s.empty()||p!=NULL){
while(p!=NULL){
s.push(p);
p=p->left;
}
if(!s.empty()){
TreeNode* t=s.top();
if(hash.find(t)==hash.end()){ //判断是否是第一次访问
hash.insert(t); //若是第一次访问栈顶元素,则加入集合里
p=t->right; //p指向右孩子
}
else{ //第二次访问
ans.push_back(t->val); //访问节点元素
s.pop();
//p=NULL; 这句话不要也可以,因为已经在访问栈顶元素了,说明p已经为NULL了
}
}
}
return ans;
}
};