遍历
广度优先遍历
广度优先遍历(Breadth-first-first order): 尽可能先访问距离根最近的节点,也成为层序遍历
下面为队列实现广度优先遍历
| 12
 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 后序遍历,对于每一棵子树,先访问左子树,然后是右子树,最后是该节点
递归实现三中深度遍历
| 12
 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一路走回来的过程,只不过是取值的时机不一样而已。实现走出去还要回来的数据结构选择栈,这样就可以实现三中非递归遍历,只不过代码略有差异且难想。
前序遍历:只要打印去的路即可
| 12
 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;
 }
 }
 
 | 
中序遍历:只要打印回的路即可
| 12
 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;
 }
 }
 
 | 
后序遍历:判断根节点是否需要出栈是难点,只有右子孩子遍历完之后才能弹栈到自己遍历
| 12
 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;
 }
 }
 }
 
 | 
三个愿望,一次满足!!!
| 12
 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-对称二叉树
| 12
 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-二叉树的最大深度
方法一:递归
| 12
 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;
 }
 
 | 
方法二:后序遍历
| 12
 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;
 }
 
 | 
方法三:层序遍历
| 12
 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-二叉树的最小深度
方法一:递归
| 12
 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;
 }
 
 | 
方法二:层序遍历
| 12
 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-翻转二叉树
| 12
 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;
 }
 
 | 
后缀表达式的二叉树形式
| 12
 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();
 }
 
 |