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