遞歸和非遞歸實現 先序、中序、後序遍歷二叉樹
先序、中序、後序遍歷二叉樹是一個基礎又非常重要的知識點,頻繁出現在《劍指offer》面試題中,很多題目都是二叉樹遍歷的變形。
所以在本文章中,我總結了用遞歸和非遞歸的方法分別實現對二叉樹的先序、中序和後序遍歷。
-
遞歸實現三種遍歷
-
先序遍歷
package algorithm.tree; /** * * @author FHY * 遞歸實現 * 按照先序遍歷樹的順序打印樹結點 */ /* * 樹節點定義 */ class TreeNode{ int val = 0; TreeNode left; TreeNode right; public TreeNode(int val){ this.val = val; } } /* 二叉樹結構如下: * * 0 * / \ * 1 2 * / \ / \ * 3 4 5 6 * * 先序遍歷結果:0 1 3 4 2 5 6 */ public class PreOrderTraversal { public static void main(String[] args) { TreeNode root = new TreeNode(0); TreeNode node1 = new TreeNode(1); TreeNode node2 = new TreeNode(2); TreeNode node3 = new TreeNode(3); TreeNode node4 = new TreeNode(4); TreeNode node5 = new TreeNode(5); TreeNode node6 = new TreeNode(6); root.left = node1; root.right = node2; node1.left = node3; node1.right = node4; node2.left = node5; node2.right = node6; printPreOrderTreeNode(root); } private static void printPreOrderTreeNode(TreeNode root) { if(root == null) return; System.out.println(root.val); printPreOrderTreeNode(root.left); printPreOrderTreeNode(root.right); } }
-
中序遍歷
package algorithm.tree; /** * * @author FHY * 遞歸實現 * 按照中序遍歷樹節點的順序打印樹節點 */ /* 新建二叉樹如下: * * 0 * / \ * 1 2 * / \ / \ * 3 4 5 6 * * 中序遍歷結果:3 1 4 0 5 2 6 */ public class InOrderTraversal_1 { public static void main(String[] args) { TreeNode root = new TreeNode(0); TreeNode node1 = new TreeNode(1); TreeNode node2 = new TreeNode(2); TreeNode node3 = new TreeNode(3); TreeNode node4 = new TreeNode(4); TreeNode node5 = new TreeNode(5); TreeNode node6 = new TreeNode(6); root.left = node1; root.right = node2; node1.left = node3; node1.right = node4; node2.left = node5; node2.right = node6; printInOrderTreeNode(root); } private static void printInOrderTreeNode(TreeNode root) { if(root.left != null) printInOrderTreeNode(root.left); System.out.println(root.val); if(root.right != null) printInOrderTreeNode(root.right); } }
-
後序遍歷
package algorithm.tree; /** * * @author FHY * 遞歸實現 * 按照後序遍歷樹節點的順序打印樹節點 */ /* 新建二叉樹如下: * * 0 * / \ * 1 2 * / \ / \ * 3 4 5 6 * * 後序遍歷結果:3 4 1 5 6 2 0 */ public class PostOrderTraversal { public static void main(String[] args) { TreeNode root = new TreeNode(0); TreeNode node1 = new TreeNode(1); TreeNode node2 = new TreeNode(2); TreeNode node3 = new TreeNode(3); TreeNode node4 = new TreeNode(4); TreeNode node5 = new TreeNode(5); TreeNode node6 = new TreeNode(6); root.left = node1; root.right = node2; node1.left = node3; node1.right = node4; node2.left = node5; node2.right = node6; postOrderTraversal(root); } private static void postOrderTraversal(TreeNode root) { if(root == null) return; if(root.left != null) postOrderTraversal(root.left); if(root.right != null) postOrderTraversal(root.right); System.out.println(root.val); } }
-
-
非遞歸實現三種遍歷
-
先序遍歷
/** * Created by FHY on 2019/5/6. * 使用非遞歸方法先序遍歷二叉樹。 1 / \ 2 3 / 4 以上輸出爲:1->2->3->4 */ import java.util.Stack; import java.util.ArrayList; public class Solution { public ArrayList<Integer> preorderTraversal(TreeNode root) { ArrayList<Integer> result = new ArrayList<Integer>(); Stack<TreeNode> stack = new Stack<TreeNode>(); if(root == null) return result; stack.push(root); TreeNode thisNode = new TreeNode(0); while(!stack.isEmpty()){ thisNode = stack.pop(); result.add(thisNode.val); if(thisNode.right != null) stack.push(thisNode.right); if(thisNode.left != null) stack.push(thisNode.left); } return result; } }
-
中序遍歷
package offer1; import java.util.Stack; /** * Created by FHY on 2019/5/10. * 非遞歸實現樹的中序遍歷 * 0 * / \ * 1 2 * / \ * 3 4 * 以上樹輸出爲1,0,3,2,4 */ public class InOrderTraverse { public static void main(String[] args){ TreeNode root = new TreeNode(0); TreeNode node1 = new TreeNode(1); TreeNode node2 = new TreeNode(2); TreeNode node3 = new TreeNode(3); TreeNode node4 = new TreeNode(4); root.left = node1; root.right = node2; node2.left = node3; node2.right = node4; getInOrderTraverse(root); } public static void getInOrderTraverse(TreeNode root){ Stack<TreeNode> stack = new Stack<TreeNode>(); TreeNode p = root; TreeNode thisNode = null; while(p != null || !stack.isEmpty()){ if(p != null){ stack.push(p); p = p.left; }else{ thisNode = stack.pop(); System.out.println(thisNode.val); p = thisNode.right; } } } }
-
後序遍歷
package offer1; /** * Created by FHY on 2019/5/5. * 使用非遞歸方法後序遍歷二叉樹。 1 / \ 2 3 / 4 以上樹輸出結果爲:2->4->3->1 * 要保證根結點在左孩子和右孩子訪問之後才能訪問,因此對於任一結點P,先將其入棧。 * 如果P不存在左孩子和右孩子,則可以直接訪問它; * 或者P存在孩子,但是其孩子都已被訪問過了,則同樣可以直接訪問該結點 * 若非上述兩種情況,則將P的右孩子和左孩子依次入棧,這樣就保證了每次取棧頂元素的時候,左孩子在右孩 子前面被訪問,左孩子和右孩子都在根結點前面被訪問。 */ import java.util.Stack; import java.util.ArrayList; //樹節點定義 class TreeNode{ int val; TreeNode left; TreeNode right; public TreeNode(int val){ this.val = val; } } public class postOrder { public static void main(String[] args){ TreeNode root = new TreeNode(1); TreeNode root_left = new TreeNode(2); TreeNode root_right = new TreeNode(3); root.left = root_left; root.right = root_right; root_right.left = new TreeNode(4); ArrayList result = postorderTraversal(root); for(int i = 0; i < result.size(); i++){ System.out.println(result.get(i)); } } public static ArrayList<Integer> postorderTraversal(TreeNode root) { ArrayList<Integer> result = new ArrayList<Integer>(); if(root == null) return result; Stack<TreeNode> stack = new Stack<TreeNode>(); stack.push(root); TreeNode cur = new TreeNode(0); TreeNode pre = null; while(!stack.isEmpty()){ cur = stack.peek(); if(cur.left == null && cur.right == null || (pre != null && (pre == cur.left || pre == cur.right))){ result.add(cur.val); pre = cur; stack.pop(); }else { if(cur.right != null){ stack.push(cur.right); } if(cur.left != null){ stack.push(cur.left); } } } return result; } }
-