Featured image of post 【算法篇】树

【算法篇】树

参天大树充满生命力,根深叶茂,分枝扶疏。 它为我们展现了数据分治的生动形态。

二叉搜索树

二叉搜索树(Binary Search Tree,简称 BST)是一种很常见的二叉树,它的定义是:

对于树中的每个节点,其左子树的每个节点的值都要小于这个节点的值,右子树的每个节点的值都要大于这个节点的值。你可以简单记为「左小右大」。

我把「子树的每个节点」加粗了,这是初学者常犯的错误,不要只看子节点,而要看整棵子树的所有节点。

比方说,下面这棵树就是一棵 BST:

1
2
3
4
5
    7
   / \
  4   9
 / \   \
1   5   10

节点 7 的左子树所有节点的值都小于 7,右子树所有节点的值都大于 7;节点 4 的左子树所有节点的值都小于 4,右子树所有节点的值都大于 4,以此类推。

相反的,下面这棵树就不是 BST:

1
2
3
4
5
    7
   / \
  4   9
 / \   \
1   8   10

红黑树

后面写

二叉树的遍历方式

深度优先遍历(DFS)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
	// 节点的基本结构
    static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x) { val = x; }
    }
    
    // 深度优先遍历
    public void dfs(TreeNode root) {
        if (root == null) {
            return;
        }
        // 业务代码写在这里,就是前序遍历(根左右)
        dfs(root.left);
        // 业务代码写在这里,就是中序遍历(左根右)
        dfs(root.right);
        // 业务代码写在这里,就是后序遍历(左右根)
    }

广度优先遍历(BFS)

 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
    // 节点的基本结构
    static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x) { val = x; }
    }
    
    // 广度优先遍历
    public void bfs(TreeNode root) {
        // 这是最简单的bfs写法,缺点是没有记录层级
        if (root == null) {
            return;
        }
        // 1. 创建一个队列
        Queue<TreeNode> queue = new LinkedList<>();
        // 2. 将根节点放入队列,offer()方法是队列的入队操作,如果队列满了,返回false
        queue.offer(root);
        // 3. 循环遍历队列
        while (!queue.isEmpty()) {
            // 4. 弹出队列头部元素,poll()方法是队列的出队操作,如果队列为空,返回null
            TreeNode node = queue.poll();
            // 5. 业务代码写在这里
            System.out.println("当前节点:" + node.val);
            // 6. 将左右子节点放入队列
            if (node.left != null) {
                queue.offer(node.left);
            }
            if (node.right != null) {
                queue.offer(node.right);
            }
        }
    }
    
    public void bfs2(TreeNode root) {
        // 这是bfs的另一种写法,可以记录层级
        if (root == null) {
            return;
        }
        // 1. 创建一个队列
        Queue<TreeNode> queue = new LinkedList<>();
        // 2. 将根节点放入队列
        queue.offer(root);
        // 3. 初始化层级, 从1开始
        int depth = 1;
        // 4. 循环遍历队列
        while (!queue.isEmpty()) {
            // 5. 记录当前层级的节点个数
            int size = queue.size();
            // 6. 遍历当前层级的节点,这里要用size,因为queue.size()是变化的
            for (int i = 0; i < size; i++) {
                // 7. 弹出队列头部元素
                TreeNode node = queue.poll();
                // 8. 业务代码写在这里
                System.out.println("当前层级:" + depth + ",当前节点:" + node.val);
                // 9. 将左右子节点放入队列
                if (node.left != null) {
                    queue.offer(node.left);
                }
                if (node.right != null) {
                    queue.offer(node.right);
                }
            }
            // 10. 层级加1
            depth++;
        }
    }
使用 Hugo 构建
主题 StackJimmy 设计