Mercurial > projects > ldc
comparison tango/tango/util/collection/impl/RBCell.d @ 132:1700239cab2e trunk
[svn r136] MAJOR UNSTABLE UPDATE!!!
Initial commit after moving to Tango instead of Phobos.
Lots of bugfixes...
This build is not suitable for most things.
author | lindquist |
---|---|
date | Fri, 11 Jan 2008 17:57:40 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
131:5825d48b27d1 | 132:1700239cab2e |
---|---|
1 /* | |
2 File: RBCell.d | |
3 | |
4 Originally written by Doug Lea and released into the public domain. | |
5 Thanks for the assistance and support of Sun Microsystems Labs, Agorics | |
6 Inc, Loral, and everyone contributing, testing, and using this code. | |
7 | |
8 History: | |
9 Date Who What | |
10 24Sep95 dl@cs.oswego.edu Create from tango.util.collection.d working file | |
11 | |
12 */ | |
13 | |
14 | |
15 module tango.util.collection.impl.RBCell; | |
16 | |
17 private import tango.util.collection.impl.Cell; | |
18 | |
19 private import tango.util.collection.model.Iterator, | |
20 tango.util.collection.model.Comparator; | |
21 | |
22 /** | |
23 * RBCell implements basic capabilities of Red-Black trees, | |
24 * an efficient kind of balanced binary tree. The particular | |
25 * algorithms used are adaptations of those in Corman, | |
26 * Lieserson, and Rivest's <EM>Introduction to Algorithms</EM>. | |
27 * This class was inspired by (and code cross-checked with) a | |
28 * similar class by Chuck McManis. The implementations of | |
29 * rebalancings during insertion and deletion are | |
30 * a little trickier than those versions since they | |
31 * don't swap Cell contents or use special dummy nilnodes. | |
32 * <P> | |
33 * It is a pure implementation class. For harnesses, see: | |
34 * See_Also: RBTree | |
35 * Authors: Doug Lea | |
36 **/ | |
37 | |
38 | |
39 | |
40 | |
41 public class RBCell(T) : Cell!(T) | |
42 { | |
43 static bool RED = false; | |
44 static bool BLACK = true; | |
45 | |
46 /** | |
47 * The node color (RED, BLACK) | |
48 **/ | |
49 | |
50 package bool color_; | |
51 | |
52 /** | |
53 * Pointer to left child | |
54 **/ | |
55 | |
56 package RBCell left_; | |
57 | |
58 /** | |
59 * Pointer to right child | |
60 **/ | |
61 | |
62 package RBCell right_; | |
63 | |
64 /** | |
65 * Pointer to parent (null if root) | |
66 **/ | |
67 | |
68 private RBCell parent_; | |
69 | |
70 /** | |
71 * Make a new Cell with given element, null links, and BLACK color. | |
72 * Normally only called to establish a new root. | |
73 **/ | |
74 | |
75 public this (T element) | |
76 { | |
77 super(element); | |
78 left_ = null; | |
79 right_ = null; | |
80 parent_ = null; | |
81 color_ = BLACK; | |
82 } | |
83 | |
84 /** | |
85 * Return a new RBCell with same element and color as self, | |
86 * but with null links. (Since it is never OK to have | |
87 * multiple identical links in a RB tree.) | |
88 **/ | |
89 | |
90 protected RBCell duplicate() | |
91 { | |
92 RBCell t = new RBCell(element()); | |
93 t.color_ = color_; | |
94 return t; | |
95 } | |
96 | |
97 | |
98 /** | |
99 * Return left child (or null) | |
100 **/ | |
101 | |
102 public final RBCell left() | |
103 { | |
104 return left_; | |
105 } | |
106 | |
107 /** | |
108 * Return right child (or null) | |
109 **/ | |
110 | |
111 public final RBCell right() | |
112 { | |
113 return right_; | |
114 } | |
115 | |
116 /** | |
117 * Return parent (or null) | |
118 **/ | |
119 public final RBCell parent() | |
120 { | |
121 return parent_; | |
122 } | |
123 | |
124 | |
125 /** | |
126 * See_Also: tango.util.collection.model.View.View.checkImplementation. | |
127 **/ | |
128 public void checkImplementation() | |
129 { | |
130 | |
131 // It's too hard to check the property that every simple | |
132 // path from node to leaf has same number of black nodes. | |
133 // So restrict to the following | |
134 | |
135 assert(parent_ is null || | |
136 this is parent_.left_ || | |
137 this is parent_.right_); | |
138 | |
139 assert(left_ is null || | |
140 this is left_.parent_); | |
141 | |
142 assert(right_ is null || | |
143 this is right_.parent_); | |
144 | |
145 assert(color_ is BLACK || | |
146 (colorOf(left_) is BLACK) && (colorOf(right_) is BLACK)); | |
147 | |
148 if (left_ !is null) | |
149 left_.checkImplementation(); | |
150 if (right_ !is null) | |
151 right_.checkImplementation(); | |
152 } | |
153 | |
154 /+ | |
155 public final void assert(bool pred) | |
156 { | |
157 ImplementationError.assert(this, pred); | |
158 } | |
159 +/ | |
160 | |
161 /** | |
162 * Return the minimum element of the current (sub)tree | |
163 **/ | |
164 | |
165 public final RBCell leftmost() | |
166 { | |
167 auto p = this; | |
168 for ( ; p.left_ !is null; p = p.left_) | |
169 {} | |
170 return p; | |
171 } | |
172 | |
173 /** | |
174 * Return the maximum element of the current (sub)tree | |
175 **/ | |
176 public final RBCell rightmost() | |
177 { | |
178 auto p = this; | |
179 for ( ; p.right_ !is null; p = p.right_) | |
180 {} | |
181 return p; | |
182 } | |
183 | |
184 /** | |
185 * Return the root (parentless node) of the tree | |
186 **/ | |
187 public final RBCell root() | |
188 { | |
189 auto p = this; | |
190 for ( ; p.parent_ !is null; p = p.parent_) | |
191 {} | |
192 return p; | |
193 } | |
194 | |
195 /** | |
196 * Return true if node is a root (i.e., has a null parent) | |
197 **/ | |
198 | |
199 public final bool isRoot() | |
200 { | |
201 return parent_ is null; | |
202 } | |
203 | |
204 | |
205 /** | |
206 * Return the inorder successor, or null if no such | |
207 **/ | |
208 | |
209 public final RBCell successor() | |
210 { | |
211 if (right_ !is null) | |
212 return right_.leftmost(); | |
213 else | |
214 { | |
215 auto p = parent_; | |
216 auto ch = this; | |
217 while (p !is null && ch is p.right_) | |
218 { | |
219 ch = p; | |
220 p = p.parent_; | |
221 } | |
222 return p; | |
223 } | |
224 } | |
225 | |
226 /** | |
227 * Return the inorder predecessor, or null if no such | |
228 **/ | |
229 | |
230 public final RBCell predecessor() | |
231 { | |
232 if (left_ !is null) | |
233 return left_.rightmost(); | |
234 else | |
235 { | |
236 auto p = parent_; | |
237 auto ch = this; | |
238 while (p !is null && ch is p.left_) | |
239 { | |
240 ch = p; | |
241 p = p.parent_; | |
242 } | |
243 return p; | |
244 } | |
245 } | |
246 | |
247 /** | |
248 * Return the number of nodes in the subtree | |
249 **/ | |
250 public final int size() | |
251 { | |
252 int c = 1; | |
253 if (left_ !is null) | |
254 c += left_.size(); | |
255 if (right_ !is null) | |
256 c += right_.size(); | |
257 return c; | |
258 } | |
259 | |
260 | |
261 /** | |
262 * Return node of current subtree containing element as element(), | |
263 * if it exists, else null. | |
264 * Uses Comparator cmp to find and to check equality. | |
265 **/ | |
266 | |
267 public RBCell find(T element, Comparator!(T) cmp) | |
268 { | |
269 auto t = this; | |
270 for (;;) | |
271 { | |
272 int diff = cmp.compare(element, t.element()); | |
273 if (diff is 0) | |
274 return t; | |
275 else | |
276 if (diff < 0) | |
277 t = t.left_; | |
278 else | |
279 t = t.right_; | |
280 if (t is null) | |
281 break; | |
282 } | |
283 return null; | |
284 } | |
285 | |
286 | |
287 /** | |
288 * Return number of nodes of current subtree containing element. | |
289 * Uses Comparator cmp to find and to check equality. | |
290 **/ | |
291 public int count(T element, Comparator!(T) cmp) | |
292 { | |
293 int c = 0; | |
294 auto t = this; | |
295 while (t !is null) | |
296 { | |
297 int diff = cmp.compare(element, t.element()); | |
298 if (diff is 0) | |
299 { | |
300 ++c; | |
301 if (t.left_ is null) | |
302 t = t.right_; | |
303 else | |
304 if (t.right_ is null) | |
305 t = t.left_; | |
306 else | |
307 { | |
308 c += t.right_.count(element, cmp); | |
309 t = t.left_; | |
310 } | |
311 } | |
312 else | |
313 if (diff < 0) | |
314 t = t.left_; | |
315 else | |
316 t = t.right_; | |
317 } | |
318 return c; | |
319 } | |
320 | |
321 | |
322 | |
323 | |
324 /** | |
325 * Return a new subtree containing each element of current subtree | |
326 **/ | |
327 | |
328 public final RBCell copyTree() | |
329 { | |
330 auto t = cast(RBCell)(duplicate()); | |
331 | |
332 if (left_ !is null) | |
333 { | |
334 t.left_ = left_.copyTree(); | |
335 t.left_.parent_ = t; | |
336 } | |
337 if (right_ !is null) | |
338 { | |
339 t.right_ = right_.copyTree(); | |
340 t.right_.parent_ = t; | |
341 } | |
342 return t; | |
343 } | |
344 | |
345 | |
346 /** | |
347 * There's no generic element insertion. Instead find the | |
348 * place you want to add a node and then invoke insertLeft | |
349 * or insertRight. | |
350 * <P> | |
351 * Insert Cell as the left child of current node, and then | |
352 * rebalance the tree it is in. | |
353 * @param Cell the Cell to add | |
354 * @param root, the root of the current tree | |
355 * Returns: the new root of the current tree. (Rebalancing | |
356 * can change the root!) | |
357 **/ | |
358 | |
359 | |
360 public final RBCell insertLeft(RBCell Cell, RBCell root) | |
361 { | |
362 left_ = Cell; | |
363 Cell.parent_ = this; | |
364 return Cell.fixAfterInsertion(root); | |
365 } | |
366 | |
367 /** | |
368 * Insert Cell as the right child of current node, and then | |
369 * rebalance the tree it is in. | |
370 * @param Cell the Cell to add | |
371 * @param root, the root of the current tree | |
372 * Returns: the new root of the current tree. (Rebalancing | |
373 * can change the root!) | |
374 **/ | |
375 | |
376 public final RBCell insertRight(RBCell Cell, RBCell root) | |
377 { | |
378 right_ = Cell; | |
379 Cell.parent_ = this; | |
380 return Cell.fixAfterInsertion(root); | |
381 } | |
382 | |
383 | |
384 /** | |
385 * Delete the current node, and then rebalance the tree it is in | |
386 * @param root the root of the current tree | |
387 * Returns: the new root of the current tree. (Rebalancing | |
388 * can change the root!) | |
389 **/ | |
390 | |
391 | |
392 public final RBCell remove (RBCell root) | |
393 { | |
394 | |
395 // handle case where we are only node | |
396 if (left_ is null && right_ is null && parent_ is null) | |
397 return null; | |
398 | |
399 // if strictly internal, swap places with a successor | |
400 if (left_ !is null && right_ !is null) | |
401 { | |
402 auto s = successor(); | |
403 // To work nicely with arbitrary subclasses of RBCell, we don't want to | |
404 // just copy successor's fields. since we don't know what | |
405 // they are. Instead we swap positions _in the tree. | |
406 root = swapPosition(this, s, root); | |
407 } | |
408 | |
409 // Start fixup at replacement node (normally a child). | |
410 // But if no children, fake it by using self | |
411 | |
412 if (left_ is null && right_ is null) | |
413 { | |
414 | |
415 if (color_ is BLACK) | |
416 root = this.fixAfterDeletion(root); | |
417 | |
418 // Unlink (Couldn't before since fixAfterDeletion needs parent ptr) | |
419 | |
420 if (parent_ !is null) | |
421 { | |
422 if (this is parent_.left_) | |
423 parent_.left_ = null; | |
424 else | |
425 if (this is parent_.right_) | |
426 parent_.right_ = null; | |
427 parent_ = null; | |
428 } | |
429 | |
430 } | |
431 else | |
432 { | |
433 auto replacement = left_; | |
434 if (replacement is null) | |
435 replacement = right_; | |
436 | |
437 // link replacement to parent | |
438 replacement.parent_ = parent_; | |
439 | |
440 if (parent_ is null) | |
441 root = replacement; | |
442 else | |
443 if (this is parent_.left_) | |
444 parent_.left_ = replacement; | |
445 else | |
446 parent_.right_ = replacement; | |
447 | |
448 left_ = null; | |
449 right_ = null; | |
450 parent_ = null; | |
451 | |
452 // fix replacement | |
453 if (color_ is BLACK) | |
454 root = replacement.fixAfterDeletion(root); | |
455 | |
456 } | |
457 | |
458 return root; | |
459 } | |
460 | |
461 /** | |
462 * Swap the linkages of two nodes in a tree. | |
463 * Return new root, in case it changed. | |
464 **/ | |
465 | |
466 static final RBCell swapPosition(RBCell x, RBCell y, RBCell root) | |
467 { | |
468 | |
469 /* Too messy. TODO: find sequence of assigments that are always OK */ | |
470 | |
471 auto px = x.parent_; | |
472 bool xpl = px !is null && x is px.left_; | |
473 auto lx = x.left_; | |
474 auto rx = x.right_; | |
475 | |
476 auto py = y.parent_; | |
477 bool ypl = py !is null && y is py.left_; | |
478 auto ly = y.left_; | |
479 auto ry = y.right_; | |
480 | |
481 if (x is py) | |
482 { | |
483 y.parent_ = px; | |
484 if (px !is null) | |
485 if (xpl) | |
486 px.left_ = y; | |
487 else | |
488 px.right_ = y; | |
489 x.parent_ = y; | |
490 if (ypl) | |
491 { | |
492 y.left_ = x; | |
493 y.right_ = rx; | |
494 if (rx !is null) | |
495 rx.parent_ = y; | |
496 } | |
497 else | |
498 { | |
499 y.right_ = x; | |
500 y.left_ = lx; | |
501 if (lx !is null) | |
502 lx.parent_ = y; | |
503 } | |
504 x.left_ = ly; | |
505 if (ly !is null) | |
506 ly.parent_ = x; | |
507 x.right_ = ry; | |
508 if (ry !is null) | |
509 ry.parent_ = x; | |
510 } | |
511 else | |
512 if (y is px) | |
513 { | |
514 x.parent_ = py; | |
515 if (py !is null) | |
516 if (ypl) | |
517 py.left_ = x; | |
518 else | |
519 py.right_ = x; | |
520 y.parent_ = x; | |
521 if (xpl) | |
522 { | |
523 x.left_ = y; | |
524 x.right_ = ry; | |
525 if (ry !is null) | |
526 ry.parent_ = x; | |
527 } | |
528 else | |
529 { | |
530 x.right_ = y; | |
531 x.left_ = ly; | |
532 if (ly !is null) | |
533 ly.parent_ = x; | |
534 } | |
535 y.left_ = lx; | |
536 if (lx !is null) | |
537 lx.parent_ = y; | |
538 y.right_ = rx; | |
539 if (rx !is null) | |
540 rx.parent_ = y; | |
541 } | |
542 else | |
543 { | |
544 x.parent_ = py; | |
545 if (py !is null) | |
546 if (ypl) | |
547 py.left_ = x; | |
548 else | |
549 py.right_ = x; | |
550 x.left_ = ly; | |
551 if (ly !is null) | |
552 ly.parent_ = x; | |
553 x.right_ = ry; | |
554 if (ry !is null) | |
555 ry.parent_ = x; | |
556 | |
557 y.parent_ = px; | |
558 if (px !is null) | |
559 if (xpl) | |
560 px.left_ = y; | |
561 else | |
562 px.right_ = y; | |
563 y.left_ = lx; | |
564 if (lx !is null) | |
565 lx.parent_ = y; | |
566 y.right_ = rx; | |
567 if (rx !is null) | |
568 rx.parent_ = y; | |
569 } | |
570 | |
571 bool c = x.color_; | |
572 x.color_ = y.color_; | |
573 y.color_ = c; | |
574 | |
575 if (root is x) | |
576 root = y; | |
577 else | |
578 if (root is y) | |
579 root = x; | |
580 return root; | |
581 } | |
582 | |
583 | |
584 | |
585 /** | |
586 * Return color of node p, or BLACK if p is null | |
587 * (In the CLR version, they use | |
588 * a special dummy `nil' node for such purposes, but that doesn't | |
589 * work well here, since it could lead to creating one such special | |
590 * node per real node.) | |
591 * | |
592 **/ | |
593 | |
594 static final bool colorOf(RBCell p) | |
595 { | |
596 return (p is null) ? BLACK : p.color_; | |
597 } | |
598 | |
599 /** | |
600 * return parent of node p, or null if p is null | |
601 **/ | |
602 static final RBCell parentOf(RBCell p) | |
603 { | |
604 return (p is null) ? null : p.parent_; | |
605 } | |
606 | |
607 /** | |
608 * Set the color of node p, or do nothing if p is null | |
609 **/ | |
610 | |
611 static final void setColor(RBCell p, bool c) | |
612 { | |
613 if (p !is null) | |
614 p.color_ = c; | |
615 } | |
616 | |
617 /** | |
618 * return left child of node p, or null if p is null | |
619 **/ | |
620 | |
621 static final RBCell leftOf(RBCell p) | |
622 { | |
623 return (p is null) ? null : p.left_; | |
624 } | |
625 | |
626 /** | |
627 * return right child of node p, or null if p is null | |
628 **/ | |
629 | |
630 static final RBCell rightOf(RBCell p) | |
631 { | |
632 return (p is null) ? null : p.right_; | |
633 } | |
634 | |
635 | |
636 /** From CLR **/ | |
637 protected final RBCell rotateLeft(RBCell root) | |
638 { | |
639 auto r = right_; | |
640 right_ = r.left_; | |
641 if (r.left_ !is null) | |
642 r.left_.parent_ = this; | |
643 r.parent_ = parent_; | |
644 if (parent_ is null) | |
645 root = r; | |
646 else | |
647 if (parent_.left_ is this) | |
648 parent_.left_ = r; | |
649 else | |
650 parent_.right_ = r; | |
651 r.left_ = this; | |
652 parent_ = r; | |
653 return root; | |
654 } | |
655 | |
656 /** From CLR **/ | |
657 protected final RBCell rotateRight(RBCell root) | |
658 { | |
659 auto l = left_; | |
660 left_ = l.right_; | |
661 if (l.right_ !is null) | |
662 l.right_.parent_ = this; | |
663 l.parent_ = parent_; | |
664 if (parent_ is null) | |
665 root = l; | |
666 else | |
667 if (parent_.right_ is this) | |
668 parent_.right_ = l; | |
669 else | |
670 parent_.left_ = l; | |
671 l.right_ = this; | |
672 parent_ = l; | |
673 return root; | |
674 } | |
675 | |
676 | |
677 /** From CLR **/ | |
678 protected final RBCell fixAfterInsertion(RBCell root) | |
679 { | |
680 color_ = RED; | |
681 auto x = this; | |
682 | |
683 while (x !is null && x !is root && x.parent_.color_ is RED) | |
684 { | |
685 if (parentOf(x) is leftOf(parentOf(parentOf(x)))) | |
686 { | |
687 auto y = rightOf(parentOf(parentOf(x))); | |
688 if (colorOf(y) is RED) | |
689 { | |
690 setColor(parentOf(x), BLACK); | |
691 setColor(y, BLACK); | |
692 setColor(parentOf(parentOf(x)), RED); | |
693 x = parentOf(parentOf(x)); | |
694 } | |
695 else | |
696 { | |
697 if (x is rightOf(parentOf(x))) | |
698 { | |
699 x = parentOf(x); | |
700 root = x.rotateLeft(root); | |
701 } | |
702 setColor(parentOf(x), BLACK); | |
703 setColor(parentOf(parentOf(x)), RED); | |
704 if (parentOf(parentOf(x)) !is null) | |
705 root = parentOf(parentOf(x)).rotateRight(root); | |
706 } | |
707 } | |
708 else | |
709 { | |
710 auto y = leftOf(parentOf(parentOf(x))); | |
711 if (colorOf(y) is RED) | |
712 { | |
713 setColor(parentOf(x), BLACK); | |
714 setColor(y, BLACK); | |
715 setColor(parentOf(parentOf(x)), RED); | |
716 x = parentOf(parentOf(x)); | |
717 } | |
718 else | |
719 { | |
720 if (x is leftOf(parentOf(x))) | |
721 { | |
722 x = parentOf(x); | |
723 root = x.rotateRight(root); | |
724 } | |
725 setColor(parentOf(x), BLACK); | |
726 setColor(parentOf(parentOf(x)), RED); | |
727 if (parentOf(parentOf(x)) !is null) | |
728 root = parentOf(parentOf(x)).rotateLeft(root); | |
729 } | |
730 } | |
731 } | |
732 root.color_ = BLACK; | |
733 return root; | |
734 } | |
735 | |
736 | |
737 | |
738 /** From CLR **/ | |
739 protected final RBCell fixAfterDeletion(RBCell root) | |
740 { | |
741 auto x = this; | |
742 while (x !is root && colorOf(x) is BLACK) | |
743 { | |
744 if (x is leftOf(parentOf(x))) | |
745 { | |
746 auto sib = rightOf(parentOf(x)); | |
747 if (colorOf(sib) is RED) | |
748 { | |
749 setColor(sib, BLACK); | |
750 setColor(parentOf(x), RED); | |
751 root = parentOf(x).rotateLeft(root); | |
752 sib = rightOf(parentOf(x)); | |
753 } | |
754 if (colorOf(leftOf(sib)) is BLACK && colorOf(rightOf(sib)) is BLACK) | |
755 { | |
756 setColor(sib, RED); | |
757 x = parentOf(x); | |
758 } | |
759 else | |
760 { | |
761 if (colorOf(rightOf(sib)) is BLACK) | |
762 { | |
763 setColor(leftOf(sib), BLACK); | |
764 setColor(sib, RED); | |
765 root = sib.rotateRight(root); | |
766 sib = rightOf(parentOf(x)); | |
767 } | |
768 setColor(sib, colorOf(parentOf(x))); | |
769 setColor(parentOf(x), BLACK); | |
770 setColor(rightOf(sib), BLACK); | |
771 root = parentOf(x).rotateLeft(root); | |
772 x = root; | |
773 } | |
774 } | |
775 else | |
776 { | |
777 auto sib = leftOf(parentOf(x)); | |
778 if (colorOf(sib) is RED) | |
779 { | |
780 setColor(sib, BLACK); | |
781 setColor(parentOf(x), RED); | |
782 root = parentOf(x).rotateRight(root); | |
783 sib = leftOf(parentOf(x)); | |
784 } | |
785 if (colorOf(rightOf(sib)) is BLACK && colorOf(leftOf(sib)) is BLACK) | |
786 { | |
787 setColor(sib, RED); | |
788 x = parentOf(x); | |
789 } | |
790 else | |
791 { | |
792 if (colorOf(leftOf(sib)) is BLACK) | |
793 { | |
794 setColor(rightOf(sib), BLACK); | |
795 setColor(sib, RED); | |
796 root = sib.rotateLeft(root); | |
797 sib = leftOf(parentOf(x)); | |
798 } | |
799 setColor(sib, colorOf(parentOf(x))); | |
800 setColor(parentOf(x), BLACK); | |
801 setColor(leftOf(sib), BLACK); | |
802 root = parentOf(x).rotateRight(root); | |
803 x = root; | |
804 } | |
805 } | |
806 } | |
807 setColor(x, BLACK); | |
808 return root; | |
809 } | |
810 } | |
811 |