返回 LeetCode 刷题

Markdown File

红黑树自顶向下插入

红黑树自顶向下插入.md

1红黑树(三)自顶向下插入
21. 前提条件
3
4自底向上插入是:
5
6先插到底
7再往上修
8
9自顶向下插入是:
10
11一边往下找插入位置
12一边提前调整
13
14目的:
15
16尽量避免插入后再一路回溯修复
17
18所以它叫:
19
20Top-Down Insertion
212. 核心思想
22
23自顶向下红黑树的核心是:
24
25向下搜索时,遇到“两个孩子都是红色”的节点,就提前变色
26
27这种节点长这样:
28
29 G(B)
30 / \
31 L(R) R(R)
32
33这相当于一个“临时的 4-节点”。
34
35处理方法:
36
37G 变红
38L 变黑
39R 变黑
40
41变成:
42
43 G(R)
44 / \
45 L(B) R(B)
46
47这叫:
48
49颜色翻转 / 拆 4-节点
503. 为什么要提前拆?
51
52因为如果不拆,等新节点插到底之后,可能会出现复杂的红红冲突。
53
54自顶向下的想法是:
55
56我还没插到底,
57但我提前把容易出问题的结构拆开。
58
59这样插入到底时,通常局部修一下就够了。
60
614. 和 2-3-4 树的关系
62
63红黑树其实可以看成:
64
652-3-4 树的二叉树表示
66
67简单理解:
68
69黑节点 + 红孩子
70可以看成一个多叉节点
71
72例如:
73
74 10(B)
75 \
76 20(R)
77
78可以理解成一个 3-节点:
79
80[10,20]
81
82如果一个黑节点有两个红孩子:
83
84 20(B)
85 / \
86 10(R) 30(R)
87
88可以理解成一个 4-节点:
89
90[10,20,30]
91
92自顶向下插入时,遇到这种 4-节点,就提前拆开。
93
945. 自顶向下基本流程
95
96插入一个新值 x:
97
98从根开始往下找插入位置
99
100while 当前节点不为空:
101
102 如果当前节点两个孩子都是红色:
103 颜色翻转
104 如果因此出现红红冲突:
105 旋转修复
106
107 根据 BST 规则往左或往右走
108
109最后插入新红节点
110
111根染黑
1126. 颜色翻转例子
113
114原来:
115
116 20(B)
117 / \
118 10(R) 30(R)
119
120向下经过 20 时发现:
121
122左右孩子都是红色
123
124于是翻转:
125
126 20(R)
127 / \
128 10(B) 30(B)
129
130如果 20 的父亲是黑色,那没事。
131
132如果 20 的父亲是红色,就出现:
133
134红父亲
135
136红20
137
138那就要旋转修复。
139
1407. 和自底向上的区别
141项目 自底向上 自顶向下
142调整时机 插入后往上修 往下找时提前修
143核心操作 看叔叔颜色 提前拆 4-节点
144是否回溯 需要 尽量不需要
145理解难度 更直观 更抽象
146
Rendered Preview

红黑树(三)自顶向下插入

  1. 前提条件

自底向上插入是:

先插到底
再往上修

自顶向下插入是:

一边往下找插入位置
一边提前调整

目的:

尽量避免插入后再一路回溯修复

所以它叫:

Top-Down Insertion
2. 核心思想

自顶向下红黑树的核心是:

向下搜索时,遇到“两个孩子都是红色”的节点,就提前变色

这种节点长这样:

    G(B)
   /    \
L(R)    R(R)

这相当于一个“临时的 4-节点”。

处理方法:

G 变红
L 变黑
R 变黑

变成:

    G(R)
   /    \
L(B)    R(B)

这叫:

颜色翻转 / 拆 4-节点
3. 为什么要提前拆?

因为如果不拆,等新节点插到底之后,可能会出现复杂的红红冲突。

自顶向下的想法是:

我还没插到底,
但我提前把容易出问题的结构拆开。

这样插入到底时,通常局部修一下就够了。

  1. 和 2-3-4 树的关系

红黑树其实可以看成:

2-3-4 树的二叉树表示

简单理解:

黑节点 + 红孩子
可以看成一个多叉节点

例如:

10(B)
  \
  20(R)

可以理解成一个 3-节点:

[10,20]

如果一个黑节点有两个红孩子:

    20(B)
   /    \
10(R)  30(R)

可以理解成一个 4-节点:

[10,20,30]

自顶向下插入时,遇到这种 4-节点,就提前拆开。

  1. 自顶向下基本流程

插入一个新值 x:

从根开始往下找插入位置

while 当前节点不为空:

如果当前节点两个孩子都是红色:
    颜色翻转
    如果因此出现红红冲突:
        旋转修复

根据 BST 规则往左或往右走

最后插入新红节点

根染黑
6. 颜色翻转例子

原来:

    20(B)
   /    \
10(R)  30(R)

向下经过 20 时发现:

左右孩子都是红色

于是翻转:

    20(R)
   /    \
10(B)  30(B)

如果 20 的父亲是黑色,那没事。

如果 20 的父亲是红色,就出现:

红父亲

红20

那就要旋转修复。

  1. 和自底向上的区别
    项目 自底向上 自顶向下
    调整时机 插入后往上修 往下找时提前修
    核心操作 看叔叔颜色 提前拆 4-节点
    是否回溯 需要 尽量不需要
    理解难度 更直观 更抽象