递归和非递归实现 先序、中序、后序遍历二叉树
先序、中序、后序遍历二叉树是一个基础又非常重要的知识点,频繁出现在《剑指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; } }
-