題目:二叉樹的後序遍歷
解析:
1.遞歸遍歷
public List<Integer> postorderTraversal1(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
if (root == null) return list;
postorder(root,list);
return list;
}
public void postorder(TreeNode root, List<Integer> list){
if (root != null){
postorder(root.left,list);
postorder(root.right,list);
list.add(root.val);
}
}
2.非遞歸遍歷
①首先向棧中循環壓入左節點,即stack中數據爲1->2->4->8;
②判斷棧頂結點8是否有右孩子,如果沒有彈出8添加到list中,即棧stack中數據爲1->2->4,list中數據爲8;
③判斷棧頂結點4是否有右孩子,結點4有右孩子,將結點4的右孩子9壓入棧中,棧stack數據爲1->2->4->9;
④判斷棧頂結點9是否有右孩子,結點9沒有右孩子,彈出結點9加入list中,棧stack中的數據爲1->2->4,list中的數據爲8->9;
⑤判斷棧頂元素4是否有結點,注意此時要加上該節點的右孩子之前是否被訪問過的限定條件,即在上一步驟記錄彈出的結點last=9。此時由於棧頂4的右孩子被訪問過,因此棧頂元素不再加入list中,直接彈出即可;
…
循環判斷棧頂元素是否有右孩子或棧頂元素的右孩子是否被訪問過,如果有則先壓入棧中,如果沒有則直接彈出加入list中。
public List<Integer> postorderTraversal2(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
if (root == null) return list;
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode pnode = null;
while (root != null || !stack.isEmpty()){
//循環將左孩子的結點壓入棧
while(root != null){
stack.push(root);
root = root.left;
}
TreeNode node = stack.peek();
//如果棧中壓入的結點的右孩子爲空,或其右孩子爲上一個已經被訪問過
if (node.right == null|| node.right == pnode){
list.add(node.val);//直接訪問該節點,不在壓入其右孩子
pnode = stack.pop();//記錄當前被訪問過的結點
root = null;
}else{
//如果棧中壓入的結點的有右孩子,那麼壓入右孩子
root = node.right;
}
}
return list;
}