1 import java.util.ArrayList;
2
3 public class RBTree<E extends Comparable<E>> extends BST<E> {
4
5 public RBTree() {
6 }
7
8
9 public RBTree(E[] elements) {
10 super(elements);
11 }
12
13 @Override
14 protected RBTreeNode<E> createNewNode(E e) {
15 return new RBTreeNode<E>(e);
16 }
17
18 @Override
20 public boolean insert(E e) {
21 boolean successful = super.insert(e);
22 if (!successful)
23 return false;
24 else {
25 ensureRBTree(e);
26 }
27
28 return true;
29 }
30
31
32 private void ensureRBTree(E e) {
33
34 ArrayList<TreeNode<E>> path = path(e);
35
36 int i = path.size() - 1;
37
38
39 RBTreeNode<E> u = (RBTreeNode<E>)(path.get(i));
40
41
42 RBTreeNode<E> v = (u == root) ? null :
43 (RBTreeNode<E>)(path.get(i - 1));
44
45 u.setRed();
46
47 if (u == root)
48 u.setBlack();
49 else if (v.isRed())
50 fixDoubleRed(u, v, path, i);
51 }
52
53
54 private void fixDoubleRed(RBTreeNode<E> u, RBTreeNode<E> v,
55 ArrayList<TreeNode<E>> path, int i) {
56
57 RBTreeNode<E> w = (RBTreeNode<E>)(path.get(i - 2));
58 RBTreeNode<E> parentOfw = (w == root) ? null :
59 (RBTreeNode<E>)path.get(i - 3);
60
61
62 RBTreeNode<E> x = (w.left == v) ?
63 (RBTreeNode<E>)(w.right) : (RBTreeNode<E>)(w.left);
64
65 if (x == null || x.isBlack()) {
66
67 if (w.left == v && v.left == u) {
68
69 restructureRecolor(u, v, w, w, parentOfw);
70
71 w.left = v.right;
72 v.right = w;
73 }
74 else if (w.left == v && v.right == u) {
75
76 restructureRecolor(v, u, w, w, parentOfw);
77 v.right = u.left;
78 w.left = u.right;
79 u.left = v;
80 u.right = w;
81 }
82 else if (w.right == v && v.right == u) {
83
84 restructureRecolor(w, v, u, w, parentOfw);
85 w.right = v.left;
86 v.left = w;
87 }
88 else {
89
90 restructureRecolor(w, u, v, w, parentOfw);
91 w.right = u.left;
92 v.left = u.right;
93 u.left = w;
94 u.right = v;
95 }
96 }
97 else {
98
99 w.setRed();
100 u.setRed();
101 ((RBTreeNode<E>)(w.left)).setBlack();
102 ((RBTreeNode<E>)(w.right)).setBlack();
103
104 if (w == root) {
105 w.setBlack();
106 }
107 else if (((RBTreeNode<E>)parentOfw).isRed()) {
108
109 u = w;
110 v = (RBTreeNode<E>)parentOfw;
111 fixDoubleRed(u, v, path, i - 2);
112 }
113 }
114 }
115
116
117 private void restructureRecolor(RBTreeNode<E> a, RBTreeNode<E> b,
118 RBTreeNode<E> c, RBTreeNode<E> w, RBTreeNode<E> parentOfw) {
119 if (parentOfw == null)
120 root = b;
121 else if (parentOfw.left == w)
122 parentOfw.left = b;
123 else
124 parentOfw.right = b;
125
126 b.setBlack();
127 a.setRed();
128 c.setRed();
129 }
130
131 @Override
134 public boolean delete(E e) {
135
136 TreeNode<E> current = root;
137 while (current != null) {
138 if (e.compareTo(current.element) < 0) {
139 current = current.left;
140 }
141 else if (e.compareTo(current.element) > 0) {
142 current = current.right;
143 }
144 else
145 break;
146 }
147
148 if (current == null)
149 return false;
150
151 java.util.ArrayList<TreeNode<E>> path;
152
153
154 if (current.left != null && current.right != null) {
155
156 TreeNode<E> rightMost = current.left;
157 while (rightMost.right != null) {
158 rightMost = rightMost.right;
159 }
160
161 path = path(rightMost.element);
162
163
164 current.element = rightMost.element;
165 }
166 else
167 path = path(e);
168
169
170 deleteLastNodeInPath(path);
171
172 size--;
173 return true;
174 }
175
176
177 public void deleteLastNodeInPath(ArrayList<TreeNode<E>> path) {
178 int i = path.size() - 1;
179
180 RBTreeNode<E> u = (RBTreeNode<E>)(path.get(i));
181 RBTreeNode<E> parentOfu = (u == root) ? null :
182 (RBTreeNode<E>)(path.get(i - 1));
183 RBTreeNode<E> grandparentOfu = (parentOfu == null ||
184 parentOfu == root) ? null :
185 (RBTreeNode<E>)(path.get(i - 2));
186 RBTreeNode<E> childOfu = (u.left == null) ?
187 (RBTreeNode<E>)(u.right) : (RBTreeNode<E>)(u.left);
188
189
190 connectNewParent(parentOfu, u, childOfu);
191
192
193 if (childOfu == root || u.isRed())
194 return;
195 else if (childOfu != null && childOfu.isRed())
196 childOfu.setBlack();
197 else
198
199 fixDoubleBlack(grandparentOfu, parentOfu, childOfu, path, i);
200 }
201
202
203 private void fixDoubleBlack(
204 RBTreeNode<E> grandparent, RBTreeNode<E> parent,
205 RBTreeNode<E> db, ArrayList<TreeNode<E>> path, int i) {
206
207 RBTreeNode<E> y = (parent.right == db) ?
208 (RBTreeNode<E>)(parent.left) : (RBTreeNode<E>)(parent.right);
209 RBTreeNode<E> y1 = (RBTreeNode<E>)(y.left);
210 RBTreeNode<E> y2 = (RBTreeNode<E>)(y.right);
211
212 if (y.isBlack() && y1 != null && y1.isRed()) {
213 if (parent.right == db) {
214
215 connectNewParent(grandparent, parent, y);
216 recolor(parent, y, y1);
217
218
219 parent.left = y.right;
220 y.right = parent;
221 }
222 else {
223
224 connectNewParent(grandparent, parent, y1);
225 recolor(parent, y1, y);
226
227
228 parent.right = y1.left;
229 y.left = y1.right;
230 y1.left = parent;
231 y1.right = y;
232 }
233 }
234 else if (y.isBlack() && y2 != null && y2.isRed()) {
235 if (parent.right == db) {
236
237 connectNewParent(grandparent, parent, y2);
238 recolor(parent, y2, y);
239
240
241 y.right = y2.left;
242 parent.left = y2.right;
243 y2.left = y;
244 y2.right = parent;
245 }
246 else {
247
248 connectNewParent(grandparent, parent, y);
249 recolor(parent, y, y2);
250
251
252 y.left = parent;
253 parent.right = y1;
254 }
255 }
256 else if (y.isBlack()) {
257
258 y.setRed();
259 if (parent.isRed())
260 parent.setBlack();
261 else if (parent != root) {
262
263
264 db = parent;
265 parent = grandparent;
266 grandparent =
267 (i >= 3) ? (RBTreeNode<E>)(path.get(i - 3)) : null;
268 fixDoubleBlack(grandparent, parent, db, path, i - 1);
269 }
270 }
271 else {
272 if (parent.right == db) {
273
274 parent.left = y2;
275 y.right = parent;
276 }
277 else {
278
279 parent.right = y.left;
280 y.left = parent;
281 }
282
283 parent.setRed();
284 y.setBlack();
285 connectNewParent(grandparent, parent, y);
286 fixDoubleBlack(y, parent, db, path, i - 1);
287 }
288 }
289
290
291 private void recolor(RBTreeNode<E> parent,
292 RBTreeNode<E> newParent, RBTreeNode<E> c) {
293
294 if (parent.isRed())
295 newParent.setRed();
296 else
297 newParent.setBlack();
298
299
300 parent.setBlack();
301 c.setBlack();
302 }
303
304
305 private void connectNewParent(RBTreeNode<E> grandparent,
306 RBTreeNode<E> parent, RBTreeNode<E> newParent) {
307 if (parent == root) {
308 root = newParent;
309 if (root != null)
310 newParent.setBlack();
311 }
312 else if (grandparent.left == parent)
313 grandparent.left = newParent;
314 else
315 grandparent.right = newParent;
316 }
317
318 @Override
319 protected void preorder(TreeNode<E> root) {
320 if (root == null) return;
321 System.out.print(root.element +
322 (((RBTreeNode<E>)root).isRed() ? " (red) " : " (black) "));
323 preorder(root.left);
324 preorder(root.right);
325 }
326
327
328 protected static class RBTreeNode<E extends Comparable<E>> extends
329 BST.TreeNode<E> {
330 private boolean red = true;
331
332 public RBTreeNode(E e) {
333 super(e);
334 }
335
336 public boolean isRed() {
337 return red;
338 }
339
340 public boolean isBlack() {
341 return!red;
342 }
343
344 public void setBlack() {
345 red = false;
346 }
347
348 public void setRed() {
349 red = true;
350 }
351
352 int blackHeight;
353 }
354 }