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