comparison src/impl/hoofbaby/util/redblack.d @ 0:3425707ddbf6

Initial import (hopefully this mercurial stuff works...)
author fraserofthenight
date Mon, 06 Jul 2009 08:06:28 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:3425707ddbf6
1 /*******************************************************************************
2
3 (this module taken from tango.util.container.RedBlack, since that
4 module is package-protected)
5
6 copyright: Copyright (c) 2008 Kris Bell. All rights reserved
7
8 license: BSD style: $(LICENSE)
9
10 version: Apr 2008: Initial release
11
12 authors: Kris, tsalm
13
14 Since: 0.99.7
15
16 Based upon Doug Lea's Java collection package
17
18 *******************************************************************************/
19
20 module candy.util.redblack;
21
22 template Compare (V) { alias int function (ref V a, ref V b) Compare; }
23
24 private typedef int AttributeDummy;
25
26 /*******************************************************************************
27
28 RedBlack implements basic capabilities of Red-Black trees,
29 an efficient kind of balanced binary tree. The particular
30 algorithms used are adaptations of those in Corman,
31 Lieserson, and Rivest's <EM>Introduction to Algorithms</EM>.
32 This class was inspired by (and code cross-checked with) a
33 similar class by Chuck McManis. The implementations of
34 rebalancings during insertion and deletion are
35 a little trickier than those versions since they
36 don't swap Cell contents or use special dummy nilnodes.
37
38 Doug Lea
39
40 *******************************************************************************/
41
42 struct RedBlack (V, A = AttributeDummy)
43 {
44 alias RedBlack!(V, A) Type;
45 alias Type *Ref;
46
47 enum : bool {RED = false, BLACK = true}
48
49 /**
50 * Pointer to left child
51 **/
52
53 package Ref left;
54
55 /**
56 * Pointer to right child
57 **/
58
59 package Ref right;
60
61 /**
62 * Pointer to parent (null if root)
63 **/
64
65 package Ref parent;
66
67 package V value;
68
69 static if (!is(typeof(A) == AttributeDummy))
70 {
71 A attribute;
72 }
73
74 /**
75 * The node color (RED, BLACK)
76 **/
77
78 package bool color;
79
80 static if (!is(typeof(A) == AttributeDummy))
81 {
82 final Ref set (V v, A a)
83 {
84 attribute = a;
85 return set (v);
86 }
87 }
88
89 /**
90 * Make a new Cell with given value, null links, and BLACK color.
91 * Normally only called to establish a new root.
92 **/
93
94 final Ref set (V v)
95 {
96 value = v;
97 left = null;
98 right = null;
99 parent = null;
100 color = BLACK;
101 return this;
102 }
103
104 /**
105 * Return a new Ref with same value and color as self,
106 * but with null links. (Since it is never OK to have
107 * multiple identical links in a RB tree.)
108 **/
109
110 protected Ref dup (Ref delegate() alloc)
111 {
112 static if (is(typeof(A) == AttributeDummy))
113 auto t = alloc().set (value);
114 else
115 auto t = alloc().set (value, attribute);
116
117 t.color = color;
118 return t;
119 }
120
121
122 /**
123 * See_Also: tango.util.collection.model.View.View.checkImplementation.
124 **/
125 public void checkImplementation ()
126 {
127
128 // It's too hard to check the property that every simple
129 // path from node to leaf has same number of black nodes.
130 // So restrict to the following
131
132 assert(parent is null ||
133 this is parent.left ||
134 this is parent.right);
135
136 assert(left is null ||
137 this is left.parent);
138
139 assert(right is null ||
140 this is right.parent);
141
142 assert(color is BLACK ||
143 (colorOf(left) is BLACK) && (colorOf(right) is BLACK));
144
145 if (left !is null)
146 left.checkImplementation();
147 if (right !is null)
148 right.checkImplementation();
149 }
150
151 /**
152 * Return the minimum value of the current (sub)tree
153 **/
154
155 Ref leftmost ()
156 {
157 auto p = this;
158 for ( ; p.left; p = p.left) {}
159 return p;
160 }
161
162 /**
163 * Return the maximum value of the current (sub)tree
164 **/
165 Ref rightmost ()
166 {
167 auto p = this;
168 for ( ; p.right; p = p.right) {}
169 return p;
170 }
171
172 /**
173 * Return the root (parentless node) of the tree
174 **/
175 Ref root ()
176 {
177 auto p = this;
178 for ( ; p.parent; p = p.parent) {}
179 return p;
180 }
181
182 /**
183 * Return true if node is a root (i.e., has a null parent)
184 **/
185
186 bool isRoot ()
187 {
188 return parent is null;
189 }
190
191
192 /**
193 * Return the inorder successor, or null if no such
194 **/
195
196 Ref successor ()
197 {
198 if (right)
199 return right.leftmost;
200
201 auto p = parent;
202 auto ch = this;
203 while (p && ch is p.right)
204 {
205 ch = p;
206 p = p.parent;
207 }
208 return p;
209 }
210
211 /**
212 * Return the inorder predecessor, or null if no such
213 **/
214
215 Ref predecessor ()
216 {
217 if (left)
218 return left.rightmost;
219
220 auto p = parent;
221 auto ch = this;
222 while (p && ch is p.left)
223 {
224 ch = p;
225 p = p.parent;
226 }
227 return p;
228 }
229
230 /**
231 * Return the number of nodes in the subtree
232 **/
233 int size ()
234 {
235 auto c = 1;
236 if (left)
237 c += left.size;
238 if (right)
239 c += right.size;
240 return c;
241 }
242
243
244 /**
245 * Return node of current subtree containing value as value(),
246 * if it exists, else null.
247 * Uses Comparator cmp to find and to check equality.
248 **/
249
250 Ref find (V value, Compare!(V) cmp)
251 {
252 auto t = this;
253 for (;;)
254 {
255 auto diff = cmp (value, t.value);
256 if (diff is 0)
257 return t;
258 else
259 if (diff < 0)
260 t = t.left;
261 else
262 t = t.right;
263 if (t is null)
264 break;
265 }
266 return null;
267 }
268
269
270 /**
271 * Return node of subtree matching "value"
272 * or, if none found, the one just after or before
273 * if it doesn't exist, return null
274 * Uses Comparator cmp to find and to check equality.
275 **/
276 Ref findFirst (V value, Compare!(V) cmp, bool after = true)
277 {
278 auto t = this;
279 auto tLower = this;
280 auto tGreater = this;
281
282 for (;;)
283 {
284 auto diff = cmp (value, t.value);
285 if (diff is 0)
286 return t;
287 else
288 if (diff < 0)
289 {
290 tGreater = t;
291 t = t.left;
292 }
293 else
294 {
295 tLower = t;
296 t = t.right;
297 }
298 if (t is null)
299 break;
300 }
301
302 if (after)
303 {
304 if (cmp (value, tGreater.value) <= 0)
305 if (cmp (value, tGreater.value) < 0)
306 return tGreater;
307 }
308 else
309 {
310 if (cmp (value, tLower.value) >= 0)
311 if (cmp (value, tLower.value) > 0)
312 return tLower;
313 }
314
315 return null;
316 }
317
318 /**
319 * Return number of nodes of current subtree containing value.
320 * Uses Comparator cmp to find and to check equality.
321 **/
322 int count (V value, Compare!(V) cmp)
323 {
324 auto c = 0;
325 auto t = this;
326 while (t)
327 {
328 int diff = cmp (value, t.value);
329 if (diff is 0)
330 {
331 ++c;
332 if (t.left is null)
333 t = t.right;
334 else
335 if (t.right is null)
336 t = t.left;
337 else
338 {
339 c += t.right.count (value, cmp);
340 t = t.left;
341 }
342 }
343 else
344 if (diff < 0)
345 t = t.left;
346 else
347 t = t.right;
348 }
349 return c;
350 }
351
352 static if (!is(typeof(A) == AttributeDummy))
353 {
354 Ref findAttribute (A attribute, Compare!(A) cmp)
355 {
356 auto t = this;
357
358 while (t)
359 {
360 if (t.attribute == attribute)
361 return t;
362 else
363 if (t.right is null)
364 t = t.left;
365 else
366 if (t.left is null)
367 t = t.right;
368 else
369 {
370 auto p = t.left.findAttribute (attribute, cmp);
371
372 if (p !is null)
373 return p;
374 else
375 t = t.right;
376 }
377 }
378 return null; // not reached
379 }
380
381 int countAttribute (A attrib, Compare!(A) cmp)
382 {
383 int c = 0;
384 auto t = this;
385
386 while (t)
387 {
388 if (t.attribute == attribute)
389 ++c;
390
391 if (t.right is null)
392 t = t.left;
393 else
394 if (t.left is null)
395 t = t.right;
396 else
397 {
398 c += t.left.countAttribute (attribute, cmp);
399 t = t.right;
400 }
401 }
402 return c;
403 }
404
405 /**
406 * find and return a cell holding (key, element), or null if no such
407 **/
408 Ref find (V value, A attribute, Compare!(V) cmp)
409 {
410 auto t = this;
411
412 for (;;)
413 {
414 int diff = cmp (value, t.value);
415 if (diff is 0 && t.attribute == attribute)
416 return t;
417 else
418 if (diff <= 0)
419 t = t.left;
420 else
421 t = t.right;
422
423 if (t is null)
424 break;
425 }
426 return null;
427 }
428
429 }
430
431
432
433 /**
434 * Return a new subtree containing each value of current subtree
435 **/
436
437 Ref copyTree (Ref delegate() alloc)
438 {
439 auto t = dup (alloc);
440
441 if (left)
442 {
443 t.left = left.copyTree (alloc);
444 t.left.parent = t;
445 }
446
447 if (right)
448 {
449 t.right = right.copyTree (alloc);
450 t.right.parent = t;
451 }
452
453 return t;
454 }
455
456
457 /**
458 * There's no generic value insertion. Instead find the
459 * place you want to add a node and then invoke insertLeft
460 * or insertRight.
461 * <P>
462 * Insert Cell as the left child of current node, and then
463 * rebalance the tree it is in.
464 * @param Cell the Cell to add
465 * @param root, the root of the current tree
466 * Returns: the new root of the current tree. (Rebalancing
467 * can change the root!)
468 **/
469
470
471 Ref insertLeft (Ref cell, Ref root)
472 {
473 left = cell;
474 cell.parent = this;
475 return cell.fixAfterInsertion (root);
476 }
477
478 /**
479 * Insert Cell as the right child of current node, and then
480 * rebalance the tree it is in.
481 * @param Cell the Cell to add
482 * @param root, the root of the current tree
483 * Returns: the new root of the current tree. (Rebalancing
484 * can change the root!)
485 **/
486
487 Ref insertRight (Ref cell, Ref root)
488 {
489 right = cell;
490 cell.parent = this;
491 return cell.fixAfterInsertion (root);
492 }
493
494
495 /**
496 * Delete the current node, and then rebalance the tree it is in
497 * @param root the root of the current tree
498 * Returns: the new root of the current tree. (Rebalancing
499 * can change the root!)
500 **/
501
502
503 Ref remove (Ref root)
504 {
505 // handle case where we are only node
506 if (left is null && right is null && parent is null)
507 return null;
508
509 // if strictly internal, swap places with a successor
510 if (left && right)
511 {
512 auto s = successor;
513
514 // To work nicely with arbitrary subclasses of Ref, we don't want to
515 // just copy successor's fields. since we don't know what
516 // they are. Instead we swap positions _in the tree.
517 root = swapPosition (this, s, root);
518 }
519
520 // Start fixup at replacement node (normally a child).
521 // But if no children, fake it by using self
522
523 if (left is null && right is null)
524 {
525 if (color is BLACK)
526 root = this.fixAfterDeletion (root);
527
528 // Unlink (Couldn't before since fixAfterDeletion needs parent ptr)
529 if (parent)
530 {
531 if (this is parent.left)
532 parent.left = null;
533 else
534 if (this is parent.right)
535 parent.right = null;
536 parent = null;
537 }
538 }
539 else
540 {
541 auto replacement = left;
542 if (replacement is null)
543 replacement = right;
544
545 // link replacement to parent
546 replacement.parent = parent;
547
548 if (parent is null)
549 root = replacement;
550 else
551 if (this is parent.left)
552 parent.left = replacement;
553 else
554 parent.right = replacement;
555
556 left = null;
557 right = null;
558 parent = null;
559
560 // fix replacement
561 if (color is BLACK)
562 root = replacement.fixAfterDeletion (root);
563 }
564 return root;
565 }
566
567 /**
568 * Swap the linkages of two nodes in a tree.
569 * Return new root, in case it changed.
570 **/
571
572 static Ref swapPosition (Ref x, Ref y, Ref root)
573 {
574 /* Too messy. TODO: find sequence of assigments that are always OK */
575
576 auto px = x.parent;
577 bool xpl = px !is null && x is px.left;
578 auto lx = x.left;
579 auto rx = x.right;
580
581 auto py = y.parent;
582 bool ypl = py !is null && y is py.left;
583 auto ly = y.left;
584 auto ry = y.right;
585
586 if (x is py)
587 {
588 y.parent = px;
589 if (px !is null)
590 if (xpl)
591 px.left = y;
592 else
593 px.right = y;
594
595 x.parent = y;
596 if (ypl)
597 {
598 y.left = x;
599 y.right = rx;
600 if (rx !is null)
601 rx.parent = y;
602 }
603 else
604 {
605 y.right = x;
606 y.left = lx;
607 if (lx !is null)
608 lx.parent = y;
609 }
610
611 x.left = ly;
612 if (ly !is null)
613 ly.parent = x;
614
615 x.right = ry;
616 if (ry !is null)
617 ry.parent = x;
618 }
619 else
620 if (y is px)
621 {
622 x.parent = py;
623 if (py !is null)
624 if (ypl)
625 py.left = x;
626 else
627 py.right = x;
628
629 y.parent = x;
630 if (xpl)
631 {
632 x.left = y;
633 x.right = ry;
634 if (ry !is null)
635 ry.parent = x;
636 }
637 else
638 {
639 x.right = y;
640 x.left = ly;
641 if (ly !is null)
642 ly.parent = x;
643 }
644
645 y.left = lx;
646 if (lx !is null)
647 lx.parent = y;
648
649 y.right = rx;
650 if (rx !is null)
651 rx.parent = y;
652 }
653 else
654 {
655 x.parent = py;
656 if (py !is null)
657 if (ypl)
658 py.left = x;
659 else
660 py.right = x;
661
662 x.left = ly;
663 if (ly !is null)
664 ly.parent = x;
665
666 x.right = ry;
667 if (ry !is null)
668 ry.parent = x;
669
670 y.parent = px;
671 if (px !is null)
672 if (xpl)
673 px.left = y;
674 else
675 px.right = y;
676
677 y.left = lx;
678 if (lx !is null)
679 lx.parent = y;
680
681 y.right = rx;
682 if (rx !is null)
683 rx.parent = y;
684 }
685
686 bool c = x.color;
687 x.color = y.color;
688 y.color = c;
689
690 if (root is x)
691 root = y;
692 else
693 if (root is y)
694 root = x;
695 return root;
696 }
697
698
699
700 /**
701 * Return color of node p, or BLACK if p is null
702 * (In the CLR version, they use
703 * a special dummy `nil' node for such purposes, but that doesn't
704 * work well here, since it could lead to creating one such special
705 * node per real node.)
706 *
707 **/
708
709 static bool colorOf (Ref p)
710 {
711 return (p is null) ? BLACK : p.color;
712 }
713
714 /**
715 * return parent of node p, or null if p is null
716 **/
717 static Ref parentOf (Ref p)
718 {
719 return (p is null) ? null : p.parent;
720 }
721
722 /**
723 * Set the color of node p, or do nothing if p is null
724 **/
725
726 static void setColor (Ref p, bool c)
727 {
728 if (p !is null)
729 p.color = c;
730 }
731
732 /**
733 * return left child of node p, or null if p is null
734 **/
735
736 static Ref leftOf (Ref p)
737 {
738 return (p is null) ? null : p.left;
739 }
740
741 /**
742 * return right child of node p, or null if p is null
743 **/
744
745 static Ref rightOf (Ref p)
746 {
747 return (p is null) ? null : p.right;
748 }
749
750
751 /** From CLR **/
752 package Ref rotateLeft (Ref root)
753 {
754 auto r = right;
755 right = r.left;
756
757 if (r.left)
758 r.left.parent = this;
759
760 r.parent = parent;
761 if (parent is null)
762 root = r;
763 else
764 if (parent.left is this)
765 parent.left = r;
766 else
767 parent.right = r;
768
769 r.left = this;
770 parent = r;
771 return root;
772 }
773
774 /** From CLR **/
775 package Ref rotateRight (Ref root)
776 {
777 auto l = left;
778 left = l.right;
779
780 if (l.right !is null)
781 l.right.parent = this;
782
783 l.parent = parent;
784 if (parent is null)
785 root = l;
786 else
787 if (parent.right is this)
788 parent.right = l;
789 else
790 parent.left = l;
791
792 l.right = this;
793 parent = l;
794 return root;
795 }
796
797
798 /** From CLR **/
799 package Ref fixAfterInsertion (Ref root)
800 {
801 color = RED;
802 auto x = this;
803
804 while (x && x !is root && x.parent.color is RED)
805 {
806 if (parentOf(x) is leftOf(parentOf(parentOf(x))))
807 {
808 auto y = rightOf(parentOf(parentOf(x)));
809 if (colorOf(y) is RED)
810 {
811 setColor(parentOf(x), BLACK);
812 setColor(y, BLACK);
813 setColor(parentOf(parentOf(x)), RED);
814 x = parentOf(parentOf(x));
815 }
816 else
817 {
818 if (x is rightOf(parentOf(x)))
819 {
820 x = parentOf(x);
821 root = x.rotateLeft(root);
822 }
823
824 setColor(parentOf(x), BLACK);
825 setColor(parentOf(parentOf(x)), RED);
826 if (parentOf(parentOf(x)) !is null)
827 root = parentOf(parentOf(x)).rotateRight(root);
828 }
829 }
830 else
831 {
832 auto y = leftOf(parentOf(parentOf(x)));
833 if (colorOf(y) is RED)
834 {
835 setColor(parentOf(x), BLACK);
836 setColor(y, BLACK);
837 setColor(parentOf(parentOf(x)), RED);
838 x = parentOf(parentOf(x));
839 }
840 else
841 {
842 if (x is leftOf(parentOf(x)))
843 {
844 x = parentOf(x);
845 root = x.rotateRight(root);
846 }
847
848 setColor(parentOf(x), BLACK);
849 setColor(parentOf(parentOf(x)), RED);
850 if (parentOf(parentOf(x)) !is null)
851 root = parentOf(parentOf(x)).rotateLeft(root);
852 }
853 }
854 }
855 root.color = BLACK;
856 return root;
857 }
858
859
860
861 /** From CLR **/
862 package Ref fixAfterDeletion(Ref root)
863 {
864 auto x = this;
865 while (x !is root && colorOf(x) is BLACK)
866 {
867 if (x is leftOf(parentOf(x)))
868 {
869 auto sib = rightOf(parentOf(x));
870 if (colorOf(sib) is RED)
871 {
872 setColor(sib, BLACK);
873 setColor(parentOf(x), RED);
874 root = parentOf(x).rotateLeft(root);
875 sib = rightOf(parentOf(x));
876 }
877 if (colorOf(leftOf(sib)) is BLACK && colorOf(rightOf(sib)) is BLACK)
878 {
879 setColor(sib, RED);
880 x = parentOf(x);
881 }
882 else
883 {
884 if (colorOf(rightOf(sib)) is BLACK)
885 {
886 setColor(leftOf(sib), BLACK);
887 setColor(sib, RED);
888 root = sib.rotateRight(root);
889 sib = rightOf(parentOf(x));
890 }
891
892 setColor(sib, colorOf(parentOf(x)));
893 setColor(parentOf(x), BLACK);
894 setColor(rightOf(sib), BLACK);
895 root = parentOf(x).rotateLeft(root);
896 x = root;
897 }
898 }
899 else
900 {
901 auto sib = leftOf(parentOf(x));
902 if (colorOf(sib) is RED)
903 {
904 setColor(sib, BLACK);
905 setColor(parentOf(x), RED);
906 root = parentOf(x).rotateRight(root);
907 sib = leftOf(parentOf(x));
908 }
909
910 if (colorOf(rightOf(sib)) is BLACK && colorOf(leftOf(sib)) is BLACK)
911 {
912 setColor(sib, RED);
913 x = parentOf(x);
914 }
915 else
916 {
917 if (colorOf(leftOf(sib)) is BLACK)
918 {
919 setColor(rightOf(sib), BLACK);
920 setColor(sib, RED);
921 root = sib.rotateLeft(root);
922 sib = leftOf(parentOf(x));
923 }
924
925 setColor(sib, colorOf(parentOf(x)));
926 setColor(parentOf(x), BLACK);
927 setColor(leftOf(sib), BLACK);
928 root = parentOf(x).rotateRight(root);
929 x = root;
930 }
931 }
932 }
933
934 setColor(x, BLACK);
935 return root;
936 }
937 }