前序遍历,中序遍历,后序遍历二叉树 ( 递归非递归方法 )
/** * 前序遍历递归解法: * (1)如果二叉树为空,空操作 * (2)如果二叉树不为空,访问根节点,前序遍历左子树,前序遍历右子树 */ public static void preorderTraversalRec(TreeNode root) { if (root == null) { return; } System.out.print(root.val + " "); preorderTraversalRec(root.left); preorderTraversalRec(root.right); } /** * 前序遍历迭代解法1:用一个辅助stack,总是把右孩子放进栈 * http://www.youtube.com/watch?v=uPTCbdHSFg4 */ public static void preorderTraversal(TreeNode root) { if(root == null){ return; } Stack<TreeNode> stack = new Stack<TreeNode>(); // 辅助stack stack.push(root); while( !stack.isEmpty() ){ TreeNode cur = stack.pop(); // 出栈栈顶元素 System.out.print(cur.val + " "); // 关键点:要先压入右孩子,再压入左孩子,这样在出栈时会先打印左孩子再打印右孩子 if(cur.right != null){ stack.push(cur.right); } if(cur.left != null){ stack.push(cur.left); } } }
前序遍历迭代法2:
while(root!=null){
while(root!=null){
systom.out.print(root);
stack.push(root);
root=root.left;
}
root=stack.pop();
while(root.right==null){
root=stack.pop();
}
root=root.right;
}
/** * 中序遍历递归解法 * (1)如果二叉树为空,空操作。 * (2)如果二叉树不为空,中序遍历左子树,访问根节点,中序遍历右子树 */ public static void inorderTraversalRec(TreeNode root) { if (root == null) { return; } inorderTraversalRec(root.left); System.out.print(root.val + " "); inorderTraversalRec(root.right); } /** * 中序遍历迭代解法 ,用栈先把根节点的所有左孩子都添加到栈内, * 然后输出栈顶元素,再处理栈顶元素的右子树 * http://www.youtube.com/watch?v=50v1sJkjxoc * * 还有一种方法能不用递归和栈,基于线索二叉树的方法,较麻烦以后补上 * http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/ */ public static void inorderTraversal(TreeNode root){ if(root == null){ return; } Stack<TreeNode> stack = new Stack<TreeNode>(); TreeNode cur = root; while( true ){ while(cur != null){ // 先添加一个非空节点所有的左孩子到栈 stack.push(cur); cur = cur.left; } if(stack.isEmpty()){ break; } // 因为此时已经没有左孩子了,所以输出栈顶元素 cur = stack.pop(); System.out.print(cur.val + " ");
(每个节点的下一个节点是这个节点的右节点的最左节点,右节点没有左节点就是右节点,没有右节点就是栈中弹出的节点) cur = cur.right; // 准备处理右子树 } } /** * 后序遍历递归解法 * (1)如果二叉树为空,空操作 * (2)如果二叉树不为空,后序遍历左子树,后序遍历右子树,访问根节点 */ public static void postorderTraversalRec(TreeNode root) { if (root == null) { return; } postorderTraversalRec(root.left); postorderTraversalRec(root.right); System.out.print(root.val + " "); } /** * 后序遍历迭代解法 * http://www.youtube.com/watch?v=hv-mJUs5mvU * */ public static void postorderTraversal(TreeNode root) { if (root == null) { return; } Stack<TreeNode> s = new Stack<TreeNode>(); // 第一个stack用于添加node和它的左右孩子 Stack<TreeNode> output = new Stack<TreeNode>();// 第二个stack用于翻转第一个stack输出
(从s弹出一个加入output,并把弹出的左右加入s,循环。)
s.push(root); while( !s.isEmpty() ){ // 确保所有元素都被翻转转移到第二个stack TreeNode cur = s.pop(); // 把栈顶元素添加到第二个stack output.push(cur); if(cur.left != null){ // 把栈顶元素的左孩子和右孩子分别添加入第一个stack s.push(cur.left); } if(cur.right != null){ s.push(cur.right); } } while( !output.isEmpty() ){ // 遍历输出第二个stack,即为后序遍历 System.out.print(output.pop().val + " "); } } /** * 分层遍历二叉树(按层次从上往下,从左往右)迭代 * 相当于广度优先搜索,使用队列实现。队列初始化,将根节点压入队列。当队列不为空,进行如下操作:弹出一个节点 * ,访问,若左子节点或右子节点不为空,将其压入队列 */ public static void levelTraversal(TreeNode root) { if (root == null) { return; } LinkedList<TreeNode> queue = new LinkedList<TreeNode>(); queue.push(root); while (!queue.isEmpty()) { TreeNode cur = queue.removeFirst(); System.out.print(cur.val + " "); if (cur.left != null) { queue.add(cur.left); } if (cur.right != null) { queue.add(cur.right); } } }