遍历
广度优先遍历
广度优先遍历(Breadth-first-first order): 尽可能先访问距离根最近的节点,也成为层序遍历
下面为队列实现广度优先遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| public class E01Leetcode102 {
public List<List<Integer>> levelOrder(TreeNode root) { List<List<Integer>> result = new ArrayList<>(); if(root == null) { return result; } LinkedListQueue<TreeNode> queue = new LinkedListQueue<>(); queue.offer(root); int c1 = 1; while(!queue.isEmpty()) { List<Integer> level = new ArrayList<>(); int c2 = 0; for (int i = 0; i < c1; i++) { TreeNode n = queue.pool(); level.add(n.val); if(n.left != null) { queue.offer(n.left); c2++; } if(n.right != null) { queue.offer(n.right); c2++; } } result.add(level); c1 = c2; } return result; } }
|
深度优先遍历
深度优先遍历(Depth-first order) : 对于二叉树,可以进一步分成三种(要深入叶子节点)
1、pre-order 前序遍历,对于每一颗子树,先访问该节点,然后是左子树,最后是右子树
2、in-order 中序遍历,对于每一颗子树,先访问左子树,然后是该节点,最后是右子树
3、post-order 后序遍历,对于每一棵子树,先访问左子树,然后是右子树,最后是该节点
递归实现三中深度遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
|
static void preOrder(TreeNode node) { if(node == null) { return; } System.out.print(node.val + "\t"); preOrder(node.left); preOrder(node.right); }
static void inOrder(TreeNode node) { if(node == null) { return; } preOrder(node.left); System.out.print(node.val + "\t"); preOrder(node.right); }
static void postOrder(TreeNode node) { if(node == null) { return; } preOrder(node.left); preOrder(node.right); System.out.print(node.val + "\t"); }
|
非递归实现
实现思路:前中后遍历虽然看起来不一样但是其实本质上都是从root一路走回来的过程,只不过是取值的时机不一样而已。实现走出去还要回来的数据结构选择栈,这样就可以实现三中非递归遍历,只不过代码略有差异且难想。
前序遍历:只要打印去的路即可
1 2 3 4 5 6 7 8 9 10 11 12 13
| LinkedList<TreeNode> stack = new LinkedList<>(); TreeNode curr = root; while(curr != null || !stack.isEmpty()) { if(curr != null) { System.out.println("去" + curr.val); stack.push(curr); curr = curr.left; } else { TreeNode pop = stack.pop(); curr = pop.right; } }
|
中序遍历:只要打印回的路即可
1 2 3 4 5 6 7 8 9 10 11 12 13
| LinkedList<TreeNode> stack = new LinkedList<>(); TreeNode curr = root; while(curr != null || !stack.isEmpty()) { if(curr != null) { stack.push(curr); curr = curr.left; } else { TreeNode pop = stack.pop(); System.out.println("回"+pop.val); curr = pop.right; } }
|
后序遍历:判断根节点是否需要出栈是难点,只有右子孩子遍历完之后才能弹栈到自己遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| LinkedList<TreeNode> stack = new LinkedList<>(); TreeNode curr = root; TreeNode pop = null; while(curr != null || !stack.isEmpty()) { if(curr != null) { System.out.println("去" + curr.val); stack.push(curr); curr = curr.left; } else { TreeNode peek = stack.peek(); if(peek.right == null || peek.right == pop) { pop = stack.pop(); System.out.println("回"+pop.val); } else { curr = peek.right; } } }
|
三个愿望,一次满足!!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| LinkedList<TreeNode> stack = new LinkedList<>(); TreeNode curr = root; TreeNode pop = null; while (curr != null || !stack.isEmpty()) { if (curr != null) { stack.push(curr); System.out.println("前" + curr.val); curr = curr.left; } else { TreeNode peek = stack.peek(); if (peek.right == null) { System.out.println("中" + peek.val); pop = stack.pop(); System.out.println("后" + pop.val); } else if (peek.right == pop) { pop = stack.pop(); System.out.println("后" + pop.val); } else { System.out.println("中" + peek.val); curr = peek.right; } } }
|
二叉树经典题
力扣101-对称二叉树
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public boolean isSymmetric(TreeNode root) { return check(root.left, root.right); } private boolean check(TreeNode left, TreeNode right) { if(left == null && right == null) { return true; } if(right == null || left == null) { return false; } if(left.val != right.val) { return false; } return check(left.left, right.right) && check(left.right, right.left); }
|
力扣104-二叉树的最大深度
方法一:递归
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
public int maxDepth(TreeNode root) { if(root == null) { return 0; } return Integer.max(maxDepth(root.left), maxDepth(root.right)) + 1; }
|
方法二:后序遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
public int maxDepth(TreeNode root) { TreeNode curr = root; TreeNode pop = null; LinkedList<TreeNode> stack = new LinkedList<>(); int max = 0; while(curr != null || !stack.isEmpty()) { if(curr != null) { stack.push(curr); int size = stack.size(); if(size > max) { max = size; } curr = curr.left; } else { TreeNode peek = stack.peek(); if(peek.right == null || peek.right == pop) { pop = stack.pop(); } else { curr = peek.right; } } } return max; }
|
方法三:层序遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
public int maxDepth(TreeNode root) { if(root == null) { return 0; } Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root); int ans = 0; while(!queue.isEmpty()) { int size = queue.size(); for (int i = 0; i < size; i++) { TreeNode poll = queue.poll(); if(poll.left != null) { queue.offer(poll.left); } if(poll.right != null) { queue.offer(poll.right); } } ans++; } return ans; }
|
力扣111-二叉树的最小深度
方法一:递归
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public int minDepth(TreeNode root) { if(root == null) { return 0; } if(root.left == null && root.right == null) { return 1; } int p1 = minDepth(root.left); int p2 = minDepth(root.right); if(p2 == 0) { return p1 + 1; } if(p1 == 0) { return p2 + 1; } return Math.min(p1, p2) + 1; }
|
方法二:层序遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
public int minDepth(TreeNode root) { if(root == null) { return 0; } Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root); int ans = 0; while(!queue.isEmpty()) { int size = queue.size(); ans++; for (int i = 0; i < size; i++) { TreeNode poll = queue.poll(); if(poll.left == null && poll.right == null) { return ans; } if(poll.left != null) { queue.offer(poll.left); } if(poll.right != null) { queue.offer(poll.right); } } } return ans; }
|
力扣226-翻转二叉树
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public TreeNode invertTree(TreeNode root) { if(root==null) { return null; } TreeNode tmp = root.right; root.right = root.left; root.left = tmp; invertTree(root.left); invertTree(root.right); return root; }
|
后缀表达式的二叉树形式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| static class TreeNode { public String val; public TreeNode left; public TreeNode right; public TreeNode(String val) { this.val = val; } public TreeNode(TreeNode left, String val, TreeNode right) { this.left = left; this.val = val; this.right = right; } @Override public String toString() { return this.val; } } public TreeNode constructExpressionTree(String[] tokens) { LinkedList<TreeNode> stack = new LinkedList<>(); for (String t : tokens) { if(t.equals("+") || t.equals("-") || t.equals("*") || t.equals("/")) { TreeNode right = stack.pop(); TreeNode left = stack.pop(); TreeNode root = new TreeNode(t); root.left = left; root.right = right; stack.push(root); } else { stack.push(new TreeNode(t)); } } return stack.peek(); }
|