Given a binary tree, return the postorder traversal of its nodes' values.
For example:
Given binary tree {1,#,2,3}
,
1 2 / 3
return [3,2,1]
.
Note: Recursive solution is trivial, could you do it iteratively?
这道题想了很久,后序遍历应该是最麻烦的吧,最容易想到的方法就是直接设置标志位。
相比于前序遍历,后续遍历思维上难度要大些,前序遍历是通过一个stack,首先压入父亲结点,然后弹出父亲结点,并输出它的value,之后压人其右儿子,左儿子即可。然而后序遍历结点的访问顺序是:左儿子 -> 右儿子 -> 自己。那么一个结点需要两种情况下才能够输出:第一,它已经是叶子结点;第二,它不是叶子结点,但是它的儿子已经输出过。那么基于此我们只需要记录一下当前输出的结点即可。对于一个新的结点,如果它不是叶子结点,儿子也没有访问,那么就需要将它的右儿子,左儿子压入。如果它满足输出条件,则输出它,并记录下当前输出结点。输出在stack为空时结束。
网上看到一种简洁的方法,如果一个节点的左子树或右子树入栈后,就将其相应的左子树或右子树设置为NULL,思想简单,代码也简单,代码如下:
/** * 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: vector<int> postorderTraversal(TreeNode* root) { vector<int> res; stack<TreeNode*> stk; TreeNode* flag=root; if(root==NULL) return res; stk.push(root); while(!stk.empty()) { flag=stk.top(); if(flag->left!=NULL) { stk.push(flag->left); flag->left=NULL; } else if(flag->right!=NULL) { stk.push(flag->right); flag->right=NULL; } else { res.push_back(flag->val); stk.pop(); } } return res; } };
设立标志位的解法如下:
/** * Definition for binary tree * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: vector<int> postorderTraversal(TreeNode *root) { vector<int> result; stack<TreeNode*> node; stack<int> nodeStatus; if(root != NULL){ node.push(root); nodeStatus.push(0); } while(!node.empty()){ TreeNode* n = node.top(); node.pop(); int status = nodeStatus.top(); nodeStatus.pop(); if(status == 0){ node.push(n); nodeStatus.push(1); if(n->right != NULL){ node.push(n->right); nodeStatus.push(0); } if(n->left != NULL){ node.push(n->left); nodeStatus.push(0); } } else{ result.push_back(n->val); } } return result; }