方法一:
public List<Integer> postorderTraversal(TreeNode root){
List<Integer> result = new ArrayList<Integer>();
if(root == null)
return result;
TreeNode node = root;
TreeNode pre = null;
Stack<TreeNode> st = new Stack<TreeNode>();
while(node != null || !st.isEmpty()){
if(node != null){ //把所有左节点压栈,直到最左叶子
st.push(node);
node = node.left;
}
else{ //压栈结束,考虑弹栈
if(st.isEmpty()) return result;
node = st.peek();
if(node.right == null || node.right == pre){//右节点为空,或者已经访问过了,弹栈、访问、标记
st.pop();
result.add(node.val);
pre = node;
node = null; //把node置为null,避免压栈
}
else
node = node.right; //右节点还没访问,使下一次循环时压栈
}
}
return result;
}
方法二:使用双栈法,借助“倒置”的先序遍历,把访问节点压进栈里,然后再逆序弹出,达到后续的效果。
public List<Integer> postorderTraversal(TreeNode root){
List<Integer> result = new List<Integer>();
if(root == null)
return result;
TreeNode node = root;
Stack<TreeNode> st = new Stack<TreeNode>();
Stack<Integer> re = new Stack<Integer>();
while(node != null || !st.isEmpty){
while(node != null)){
st.push(node);
re.push(node.val);
node = node.right; //只把右节点压栈
}
if(!st.isEmpty()){
node = st.pop(); //先弹栈,再访问左节点,此时栈顶存的是下一次循环要访问其左节点的节点
node = node.left;
}
}
while(!re.isEmpty()){
result.add(re.pop());
}
return result;
}