直接上代碼java
import java.util.Stack; public class BinaryTree { //定義一棵二叉樹,包括左子樹、右子樹、該節點的值和構造器 public BinaryTree lchild; public BinaryTree rchild; public char data; public BinaryTree(BinaryTree l,BinaryTree r,char data) { lchild = l; rchild = r; this.data = data; } //訪問節點的函數 public void visit(BinaryTree t) { System.out.println(t.data); } /* * 遞歸實現二叉樹的遍歷都是分四步 * 1.判斷樹若是爲空則返回 * 2.訪問節點 * 3.判斷左子樹若是不爲空則遞歸左子樹 * 4.判斷右子樹不爲空則遞歸右子樹 * 前、中、後三個遍歷的區別就是訪問節點這一步分別實在判斷左子樹前,判斷左子樹和右子樹中間,判斷右子樹以後*/ //遞歸實現前序遍歷 public void pre(BinaryTree t) { if(t == null) return; visit(t); if(t.lchild != null) pre(t.lchild); if(t.rchild != null) pre(t.rchild); } //遞歸實現中序遍歷 public void mid(BinaryTree t) { if(t == null) return; if(t.lchild != null) mid(t.lchild); visit(t); if(t.rchild != null) mid(t.rchild); } //遞歸實現後序遍歷 public void pos(BinaryTree t) { if(t == null) return; if(t.lchild != null) pos(t.lchild); if(t.rchild != null) pos(t.rchild); visit(t); } /** * 非遞歸實現二叉樹的遍歷都是用棧實現 */ / /** * 非遞歸實現前序遍歷 * 注意因爲棧先進後出的特色,順序是:出棧並訪問,右子樹不空壓棧,左子樹不空壓棧 */ public void pre2(BinaryTree t) { Stack<BinaryTree> s = new Stack<>(); s.push(t); while(!s.isEmpty()) { BinaryTree b = s.pop(); visit(b); if(b.rchild != null) s.push(b.rchild); if (b.lchild != null) s.push(b.lchild); } } /** * 非遞歸實現中序遍歷須要一箇中間變量p表明當前樹 * */ / public void mid2(BinaryTree t) { Stack<BinaryTree> s = new Stack<>(); BinaryTree p = t; while(!s.isEmpty() || p!=null) { if(p != null) { s.push(p); p = p.lchild; } else { p = s.pop(); visit(p); p = p.rchild; } } } /* 二叉樹的非遞歸後序遍歷 和前序遍歷的不一樣是先判斷一下是否是沒有孩子或者左右孩子已經訪問,而後才能夠訪問該節點 */ public List<Integer> postorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>(); if (root==null) return res; Stack<TreeNode> stack = new Stack<>(); TreeNode last = null; TreeNode cur ; stack.push(root); while (!stack.isEmpty()) { cur = stack.peek(); if ((cur.left==null&&cur.right==null)||last!=null&&(last==cur.left||last==cur.right)) { //沒有孩子或者孩子已經遍歷過 res.add(cur.val); last = cur; stack.pop(); } else { if (cur.right!=null) stack.push(cur.right); if (cur.left!=null) stack.push(cur.left); } } return res; } }
還有一種方法:前序遍歷的時候,順序是:根-左-右。如今只要改爲:根-右-左,最後在reverse一下數組
注意因爲stack先進後出,前序遍歷的時候是先壓入右,再壓左,這裏是先左後右函數
public ArrayList<Integer> postorderTraversal(TreeNode root) { if(root==null) return new ArrayList(); Stack<TreeNode> stack = new Stack(); ArrayList<Integer> res = new ArrayList(); stack.push(root); while(!stack.isEmpty()) { TreeNode cur = stack.pop(); res.add(cur.val); if(cur.left!=null) stack.push(cur.left); if(cur.right!=null) stack.push(cur.right); } Collections.reverse(res); return res; }
層序遍歷:post
層序遍歷用BFSthis
迭代方法:存取節點的結構是queue隊列,經常使用的實現類是linkedlist,不斷添加節點到隊列後邊spa
遞歸方法:維護一個二維數組和層數,不一樣層的數放到不一樣的數組中code
/* 迭代方法 */ public List<List<Integer>> levelOrder(TreeNode root) { List<List<Integer>> res = new ArrayList<>(); if (root==null) return res; Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root); while (!queue.isEmpty()) { int s = queue.size(); List<Integer> cur = new ArrayList<>(); for (int i = 0; i < s; i++) { TreeNode temp = queue.poll(); cur.add(temp.val); if (temp.left!=null) queue.offer(temp.left); if (temp.right!=null) queue.offer(temp.right); } res.add(cur); } return res; }
遞歸方法:blog
List<List<Integer>> res = new ArrayList<>(); public List<List<Integer>> levelOrder(TreeNode root) { helper(root,0); return res; } public void helper(TreeNode root,int c) { if (root==null) return; if (res.size()==c) res.add(new ArrayList<>()); List<Integer> cur = res.get(c); cur.add(root.val); if (root.left!=null) helper(root.left,c+1); if (root.right!=null) helper(root.right,c+1); }