這種算法只用到了一次入棧一次出棧就能夠了,算法
//首先將根節點的左節點全部的節點入棧,一直到葉子節點,先將最右的葉子節點入棧,而後判斷是否已到了葉子節點,若是是則將節點的value值入棧,接着將此節點出棧,由於它沒用了 public ArrayList<Integer> postorderTraversal(TreeNode root) { // write your code here Stack<TreeNode> s = new Stack<TreeNode>(); ArrayList<Integer> Result = new ArrayList<Integer>(); if(root == null) return Result; TreeNode cur; TreeNode pre = null; s.push(root); //對於全部的節點都先入棧 while(!s.empty()){ cur = s.peek(); //當前操做數爲棧的頂部元素 if((cur.left==null&&cur.right==null)||(pre !=null&&(pre==cur.left||pre==cur.right))){ //若是當前操做數左右都爲空,或者P存在左孩子或者右孩子,可是其左孩子和右孩子都已被訪問過了,說明能夠訪問該節點了,而後此節點就沒用了能夠出棧了 Result.add(cur.val); s.pop(); pre = cur; //先保留一下子當前的節點,留着用來判斷是否該訪問他的父節點。 }else { if(cur.right!=null) s.push(cur.right); //若是當前節點右節點不爲空就入棧,只有先讓右節點入棧才能夠保證訪問的順序是對的, if(cur.left!=null) s.push(cur.left);//若是左孩子不爲空,左孩子最後入棧 } } return Result; }
九章算法:post
Stack<TreeNode> s = new Stack<TreeNode>(); ArrayList<Integer> r = new ArrayList<Integer>(); if(root ==null) return r; TreeNode pre = null; TreeNode cur; s.push(root); while(!s.empty()){ cur = s.peek(); if(pre==null||pre.left ==cur||pre.right==cur){ //先從上往下遍歷到葉子節點 if(cur.left!=null){ s.push(cur.left); //將每個左子樹節點入棧 }else if(cur.right!=null){ //如他的左子節點爲空判斷右節點,若是不爲空就將右節點入棧 s.push(cur.right); } }else if(cur.left==pre){ //開始從左子樹的底部往上遍歷,當cur.left==pre說明已經到達了左子樹的底部他的左子樹已經遍歷了,執行這一步的時候說明該節點的左孩子已經遍歷到了且出棧了 if(cur.right!=null){ //這時須要作的是將右孩子入棧待遍歷 s.push(cur.right); } }else { //從右子樹的底部往上遍歷 r.add(cur.val); s.pop(); } pre=cur; } return r;
遞歸實現:spa
ArrayList<Integer> r = new ArrayList<Integer>(); if(root ==null){ return r; } r.addAll(postorderTraversal(root.left)); r.addAll(postorderTraversal(root.right)); r.add(root.val); return r;