红黑树是每个节点都带有颜色属性的二叉查找树,颜色为 红色 或 黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:
- 节点是红色或黑色。
- 根是黑色。
- 所有叶子都是黑色(叶子是NIL节点)。
- 每个红色节点必须有两个黑色的子节点。(从每个叶子到根的所有路径上不能有两个连续的红色节点。)
- 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。
下面是一个具体的红黑树的图例:
旋转
旋转是一种能保持二叉搜索树性质的搜索树局部操作。其中两种旋转分别为左旋和右旋:
在某个结点 x 上进行左旋时,假设它的右孩子为y而不是树的 T.nil 结点;x为其右孩子而不是 T.nil 结点的树内任意节点。
左旋以 x 到 y 的链为“支轴”进行,使得 y 成为该子树的新的根节点,x 成为 y 的左孩子,y 的左孩子变成 x 的右孩子;右旋与此相反。
左旋代码:
1 /**
2 * 左旋
3 * 左旋示意图(对节点x进行左旋):
4 * px px
5 * / /
6 * x y
7 * / \ --(左旋)--> / \
8 * lx y x ry
9 * / \ / \
10 * ly ry lx ly
11 *
12 * @param x
13 */
14 private void leftRotate(RBTNode<T> x) {
15 RBTNode<T> y = x.right; // y是x的右节点
16
17 x.right = y.left; // 把x的左节点变为y的右节点
18 // 若y有左子节点,把y的左节点的父节点换成x
19 if (y.left != null) {
20 y.left.parent = x;
21 }
22
23 y.parent = x.parent; // y的父节点(原来是x)设为x的父节点
24
25 // 若x是根节点,y直接变根节点
26 if (x.parent == null) {
27 this.mRoot = y;
28 } else {
29 if (x.parent.left == x) {
30 x.parent.left = y; // 如果x是x父节点的左孩子,把x的父节点的左孩子指向y
31 } else {
32 x.parent.right = y; // 如果x是x父节点的右孩子,把x的父节点的右孩子指向y
33 }
34 }
35
36 y.left = x; // 将y的左节点指向x
37 x.parent = y; // 将x的父节点设为y
38 }
右旋代码:
1 /**
2 * 右旋,操作和左旋相反
3 * 右旋示意图(对节点y进行左旋):
4 * py py
5 * / /
6 * y x
7 * / \ --(右旋)--> / \
8 * x ry lx y
9 * / \ / \
10 * lx rx rx ry
11 *
12 * @param y
13 */
14 private void rightRotate(RBTNode<T> y) {
15 RBTNode<T> x = y.left; // y的左孩子
16
17 y.left = x.right;
18 if (x.right != null) {
19 x.right.parent = y;
20 }
21
22 x.parent = y.parent;
23
24 if (y.parent == null) {
25 this.mRoot = x;
26 } else {
27 if (y.parent.left == y) {
28 y.parent.left = x;
29 } else {
30 y.parent.right = x;
31 }
32 }
33
34 x.right = y;
35 y.parent = x;
36 }
红黑树新结点插入代码:
就像一个普通的二叉搜索树一样,将新结点插入树中,并将其着为红色。之后为了能保证红黑的性质,还需要一个辅助代码对结点重新着色并且旋转。
1 /**
2 * 插入操作
3 *
4 * @param node
5 */
6 private void insert(RBTNode<T> node) {
7 int result;
8 RBTNode<T> y = null;
9 RBTNode<T> x = this.mRoot;
10
11 // 查找树中插入点的父结点y的位置
12 while (x != null) {
13 y = x; // 注意这里,y不是空的
14 result = node.key.compareTo(x.key);
15 if (result < 0) {
16 x = x.left;
17 } else {
18 x = x.right;
19 }
20 }
21
22 node.parent = y;
23 if (y != null) {
24 result = node.key.compareTo(y.key);
25 if (result < 0) {
26 y.left = node;
27 } else {
28 y.right = node;
29 }
30 } else {
31 this.mRoot = node;
32 }
33
34 node.color = RED;
35
36 // 插入后修正树
37 insertFixUp(node);
38 }
辅助修正函数:
1 /**
2 * 红黑树插入修正函数
3 *
4 * @param node
5 */
6 private void insertFixUp(RBTNode<T> node) {
7 RBTNode<T> parent, gparent; // 父节点,祖父节点
8
9 while (((parent = parentOf(node)) != null) && isRed(parent)) {
10 gparent = parentOf(parent);
11
12 // 父节点是祖父节点的左孩子
13 if (parent == gparent.left) {
14 RBTNode<T> uncle = gparent.right; // 叔叔节点,祖父的右节点
15
16 // ① 叔叔节点是红色的
17 if ((uncle != null) && isRed(uncle)) {
18 node.setColor(BLACK);
19 parent.setColor(BLACK);
20 gparent.setColor(RED);
21 node = gparent;
22 continue;
23 }
24
25 // ② 叔叔是黑色,且当前节点是右孩子
26 if (parent.right == node) {
27 RBTNode<T> tmp;
28 leftRotate(parent);
29 tmp = parent;
30 parent = node;
31 node = tmp;
32 }
33
34 // ③ 叔叔是黑色,且当前节点是左孩子
35 parent.setColor(BLACK);
36 gparent.setColor(RED);
37 rightRotate(gparent);
38
39 } else { // 父节点是祖父节点的右孩子
40
41 RBTNode<T> uncle = gparent.left; // 叔叔节点,祖父的左节点
42
43 // ① 叔叔节点是红色的
44 if ((uncle != null) && isRed(uncle)) {
45 uncle.setColor(BLACK);
46 parent.setColor(BLACK);
47 gparent.setColor(RED);
48 node = gparent;
49 continue;
50 }
51
52 // ② 叔叔是黑色,且当前节点是左孩子
53 if (parent.left == node) {
54 RBTNode<T> tmp;
55 rightRotate(parent);
56 tmp = parent;
57 parent = node;
58 node = tmp;
59 }
60
61 // ③ 叔叔是黑色,且当前节点是右孩子
62 parent.setColor(BLACK);
63 gparent.setColor(RED);
64 leftRotate(gparent);
65 }
66 }
67
68 this.mRoot.setColor(BLACK);
69 }
修正过程实例:
以下图中的 z 为插入后的结点,y 表示叔结点uncle,图中的每个子树的低端的节点是红黑树代码中的边界,边界中每个节点有黑色的哨兵没有画出来。
下面是介绍的是上面代码中 父节点是祖父节点的左孩子 的代码。
先看图中的第一个树,插入的 z 结点和 z.parent 父节点都是 RED,这违反了性质四。
情况 1(得到的是图中的第二个树):由于图中的第一个树中叔结点是红色,z 结点和 z.parent 父节点都是 RED,结点都要被重新着色,并沿着指针 z 上升;
情况 2(得到的是图中的第三个树):由于图中的第二个树中 z 及其父节点 z.parent 都为红色,其叔结点为黑色,左旋父节点 z.parent后得到;
情况 3(得到的是图中的第四个树):z 是其父节点的左孩子,重新着色后右旋的到图中的第四个树,这样之后就是合法的红黑树了。
分析红黑树的插入时间复杂度:
一颗具有 n 个节点的红黑树高度为O(log n),则按照一个普通的二叉查找树的方式插入结点需要花费 O(log n);修正代码中,当情况 1发生,指针 z沿着树上升2层,才会执行 while 循环,while 循环可能执行的总次数为 O(log n)。所以红黑树的插入的总的时间复杂度为 O(log n)。此外,插入算法中总的来说旋转次数不超过 2 次。
红黑树的删除:
1 /**
2 * 删除树中某个节点
3 *
4 * @param node 要删除的结点
5 */
6 private void remove(RBTNode<T> node) {
7 RBTNode<T> child, parent;
8 boolean color;
9
10 // 要删除的结点node有2个子结点
11 if ((node.left != null) && (node.right != null)) {
12 RBTNode<T> replace = node;
13
14 // 寻找后继结点
15 replace = replace.right;
16 while (replace.left != null) {
17 replace = replace.left;
18 }
19
20 // 判断删除的结点是不是根结点
21 if (parentOf(node) != null) {
22 if (parentOf(node).left == node) {
23 parentOf(node).left = replace;
24 } else {
25 parentOf(node).right = replace;
26 }
27 } else {
28 this.mRoot = replace;
29 }
30
31
32 child = replace.right; // 后继结点的右孩子?左孩子呢?左孩子有早就是后继结点了,所以直接看后继结点还有没有右孩子
33 parent = parentOf(replace); // 后继结点的父结点
34 color = replace.color; // 后继结点的颜色
35
36 // 要删除的结点node是后继结点的父结点
37 if (parent == node) {
38 parent = replace; // 这里应该后继结点直接替换node,留下后继结点的右子树
39 } else { // 后继结点的父结点不是要删除的结点node
40 // 后继结点的孩子不为空
41 if (child != null)
42 child.setParent(parent); // 把<后继结点的右孩子>的<父结点>设为<后继结点的父结点>
43 parent.left = child; // <后继结点的父结点>的<左孩子>指向<后继结点的右孩子>
44
45 replace.right = node.right; // 后继结点的右孩子指向删除结点的右子树
46 node.right.setParent(replace); //删除结点的右子树的父结点设置为后继结点
47 }
48
49 replace.parent = node.parent;
50 replace.color = node.color;
51 replace.left = node.left;
52 node.left.parent = replace;
53
54 if (color == BLACK)
55 removeFixup(child, parent);
56
57 node = null;
58
59 return;
60 }
61
62 // 选一个要删除的结点的孩子
63 if (node.left != null) {
64 child = node.left;
65 } else {
66 child = node.right;
67 }
68
69 parent = node.parent;
70 color = node.color;
71
72 // 要删除的结点的孩子不为空
73 if (child != null)
74 child.parent = parent;
75
76 // 要删除的结点的父结点是不是树根
77 if (parent != null) {
78 if (parent.left == node) {
79 parent.left = child;
80 } else {
81 parent.right = child;
82 }
83 } else {
84 this.mRoot = child;
85 }
86
87 if (color == BLACK)
88 removeFixup(child, parent);
89
90 node = null;
91 }
删除修正函数:
1 /**
2 * 删除修正函数
3 *
4 * @param x
5 * @param parent
6 */
7 private void removeFixup(RBTNode<T> x, RBTNode<T> parent) {
8 RBTNode<T> w;
9
10 while ((x == null || isBlack(x)) && (x != this.mRoot)) {
11 if (parent.left == x) {
12 w = parent.right;
13
14 // ① x的兄弟结点w是红色的
15 if (isRed(w)) {
16 w.setColor(BLACK); // w染黑
17 parent.setColor(RED);
18 leftRotate(parent);
19 w = parent.right;
20 }
21
22 // ② x的兄弟结点w是黑色的,而且w的两个孩子结点都是黑色的
23 if ((w.left == null || isBlack(w.left)) &&
24 (w.right == null || isBlack(w.right))) {
25 w.setColor(RED);
26 x = parent;
27 parent = parentOf(x);
28
29 } else {
30
31 // ③ x的兄弟结点w是黑色的,w的右孩子是黑色的,w的左孩子是红色的
32 if ((w.right == null || isBlack(w.right)) &&
33 (w.left == null || isBlack(w.left))) {
34 w.left.setColor(BLACK);
35 w.setColor(RED);
36 rightRotate(w);
37 w = parent.right;
38 }
39
40 // ④ x的兄弟结点w是黑色的,w的右孩子是红色的
41 w.setColor(parent.color);
42 parent.setColor(BLACK);
43 w.right.setColor(BLACK);
44 leftRotate(parent);
45 x = this.mRoot;
46
47 break;
48 }
49
50 } else {
51
52 w = parent.left;
53 // ① x的兄弟结点w是红色的
54 if (isRed(w)) {
55 w.setColor(BLACK);
56 parent.setColor(RED);
57 rightRotate(parent);
58 w = parent.left;
59 }
60
61 // ② x的兄弟结点w是黑色的,而且w的两个孩子结点都是黑色的
62 if ((w.left == null || isBlack(w.left)) &&
63 (w.right == null || isBlack(w.right))) {
64 w.setColor(RED);
65 x = parent;
66 parent = parentOf(x);
67 } else {
68
69 // ③ x的兄弟结点w是黑色的,w的右孩子是黑色的,w的左孩子是红色的
70 if (w.left == null || isBlack(w.left)) {
71 w.right.setColor(BLACK);
72 w.setColor(RED);
73 leftRotate(w);
74 w = parent.left;
75 }
76
77 // ④ x的兄弟结点w是黑色的,w的右孩子是红色的
78 w.setColor(parent.color);
79 parent.setColor(BLACK);
80 w.left.setColor(BLACK);
81 rightRotate(parent);
82 x = this.mRoot;
83
84 break;
85 }
86 }
87 }
88
89 if (x != null)
90 x.setColor(BLACK);
91 }
红黑树总的代码(包含测试代码):
1 package tree;
2
3 /**
4 * @program: MyPractice
5 * @description: 红黑树
6 * @author: Mr.Wu
7 * @create: 2019-08-28 17:19
8 **/
9 public class RBTree<T extends Comparable<T>> {
10 // 根节点
11 private RBTNode<T> mRoot;
12
13 private static final boolean RED = false;
14 private static final boolean BLACK = true;
15
16 private static final int a[] = {10, 40, 30, 60, 90, 70, 20, 50, 80};
17 private static final boolean mDebugInsert = false;
18 private static final boolean mDebugDelete = true;
19
20 /**
21 * 左旋
22 * 左旋示意图(对节点x进行左旋):
23 * px px
24 * / /
25 * x y
26 * / \ --(左旋)--> / \
27 * lx y x ry
28 * / \ / \
29 * ly ry lx ly
30 *
31 * @param x
32 */
33 private void leftRotate(RBTNode<T> x) {
34 RBTNode<T> y = x.right; // y是x的右节点
35
36 x.right = y.left; // 把y的左节点变为x的右节点
37 // 若y有左子节点,把y的左节点的父节点换成x
38 if (y.left != null) {
39 y.left.parent = x;
40 }
41
42 y.parent = x.parent; // y的父节点(原来是x)设为x的父节点
43
44 // 若x是根节点,y直接变根节点
45 if (x.parent == null) {
46 this.mRoot = y;
47 } else {
48 if (x.parent.left == x) {
49 x.parent.left = y; // 如果x是x父节点的左孩子,把x的父节点的左孩子指向y
50 } else {
51 x.parent.right = y; // 如果x是x父节点的右孩子,把x的父节点的右孩子指向y
52 }
53 }
54
55 y.left = x; // 将y的左节点指向x
56 x.parent = y; // 将x的父节点设为y
57 }
58
59 /**
60 * 右旋,操作和左旋相反
61 * 右旋示意图(对节点y进行左旋):
62 * py py
63 * / /
64 * y x
65 * / \ --(右旋)--> / \
66 * x ry lx y
67 * / \ / \
68 * lx rx rx ry
69 *
70 * @param y
71 */
72 private void rightRotate(RBTNode<T> y) {
73 RBTNode<T> x = y.left; // y的左孩子
74
75 y.left = x.right;
76 if (x.right != null) {
77 x.right.parent = y;
78 }
79
80 x.parent = y.parent;
81
82 if (y.parent == null) {
83 this.mRoot = x;
84 } else {
85 if (y.parent.left == y) {
86 y.parent.left = x;
87 } else {
88 y.parent.right = x;
89 }
90 }
91
92 x.right = y;
93 y.parent = x;
94 }
95
96 /**
97 * 插入结点
98 *
99 * @param key
100 */
101 public void insert(T key) {
102 RBTNode<T> node = new RBTNode<>(BLACK, key, null, null, null);
103 if (node != null) {
104 insert(node);
105 }
106 }
107
108 /**
109 * 插入操作
110 *
111 * @param node
112 */
113 private void insert(RBTNode<T> node) {
114 int result;
115 RBTNode<T> y = null;
116 RBTNode<T> x = this.mRoot;
117
118 // 查找树中插入点的父结点y的位置
119 while (x != null) {
120 y = x; // 注意这里,y不是空的
121 result = node.key.compareTo(x.key);
122 if (result < 0) {
123 x = x.left;
124 } else {
125 x = x.right;
126 }
127 }
128
129 node.parent = y;
130 if (y != null) {
131 result = node.key.compareTo(y.key);
132 if (result < 0) {
133 y.left = node;
134 } else {
135 y.right = node;
136 }
137 } else {
138 this.mRoot = node;
139 }
140
141 node.color = RED;
142
143 // 插入后修正树
144 insertFixUp(node);
145 }
146
147 /**
148 * 红黑树插入修正函数
149 *
150 * @param node
151 */
152 private void insertFixUp(RBTNode<T> node) {
153 RBTNode<T> parent, gparent; // 父节点 与 祖父节点
154
155 while (((parent = parentOf(node)) != null) && isRed(parent)) {
156 gparent = parentOf(parent);
157
158 // 父节点是祖父节点的左孩子
159 if (parent == gparent.left) {
160 RBTNode<T> uncle = gparent.right; // 叔叔节点,祖父的右节点
161
162 // ① 叔叔节点是红色的
163 if ((uncle != null) && isRed(uncle)) {
164 node.setColor(BLACK);
165 parent.setColor(BLACK);
166 gparent.setColor(RED);
167 node = gparent;
168 continue;
169 }
170
171 // ② 叔叔是黑色,且当前节点是右孩子
172 if (parent.right == node) {
173 RBTNode<T> tmp;
174 leftRotate(parent);
175 tmp = parent;
176 parent = node;
177 node = tmp;
178 }
179
180 // ③ 叔叔是黑色,且当前节点是左孩子
181 parent.setColor(BLACK);
182 gparent.setColor(RED);
183 rightRotate(gparent);
184
185 } else { // 父节点是祖父节点的右孩子
186
187 RBTNode<T> uncle = gparent.left; // 叔叔节点,祖父的左节点
188
189 // ① 叔叔节点是红色的
190 if ((uncle != null) && isRed(uncle)) {
191 uncle.setColor(BLACK);
192 parent.setColor(BLACK);
193 gparent.setColor(RED);
194 node = gparent;
195 continue;
196 }
197
198 // ② 叔叔是黑色,且当前节点是左孩子
199 if (parent.left == node) {
200 RBTNode<T> tmp;
201 rightRotate(parent);
202 tmp = parent;
203 parent = node;
204 node = tmp;
205 }
206
207 // ③ 叔叔是黑色,且当前节点是右孩子
208 parent.setColor(BLACK);
209 gparent.setColor(RED);
210 leftRotate(gparent);
211 }
212 }
213
214 this.mRoot.setColor(BLACK);
215 }
216
217 /**
218 * 删除树中某个值
219 *
220 * @param key
221 */
222 public void remove(T key) {
223 RBTNode<T> node;
224
225 if ((node = search(mRoot, key)) != null)
226 remove(node);
227 }
228
229 /**
230 * 删除树中某个节点
231 *
232 * @param node 要删除的结点
233 */
234 private void remove(RBTNode<T> node) {
235 RBTNode<T> child, parent;
236 boolean color;
237
238 // 要删除的结点node有2个子结点
239 if ((node.left != null) && (node.right != null)) {
240 RBTNode<T> replace = node;
241
242 // 寻找后继结点
243 replace = replace.right;
244 while (replace.left != null) {
245 replace = replace.left;
246 }
247
248 // 判断删除的结点是不是根结点
249 if (parentOf(node) != null) {
250 if (parentOf(node).left == node) {
251 parentOf(node).left = replace;
252 } else {
253 parentOf(node).right = replace;
254 }
255 } else {
256 this.mRoot = replace;
257 }
258
259
260 child = replace.right; // 后继结点的右孩子?左孩子呢?左孩子有早就是后继结点了,所以直接看后继结点还有没有右孩子
261 parent = parentOf(replace); // 后继结点的父结点
262 color = replace.color; // 后继结点的颜色
263
264 // 要删除的结点node是后继结点的父结点
265 if (parent == node) {
266 parent = replace; // 这里应该后继结点直接替换node,留下后继结点的右子树
267 } else { // 后继结点的父结点不是要删除的结点node
268 // 后继结点的孩子不为空
269 if (child != null)
270 child.setParent(parent); // 把<后继结点的右孩子>的<父结点>设为<后继结点的父结点>
271 parent.left = child; // <后继结点的父结点>的<左孩子>指向<后继结点的右孩子>
272
273 replace.right = node.right; // 后继结点的右孩子指向删除结点的右子树
274 node.right.setParent(replace); //删除结点的右子树的父结点设置为后继结点
275 }
276
277 replace.parent = node.parent;
278 replace.color = node.color;
279 replace.left = node.left;
280 node.left.parent = replace;
281
282 if (color == BLACK)
283 removeFixup(child, parent);
284
285 node = null;
286
287 return;
288 }
289
290 // 选一个要删除的结点的孩子
291 if (node.left != null) {
292 child = node.left;
293 } else {
294 child = node.right;
295 }
296
297 parent = node.parent;
298 color = node.color;
299
300 // 要删除的结点的孩子不为空
301 if (child != null)
302 child.parent = parent;
303
304 // 要删除的结点的父结点是不是树根
305 if (parent != null) {
306 if (parent.left == node) {
307 parent.left = child;
308 } else {
309 parent.right = child;
310 }
311 } else {
312 this.mRoot = child;
313 }
314
315 if (color == BLACK)
316 removeFixup(child, parent);
317
318 node = null;
319 }
320
321 /**
322 * 删除修正函数
323 *
324 * @param x
325 * @param parent
326 */
327 private void removeFixup(RBTNode<T> x, RBTNode<T> parent) {
328 RBTNode<T> w;
329
330 while ((x == null || isBlack(x)) && (x != this.mRoot)) {
331 if (parent.left == x) {
332 w = parent.right;
333
334 // ① x的兄弟结点w是红色的
335 if (isRed(w)) {
336 w.setColor(BLACK); // w染黑
337 parent.setColor(RED);
338 leftRotate(parent);
339 w = parent.right;
340 }
341
342 // ② x的兄弟结点w是黑色的,而且w的两个孩子结点都是黑色的
343 if ((w.left == null || isBlack(w.left)) &&
344 (w.right == null || isBlack(w.right))) {
345 w.setColor(RED);
346 x = parent;
347 parent = parentOf(x);
348
349 } else {
350
351 // ③ x的兄弟结点w是黑色的,w的右孩子是黑色的,w的左孩子是红色的
352 if ((w.right == null || isBlack(w.right)) &&
353 (w.left == null || isBlack(w.left))) {
354 w.left.setColor(BLACK);
355 w.setColor(RED);
356 rightRotate(w);
357 w = parent.right;
358 }
359
360 // ④ x的兄弟结点w是黑色的,w的右孩子是红色的
361 w.setColor(parent.color);
362 parent.setColor(BLACK);
363 w.right.setColor(BLACK);
364 leftRotate(parent);
365 x = this.mRoot;
366
367 break;
368 }
369
370 } else {
371
372 w = parent.left;
373 // ① x的兄弟结点w是红色的
374 if (isRed(w)) {
375 w.setColor(BLACK);
376 parent.setColor(RED);
377 rightRotate(parent);
378 w = parent.left;
379 }
380
381 // ② x的兄弟结点w是黑色的,而且w的两个孩子结点都是黑色的
382 if ((w.left == null || isBlack(w.left)) &&
383 (w.right == null || isBlack(w.right))) {
384 w.setColor(RED);
385 x = parent;
386 parent = parentOf(x);
387 } else {
388
389 // ③ x的兄弟结点w是黑色的,w的右孩子是黑色的,w的左孩子是红色的
390 if (w.left == null || isBlack(w.left)) {
391 w.right.setColor(BLACK);
392 w.setColor(RED);
393 leftRotate(w);
394 w = parent.left;
395 }
396
397 // ④ x的兄弟结点w是黑色的,w的右孩子是红色的
398 w.setColor(parent.color);
399 parent.setColor(BLACK);
400 w.left.setColor(BLACK);
401 rightRotate(parent);
402 x = this.mRoot;
403
404 break;
405 }
406 }
407 }
408
409 if (x != null)
410 x.setColor(BLACK);
411 }
412
413 private boolean isRed(RBTNode<T> node) {
414 return (node != null) && (node.color == RED);
415 }
416
417 private boolean isBlack(RBTNode<T> node) {
418 return !isRed(node);
419 }
420
421 /**
422 * 二叉查找,递归
423 *
424 * @param x
425 * @param key
426 * @return
427 */
428 private RBTNode<T> search(RBTNode<T> x, T key) {
429 if (x == null)
430 return x;
431
432 int result = key.compareTo(x.key);
433 if (result < 0) {
434 return search(x.left, key);
435 } else if (result > 0) {
436 return search(x.right, key);
437 } else {
438 return x;
439 }
440 }
441
442 /**
443 * 找结点的父节点
444 *
445 * @param node
446 * @return
447 */
448 private RBTNode<T> parentOf(RBTNode<T> node) {
449 return (node != null) ? node.parent : null;
450 }
451
452 /**
453 * 置空树
454 */
455 public void clear() {
456 destroy(mRoot);
457 mRoot = null;
458 }
459
460 /**
461 * 销毁树
462 *
463 * @param tree
464 */
465 private void destroy(RBTNode<T> tree) {
466 if (tree == null) {
467 return;
468 }
469 if (tree.left != null) {
470 destroy(tree.left);
471 }
472 if (tree.right != null) {
473 destroy(tree.right);
474 }
475
476 tree = null;
477 }
478
479 /**
480 * 先序遍历
481 */
482 public void preOrder() {
483 preOrder(mRoot);
484 }
485
486 /**
487 * 先序遍历
488 *
489 * @param tree
490 */
491 private void preOrder(RBTNode<T> tree) {
492 if (tree != null) {
493 System.out.print(tree.key + " ");
494 preOrder(tree.left);
495 preOrder(tree.right);
496 }
497 }
498
499 public void inOrder() {
500 inOrder(mRoot);
501 }
502
503 /**
504 * 中序遍历
505 *
506 * @param tree
507 */
508 private void inOrder(RBTNode<T> tree) {
509 if (tree != null) {
510 inOrder(tree.left);
511 System.out.print(tree.key + " ");
512 inOrder(tree.right);
513 }
514 }
515
516 /**
517 * 后序遍历
518 */
519 public void postOrder() {
520 postOrder(mRoot);
521 }
522
523 /**
524 * 后序遍历
525 *
526 * @param tree
527 */
528 private void postOrder(RBTNode<T> tree) {
529 if (tree != null) {
530 postOrder(tree.left);
531 postOrder(tree.right);
532 System.out.print(tree.key + " ");
533 }
534 }
535
536 /**
537 * 打印树的信息
538 */
539 public void print() {
540 if (mRoot != null) {
541 print(mRoot, mRoot.key, 0);
542 }
543 }
544
545 /**
546 * 打印树的详细信息
547 *
548 * @param tree
549 * @param key
550 * @param direction
551 */
552 private void print(RBTNode<T> tree, T key, int direction) {
553 if (tree != null) {
554 if (direction == 0) {
555 System.out.printf("%2d(B) is root\n", tree.key);
556 } else {
557 System.out.printf("%2d(%s) is %2d's %6s child\n", tree.key, isRed(tree) ? "R" : "B",
558 key, direction == 1 ? "right" : "left");
559 }
560 print(tree.left, tree.key, -1);
561 print(tree.right, tree.key, 1);
562 }
563 }
564
565 /**
566 * 找树中值最大的结点
567 *
568 * @param tree
569 * @return
570 */
571 private RBTNode<T> maximum(RBTNode<T> tree) {
572 if (tree == null)
573 return null;
574 while (tree.right != null)
575 tree = tree.right;
576 return null;
577 }
578
579 /**
580 * 找树中值最大的结点
581 *
582 * @return
583 */
584 public T maximum() {
585 RBTNode<T> p = maximum(mRoot);
586 if (p != null)
587 return p.key;
588 return null;
589 }
590
591 /**
592 * 找树中值最小的结点
593 *
594 * @param tree
595 * @return
596 */
597 private RBTNode<T> minimum(RBTNode<T> tree) {
598 if (tree == null)
599 return null;
600 while (tree.left != null)
601 tree = tree.left;
602 return tree;
603 }
604
605 /**
606 * 找树中值最小的结点
607 */
608 public T minimum() {
609 RBTNode<T> p = minimum(mRoot);
610 if (p != null)
611 return p.key;
612 return null;
613 }
614
615 /**
616 * 测试主函数
617 * @param args
618 */
619 public static void main(String[] args) {
620 int i, length = a.length;
621 RBTree<Integer> tree = new RBTree<>();
622
623 System.out.printf("== 原始数据: ");
624 for (i = 0; i < length; i++)
625 System.out.printf("%d ", a[i]);
626 System.out.printf("\n");
627
628 for (i = 0; i < length; i++) {
629 tree.insert(a[i]);
630 // 设置mDebugInsert=true,测试"添加函数"
631 if (mDebugInsert) {
632 System.out.printf("== 添加节点: %d\n", a[i]);
633 System.out.printf("== 树的详细信息: \n");
634 tree.print();
635 System.out.printf("\n");
636 }
637 }
638
639 System.out.printf("== 前序遍历: ");
640 tree.preOrder();
641
642 System.out.printf("\n== 中序遍历: ");
643 tree.inOrder();
644
645 System.out.printf("\n== 后序遍历: ");
646 tree.postOrder();
647
648 System.out.printf("\n");
649
650 System.out.printf("== 最小值: %s\n", tree.minimum());
651 System.out.printf("== 最大值: %s\n", tree.maximum());
652 System.out.printf("== 树的详细信息: \n");
653 tree.print();
654
655 System.out.printf("\n");
656
657 // 设置mDebugDelete=true,测试"删除函数"
658 if (mDebugDelete) {
659 for (i = 0; i < length; i++) {
660 tree.remove(a[i]);
661
662 System.out.printf("== 删除节点: %d\n", a[i]);
663 System.out.printf("== 树的详细信息: \n");
664 tree.print();
665
666 System.out.printf("\n");
667 }
668 }
669
670 // 销毁二叉树
671 tree.clear();
672 }
673
674 /** 红黑树结点 RBTNode **/
675 public class RBTNode<T extends Comparable<T>> {
676 boolean color; // 颜色
677 T key; // 关键字
678 RBTNode<T> left;
679 RBTNode<T> right;
680 RBTNode<T> parent;
681
682 public RBTNode(boolean color, T key, RBTNode<T> left, RBTNode<T> right, RBTNode<T> parent) {
683 this.color = color;
684 this.key = key;
685 this.left = left;
686 this.right = right;
687 this.parent = parent;
688 }
689
690 public boolean isColor() {
691 return color;
692 }
693
694 public void setColor(boolean color) {
695 this.color = color;
696 }
697
698 public T getKey() {
699 return key;
700 }
701
702 public void setKey(T key) {
703 this.key = key;
704 }
705
706 public RBTNode<T> getLeft() {
707 return left;
708 }
709
710 public void setLeft(RBTNode<T> left) {
711 this.left = left;
712 }
713
714 public RBTNode<T> getRight() {
715 return right;
716 }
717
718 public void setRight(RBTNode<T> right) {
719 this.right = right;
720 }
721
722 public RBTNode<T> getParent() {
723 return parent;
724 }
725
726 public void setParent(RBTNode<T> parent) {
727 this.parent = parent;
728 }
729 }
730 }
来源:oschina
链接:https://my.oschina.net/u/4309066/blog/3411427