文章

二叉树的遍历Java

先序、中序、后序和层序遍历,涵盖递归和非递归算法。以及Morris遍历、二叉树深度计算及最近公共祖先的解决方案。

二叉树的遍历Java

二叉树的遍历

先序

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    static List<Integer> res;

    public List<Integer> preorderTraversal(TreeNode root) {
        res = new ArrayList<>();
        // preorderRecursion(root);
        // preorder(root);
        // preorderMorris(root);
        postorder2(root);
        return res;
    }
    
    // 保存右节点
    public static void postorder2(TreeNode root) {
        if (root == null) return;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode cur = stack.pop();
            res.add(cur.val);
            if (cur.right != null) stack.push(cur.right);
            if (cur.left != null) stack.push(cur.left);
        }
    }
    
    // Morris
    public static void preorderMorris(TreeNode root) {
        if (root == null) return;

        TreeNode cur = root;

        while (cur != null) {
            if (cur.left != null) {
                // 左子树不空,遍历左子树,找到左子树的最右侧节点
                TreeNode rightMost = cur.left;
                while (rightMost.right != null && rightMost.right != cur) {
                    rightMost = rightMost.right;
                }
                // 最右侧节点的右指针指向null或者cur
                if (rightMost.right == null) {
                    // 有左右孩子的节点第一次被访问
                    res.add(cur.val);
                    // 把最右侧节点的right指向cur
                    rightMost.right = cur;
                    // 访问左子树
                    cur = cur.left;
                } else {
                    // 有左右孩子的节点第二次被访问
                    // 恢复
                    rightMost.right = null;
                    // 遍历右子树
                    cur = cur.right;
                }
            } else {
                // 只有右孩子的节点只会被访问一次
                res.add(cur.val);
                // 遍历右子树
                cur = cur.right;
            }
        }
    }

    // 非递归
    public static void preorder(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        while (!stack.isEmpty() || root != null) {
            while (root != null) {
                res.add(root.val);
                stack.add(root);
                root = root.left;
            }
            root = stack.pop();
            root = root.right;
        }
    }

    // 递归
    public static void preorderRecursion(TreeNode root) {
        if (root == null)
            return;
        res.add(root.val);
        preorderRecursion(root.left);
        preorderRecursion(root.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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    static List<Integer> res;

    public List<Integer> inorderTraversal(TreeNode root) {
        res = new ArrayList<>();
//        inorderRecursion(root);
//        inorder(root);
        inorderMorris(root);
        return res;
    }

    public static void inorderMorris(TreeNode root) {
        if (root == null) return;
        TreeNode cur = root;
        while (cur != null) {
            if (cur.left != null) {
                TreeNode rightMost = cur.left;
                while (rightMost.right != null && rightMost.right != cur) {
                    rightMost = rightMost.right;
                }
                if (rightMost.right == null) {
                    rightMost.right = cur;
                    cur = cur.left;
                } else {
                    // 有左右孩子的节点第二次被经过,左子树都遍历完了,访问节点
                    res.add(cur.val);
                    rightMost.right = null;
                    cur = cur.right;
                }
            } else {
                // 只有右孩子的节点只会被经过一次,直接访问
                res.add(cur.val);
                cur = cur.right;
            }
        }
    }

    public static void inorder(TreeNode root) {
        if (root == null) return;
        Stack<TreeNode> stack = new Stack<>();
        while (!stack.isEmpty() || root != null) {
            while (root != null) {
                stack.push(root);
                root = root.left;
            }
            root = stack.pop();
            res.add(root.val);
            root = root.right;
        }
    }

    public static void inorderRecursion(TreeNode root) {
        if (root == null) return;
        inorderRecursion(root.left);
        res.add(root.val);
        inorderRecursion(root.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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
public class Solution {
    static List<Integer> res;

    public List<Integer> postorderTraversal(TreeNode root) {
        res = new ArrayList<>();
//        postorderRecursion(root);
//        postorder(root);
        postorderMorris(root);
        return res;
    }

    public static void postorderMorris(TreeNode root) {
        TreeNode cur = root;
        while (cur != null) {
            if (cur.left != null) {
                TreeNode rightMost = cur.left;
                while (rightMost.right != null && rightMost.right != cur) {
                    rightMost = rightMost.right;
                }
                if (rightMost.right == null) {
                    rightMost.right = cur;
                    cur = cur.left;
                } else {
                    rightMost.right = null;
                    // 一个节点被第二次经过的时候,自底向上访问左子树的所有的右节点
                    visitReversedRightTree(cur.left);
                    cur = cur.right;
                }
            } else {
                cur = cur.right;
            }
        }
        // 再遍历一次
        visitReversedRightTree(root);
    }

    // 自底向上访问右节点(访问反转后的右节点)
    public static void visitReversedRightTree(TreeNode root) {
        // 反转右子树
        TreeNode reversed = reverseRightTree(root);
        TreeNode cur = reversed;
        while (cur != null) {
            res.add(cur.val);
            cur = cur.right;
        }
        // 反转回去
        reverseRightTree(reversed);
    }

    // 把右子树反转
    public static TreeNode reverseRightTree(TreeNode root) {
        TreeNode pre = null;
        TreeNode cur = root;
        while (cur != null) {
            TreeNode nextRight = cur.right;
            cur.right = pre;
            pre = cur;
            cur = nextRight;
        }
        return pre;
    }

    public static void postorder(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        TreeNode pre = null;
        while (!stack.isEmpty() || root != null) {
            while (root != null) {
                stack.push(root);
                root = root.left;
            }

            root = stack.pop();
            if (root.right == null || root.right == pre) {
                // 没有右子树或者右子树已经被访问过了
                res.add(root.val);
                // pre始终指向上一个被访问过的节点
                pre = root;
                root = null;
            } else {
                // 访问右子树前,先把当前节点重新入栈
                stack.push(root);
                root = root.right;
            }
        }
    }

    public static void postorderRecursion(TreeNode root) {
        if (root == null) return;
        postorderRecursion(root.left);
        postorderRecursion(root.right);
        res.add(root.val);
    }
}

层序

二叉树深度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Solution {
    public int maxDepth(TreeNode root) {
        // 递归
/*        if (root == null) return 0;
        return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;*/

        // 层序遍历累计层数
        if (root == null) return 0;
        int res = 0;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);

        while (!queue.isEmpty()) {
            res++;
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode temp = queue.remove();
                if (temp.left != null) queue.add(temp.left);
                if (temp.right != null) queue.add(temp.right);
            }
        }
        return res;
    }
}

层序遍历记录每一层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Solution {
    public static List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        if (root == null) return res;

        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);

        while (!queue.isEmpty()) {
            List<Integer> tempList = new ArrayList<>();
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode node = queue.remove();
                tempList.add(node.val);
                if (node.left != null) queue.add(node.left);
                if (node.right != null) queue.add(node.right);
            }
            res.add(tempList);
        }
        return res;
    }
}

最近公共祖先LCA

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
42
43
44
45
46
47
48
49
50
class Solution {
//    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//        if (root == null) return null;
//        if (root == p || root == q) return root;
//        TreeNode left = lowestCommonAncestor(root.left, p, q);
//        TreeNode right = lowestCommonAncestor(root.right, p, q);
//        if (left == null)
//            return right;
//        else if (right == null)
//            return left;
//        else
//            return root;
//    }

    static Map<Integer, TreeNode> map;
    static Set<Integer> visited;

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        // 存储子节点的值和父节点
        map = new HashMap<>();
        visited = new HashSet<>();
        // 保存关系
        dfs(root);

        while (p != null) {
            visited.add(p.val);
            // 获取父节点
            p = map.get(p.val);
        }

        while (q != null) {
            // 第一个遇到的已经被访问过的节点就是LCA
            if (visited.contains(q.val))
                return q;
            q = map.get(q.val);
        }
        return null;
    }

    public static void dfs(TreeNode root) {
        if (root.left != null) {
            map.put(root.left.val, root);
            dfs(root.left);
        }
        if (root.right != null) {
            map.put(root.right.val, root);
            dfs(root.right);
        }
    }
}
本文由作者按照 CC BY 4.0 进行授权