1 /**
2 This module implements a red-black tree container.
3 
4 This module is a submodule of $(MREF std, container).
5 
6 Source: $(PHOBOSSRC std/container/rbtree.d)
7 
8 Copyright: Red-black tree code copyright (C) 2008- by Steven Schveighoffer. Other code
9 copyright 2010- Andrei Alexandrescu. All rights reserved by the respective holders.
10 
11 License: Distributed under the Boost Software License, Version 1.0.
12 (See accompanying file LICENSE_1_0.txt or copy at $(HTTP
13 boost.org/LICENSE_1_0.txt)).
14 
15 Authors: Steven Schveighoffer, $(HTTP erdani.com, Andrei Alexandrescu)
16 */
17 module std.container.rbtree;
18 
19 ///
20 @safe pure unittest
21 {
22     import std.algorithm.comparison : equal;
23     import std.container.rbtree;
24 
25     auto rbt = redBlackTree(3, 1, 4, 2, 5);
26     assert(rbt.front == 1);
27     assert(equal(rbt[], [1, 2, 3, 4, 5]));
28 
29     rbt.removeKey(1, 4);
30     assert(equal(rbt[], [2, 3, 5]));
31 
32     rbt.removeFront();
33     assert(equal(rbt[], [3, 5]));
34 
35     rbt.insert([1, 2, 4]);
36     assert(equal(rbt[], [1, 2, 3, 4, 5]));
37 
38     // Query bounds in O(log(n))
39     assert(rbt.lowerBound(3).equal([1, 2]));
40     assert(rbt.equalRange(3).equal([3]));
41     assert(rbt.upperBound(3).equal([4, 5]));
42 
43     // A Red Black tree with the highest element at front:
44     import std.range : iota;
45     auto maxTree = redBlackTree!"a > b"(iota(5));
46     assert(equal(maxTree[], [4, 3, 2, 1, 0]));
47 
48     // adding duplicates will not add them, but return 0
49     auto rbt2 = redBlackTree(1, 3);
50     assert(rbt2.insert(1) == 0);
51     assert(equal(rbt2[], [1, 3]));
52     assert(rbt2.insert(2) == 1);
53 
54     // however you can allow duplicates
55     auto ubt = redBlackTree!true([0, 1, 0, 1]);
56     assert(equal(ubt[], [0, 0, 1, 1]));
57 }
58 
59 import std.format;
60 import std.functional : binaryFun;
61 
62 public import std.container.util;
63 
64 version (StdUnittest) debug = RBDoChecks;
65 
66 //debug = RBDoChecks;
67 
68 /*
69  * Implementation for a Red Black node for use in a Red Black Tree (see below)
70  *
71  * this implementation assumes we have a marker Node that is the parent of the
72  * root Node.  This marker Node is not a valid Node, but marks the end of the
73  * collection.  The root is the left child of the marker Node, so it is always
74  * last in the collection.  The marker Node is passed in to the setColor
75  * function, and the Node which has this Node as its parent is assumed to be
76  * the root Node.
77  *
78  * A Red Black tree should have O(lg(n)) insertion, removal, and search time.
79  */
80 struct RBNode(V)
81 {
82     /*
83      * Convenience alias
84      */
85     alias Node = RBNode*;
86 
87     private Node _left;
88     private Node _right;
89     private Node _parent;
90 
91     /**
92      * The value held by this node
93      */
94     V value;
95 
96     /**
97      * Enumeration determining what color the node is.  Null nodes are assumed
98      * to be black.
99      */
100     enum Color : byte
101     {
102         Red,
103         Black
104     }
105 
106     /**
107      * The color of the node.
108      */
109     Color color;
110 
111     /**
112      * Get the left child
113      */
114     @property inout(RBNode)* left() inout return scope
115     {
116         return _left;
117     }
118 
119     /**
120      * Get the right child
121      */
122     @property inout(RBNode)* right() inout return scope
123     {
124         return _right;
125     }
126 
127     /**
128      * Get the parent
129      */
130     @property inout(RBNode)* parent() inout return scope
131     {
132         return _parent;
133     }
134 
135     /**
136      * Set the left child.  Also updates the new child's parent node.  This
137      * does not update the previous child.
138      *
139      * $(RED Warning: If the node this is called on is a local variable, a stack pointer can be
140      * escaped through `newNode.parent`. It's marked `@trusted` only for backwards compatibility.)
141      *
142      * Returns newNode
143      */
144     @property Node left(return scope Node newNode) @trusted
145     {
146         _left = newNode;
147         if (newNode !is null)
148             newNode._parent = &this;
149         return newNode;
150     }
151 
152     /**
153      * Set the right child.  Also updates the new child's parent node.  This
154      * does not update the previous child.
155      *
156      * $(RED Warning: If the node this is called on is a local variable, a stack pointer can be
157      * escaped through `newNode.parent`. It's marked `@trusted` only for backwards compatibility.)
158      *
159      * Returns newNode
160      */
161     @property Node right(return scope Node newNode) @trusted
162     {
163         _right = newNode;
164         if (newNode !is null)
165             newNode._parent = &this;
166         return newNode;
167     }
168 
169     // assume _left is not null
170     //
171     // performs rotate-right operation, where this is T, _right is R, _left is
172     // L, _parent is P:
173     //
174     //      P         P
175     //      |   ->    |
176     //      T         L
177     //     / \       / \
178     //    L   R     a   T
179     //   / \           / \
180     //  a   b         b   R
181     //
182     /**
183      * Rotate right.  This performs the following operations:
184      *  - The left child becomes the parent of this node.
185      *  - This node becomes the new parent's right child.
186      *  - The old right child of the new parent becomes the left child of this
187      *    node.
188      */
189     Node rotateR()
190     in
191     {
192         assert(_left !is null, "left node must not be null");
193     }
194     do
195     {
196         // sets _left._parent also
197         if (isLeftNode)
198             parent.left = _left;
199         else
200             parent.right = _left;
201         Node tmp = _left._right;
202 
203         // sets _parent also
204         _left.right = &this;
205 
206         // sets tmp._parent also
207         left = tmp;
208 
209         return &this;
210     }
211 
212     // assumes _right is non null
213     //
214     // performs rotate-left operation, where this is T, _right is R, _left is
215     // L, _parent is P:
216     //
217     //      P           P
218     //      |    ->     |
219     //      T           R
220     //     / \         / \
221     //    L   R       T   b
222     //       / \     / \
223     //      a   b   L   a
224     //
225     /**
226      * Rotate left.  This performs the following operations:
227      *  - The right child becomes the parent of this node.
228      *  - This node becomes the new parent's left child.
229      *  - The old left child of the new parent becomes the right child of this
230      *    node.
231      */
232     Node rotateL()
233     in
234     {
235         assert(_right !is null, "right node must not be null");
236     }
237     do
238     {
239         // sets _right._parent also
240         if (isLeftNode)
241             parent.left = _right;
242         else
243             parent.right = _right;
244         Node tmp = _right._left;
245 
246         // sets _parent also
247         _right.left = &this;
248 
249         // sets tmp._parent also
250         right = tmp;
251         return &this;
252     }
253 
254 
255     /**
256      * Returns true if this node is a left child.
257      *
258      * Note that this should always return a value because the root has a
259      * parent which is the marker node.
260      */
261     @property bool isLeftNode() const
262     in
263     {
264         assert(_parent !is null, "parent must not be null");
265     }
266     do
267     {
268         return _parent._left is &this;
269     }
270 
271     /**
272      * Set the color of the node after it is inserted.  This performs an
273      * update to the whole tree, possibly rotating nodes to keep the Red-Black
274      * properties correct.  This is an O(lg(n)) operation, where n is the
275      * number of nodes in the tree.
276      *
277      * end is the marker node, which is the parent of the topmost valid node.
278      */
279     void setColor(Node end)
280     {
281         // test against the marker node
282         if (_parent !is end)
283         {
284             if (_parent.color == Color.Red)
285             {
286                 Node cur = &this;
287                 while (true)
288                 {
289                     // because root is always black, _parent._parent always exists
290                     if (cur._parent.isLeftNode)
291                     {
292                         // parent is left node, y is 'uncle', could be null
293                         Node y = cur._parent._parent._right;
294                         if (y !is null && y.color == Color.Red)
295                         {
296                             cur._parent.color = Color.Black;
297                             y.color = Color.Black;
298                             cur = cur._parent._parent;
299                             if (cur._parent is end)
300                             {
301                                 // root node
302                                 cur.color = Color.Black;
303                                 break;
304                             }
305                             else
306                             {
307                                 // not root node
308                                 cur.color = Color.Red;
309                                 if (cur._parent.color == Color.Black)
310                                     // satisfied, exit the loop
311                                     break;
312                             }
313                         }
314                         else
315                         {
316                             if (!cur.isLeftNode)
317                                 cur = cur._parent.rotateL();
318                             cur._parent.color = Color.Black;
319                             cur = cur._parent._parent.rotateR();
320                             cur.color = Color.Red;
321                             // tree should be satisfied now
322                             break;
323                         }
324                     }
325                     else
326                     {
327                         // parent is right node, y is 'uncle'
328                         Node y = cur._parent._parent._left;
329                         if (y !is null && y.color == Color.Red)
330                         {
331                             cur._parent.color = Color.Black;
332                             y.color = Color.Black;
333                             cur = cur._parent._parent;
334                             if (cur._parent is end)
335                             {
336                                 // root node
337                                 cur.color = Color.Black;
338                                 break;
339                             }
340                             else
341                             {
342                                 // not root node
343                                 cur.color = Color.Red;
344                                 if (cur._parent.color == Color.Black)
345                                     // satisfied, exit the loop
346                                     break;
347                             }
348                         }
349                         else
350                         {
351                             if (cur.isLeftNode)
352                                 cur = cur._parent.rotateR();
353                             cur._parent.color = Color.Black;
354                             cur = cur._parent._parent.rotateL();
355                             cur.color = Color.Red;
356                             // tree should be satisfied now
357                             break;
358                         }
359                     }
360                 }
361 
362             }
363         }
364         else
365         {
366             //
367             // this is the root node, color it black
368             //
369             color = Color.Black;
370         }
371     }
372 
373     /**
374      * Remove this node from the tree.  The 'end' node is used as the marker
375      * which is root's parent.  Note that this cannot be null!
376      *
377      * Returns the next highest valued node in the tree after this one, or end
378      * if this was the highest-valued node.
379      */
380     Node remove(Node end) return
381     {
382         //
383         // remove this node from the tree, fixing the color if necessary.
384         //
385         Node x;
386         Node ret = next;
387 
388         // if this node has 2 children
389         if (_left !is null && _right !is null)
390         {
391             //
392             // normally, we can just swap this node's and y's value, but
393             // because an iterator could be pointing to y and we don't want to
394             // disturb it, we swap this node and y's structure instead.  This
395             // can also be a benefit if the value of the tree is a large
396             // struct, which takes a long time to copy.
397             //
398             Node yp, yl, yr;
399             Node y = ret; // y = next
400             yp = y._parent;
401             yl = y._left;
402             yr = y._right;
403             auto yc = y.color;
404             auto isyleft = y.isLeftNode;
405 
406             //
407             // replace y's structure with structure of this node.
408             //
409             if (isLeftNode)
410                 _parent.left = y;
411             else
412                 _parent.right = y;
413             //
414             // need special case so y doesn't point back to itself
415             //
416             y.left = _left;
417             if (_right is y)
418                 y.right = &this;
419             else
420                 y.right = _right;
421             y.color = color;
422 
423             //
424             // replace this node's structure with structure of y.
425             //
426             left = yl;
427             right = yr;
428             if (_parent !is y)
429             {
430                 if (isyleft)
431                     yp.left = &this;
432                 else
433                     yp.right = &this;
434             }
435             color = yc;
436         }
437 
438         // if this has less than 2 children, remove it
439         if (_left !is null)
440             x = _left;
441         else
442             x = _right;
443 
444         bool deferedUnlink = false;
445         if (x is null)
446         {
447             // pretend this is a null node, defer unlinking the node
448             x = &this;
449             deferedUnlink = true;
450         }
451         else if (isLeftNode)
452             _parent.left = x;
453         else
454             _parent.right = x;
455 
456         // if the color of this is black, then it needs to be fixed
457         if (color == color.Black)
458         {
459             // need to recolor the tree.
460             while (x._parent !is end && x.color == Node.Color.Black)
461             {
462                 if (x.isLeftNode)
463                 {
464                     // left node
465                     Node w = x._parent._right;
466                     if (w.color == Node.Color.Red)
467                     {
468                         w.color = Node.Color.Black;
469                         x._parent.color = Node.Color.Red;
470                         x._parent.rotateL();
471                         w = x._parent._right;
472                     }
473                     Node wl = w.left;
474                     Node wr = w.right;
475                     if ((wl is null || wl.color == Node.Color.Black) &&
476                             (wr is null || wr.color == Node.Color.Black))
477                     {
478                         w.color = Node.Color.Red;
479                         x = x._parent;
480                     }
481                     else
482                     {
483                         if (wr is null || wr.color == Node.Color.Black)
484                         {
485                             // wl cannot be null here
486                             wl.color = Node.Color.Black;
487                             w.color = Node.Color.Red;
488                             w.rotateR();
489                             w = x._parent._right;
490                         }
491 
492                         w.color = x._parent.color;
493                         x._parent.color = Node.Color.Black;
494                         w._right.color = Node.Color.Black;
495                         x._parent.rotateL();
496                         x = end.left; // x = root
497                     }
498                 }
499                 else
500                 {
501                     // right node
502                     Node w = x._parent._left;
503                     if (w.color == Node.Color.Red)
504                     {
505                         w.color = Node.Color.Black;
506                         x._parent.color = Node.Color.Red;
507                         x._parent.rotateR();
508                         w = x._parent._left;
509                     }
510                     Node wl = w.left;
511                     Node wr = w.right;
512                     if ((wl is null || wl.color == Node.Color.Black) &&
513                             (wr is null || wr.color == Node.Color.Black))
514                     {
515                         w.color = Node.Color.Red;
516                         x = x._parent;
517                     }
518                     else
519                     {
520                         if (wl is null || wl.color == Node.Color.Black)
521                         {
522                             // wr cannot be null here
523                             wr.color = Node.Color.Black;
524                             w.color = Node.Color.Red;
525                             w.rotateL();
526                             w = x._parent._left;
527                         }
528 
529                         w.color = x._parent.color;
530                         x._parent.color = Node.Color.Black;
531                         w._left.color = Node.Color.Black;
532                         x._parent.rotateR();
533                         x = end.left; // x = root
534                     }
535                 }
536             }
537             x.color = Node.Color.Black;
538         }
539 
540         if (deferedUnlink)
541         {
542             //
543             // unlink this node from the tree
544             //
545             if (isLeftNode)
546                 _parent.left = null;
547             else
548                 _parent.right = null;
549         }
550 
551         // clean references to help GC
552         // https://issues.dlang.org/show_bug.cgi?id=12915
553         _left = _right = _parent = null;
554 
555         return ret;
556     }
557 
558     /**
559      * Return the leftmost descendant of this node.
560      */
561     @property inout(RBNode)* leftmost() inout return
562     {
563         inout(RBNode)* result = &this;
564         while (result._left !is null)
565             result = result._left;
566         return result;
567     }
568 
569     /**
570      * Return the rightmost descendant of this node
571      */
572     @property inout(RBNode)* rightmost() inout return
573     {
574         inout(RBNode)* result = &this;
575         while (result._right !is null)
576             result = result._right;
577         return result;
578     }
579 
580     /**
581      * Returns the next valued node in the tree.
582      *
583      * You should never call this on the marker node, as it is assumed that
584      * there is a valid next node.
585      */
586     @property inout(RBNode)* next() inout return
587     {
588         inout(RBNode)* n = &this;
589         if (n.right is null)
590         {
591             while (!n.isLeftNode)
592                 n = n._parent;
593             return n._parent;
594         }
595         else
596             return n.right.leftmost;
597     }
598 
599     /**
600      * Returns the previous valued node in the tree.
601      *
602      * You should never call this on the leftmost node of the tree as it is
603      * assumed that there is a valid previous node.
604      */
605     @property inout(RBNode)* prev() inout return
606     {
607         inout(RBNode)* n = &this;
608         if (n.left is null)
609         {
610             while (n.isLeftNode)
611                 n = n._parent;
612             return n._parent;
613         }
614         else
615             return n.left.rightmost;
616     }
617 
618     Node dup(scope Node delegate(V v) alloc)
619     {
620         //
621         // duplicate this and all child nodes
622         //
623         // The recursion should be lg(n), so we shouldn't have to worry about
624         // stack size.
625         //
626         Node copy = alloc(value);
627         copy.color = color;
628         if (_left !is null)
629             copy.left = _left.dup(alloc);
630         if (_right !is null)
631             copy.right = _right.dup(alloc);
632         return copy;
633     }
634 
635     Node dup()
636     {
637         Node copy = new RBNode!V(null, null, null, value);
638         copy.color = color;
639         if (_left !is null)
640             copy.left = _left.dup();
641         if (_right !is null)
642             copy.right = _right.dup();
643         return copy;
644     }
645 }
646 
647 //constness checks
648 @safe pure unittest
649 {
650     const RBNode!int n;
651     static assert(is(typeof(n.leftmost)));
652     static assert(is(typeof(n.rightmost)));
653     static assert(is(typeof(n.next)));
654     static assert(is(typeof(n.prev)));
655 }
656 
657 private struct RBRange(N)
658 {
659     alias Node = N;
660     alias Elem = typeof(Node.value);
661 
662     private Node _begin;
663     private Node _end;
664 
665     private this(Node b, Node e)
666     {
667         _begin = b;
668         _end = e;
669     }
670 
671     /**
672      * Returns `true` if the range is _empty
673      */
674     @property bool empty() const
675     {
676         return _begin is _end;
677     }
678 
679     /**
680      * Returns the first element in the range
681      */
682     @property Elem front()
683     {
684         return _begin.value;
685     }
686 
687     /**
688      * Returns the last element in the range
689      */
690     @property Elem back()
691     {
692         return _end.prev.value;
693     }
694 
695     /**
696      * pop the front element from the range
697      *
698      * Complexity: amortized $(BIGOH 1)
699      */
700     void popFront()
701     {
702         _begin = _begin.next;
703     }
704 
705     /**
706      * pop the back element from the range
707      *
708      * Complexity: amortized $(BIGOH 1)
709      */
710     void popBack()
711     {
712         _end = _end.prev;
713     }
714 
715     /**
716      * Trivial _save implementation, needed for `isForwardRange`.
717      */
718     @property RBRange save()
719     {
720         return this;
721     }
722 }
723 
724 /**
725  * Implementation of a $(LINK2 https://en.wikipedia.org/wiki/Red%E2%80%93black_tree,
726  * red-black tree) container.
727  *
728  * All inserts, removes, searches, and any function in general has complexity
729  * of $(BIGOH lg(n)).
730  *
731  * To use a different comparison than $(D "a < b"), pass a different operator string
732  * that can be used by $(REF binaryFun, std,functional), or pass in a
733  * function, delegate, functor, or any type where $(D less(a, b)) results in a `bool`
734  * value.
735  *
736  * Note that less should produce a strict ordering.  That is, for two unequal
737  * elements `a` and `b`, $(D less(a, b) == !less(b, a)). $(D less(a, a)) should
738  * always equal `false`.
739  *
740  * If `allowDuplicates` is set to `true`, then inserting the same element more than
741  * once continues to add more elements.  If it is `false`, duplicate elements are
742  * ignored on insertion.  If duplicates are allowed, then new elements are
743  * inserted after all existing duplicate elements.
744  */
745 final class RedBlackTree(T, alias less = "a < b", bool allowDuplicates = false)
746 if (is(typeof(binaryFun!less(T.init, T.init))))
747 {
748     import std.meta : allSatisfy;
749     import std.range : Take;
750     import std.range.primitives : isInputRange, walkLength;
751     import std.traits : isIntegral, isDynamicArray, isImplicitlyConvertible;
752 
753     alias _less = binaryFun!less;
754 
755     version (StdUnittest)
756     {
757         static if (is(typeof(less) == string))
758         {
759             private enum doUnittest = is(byte : T) && isIntegral!T && (less == "a < b" || less == "a > b");
760         }
761         else
762             enum doUnittest = false;
763 
764         // note, this must be final so it does not affect the vtable layout
765         bool arrayEqual(T[] arr)
766         {
767             if (walkLength(this[]) == arr.length)
768             {
769                 foreach (v; arr)
770                 {
771                     if (!(v in this))
772                         return false;
773                 }
774                 return true;
775             }
776             return false;
777         }
778     }
779     else
780     {
781         private enum doUnittest = false;
782     }
783 
784     /**
785       * Element type for the tree
786       */
787     alias Elem = T;
788 
789     // used for convenience
790     private alias RBNode = .RBNode!Elem;
791     private alias Node = RBNode.Node;
792 
793     private Node   _end;
794     private Node   _begin;
795     private size_t _length;
796 
797     private void _setup()
798     {
799         //Make sure that _setup isn't run more than once.
800         assert(!_end, "Setup must only be run once");
801         _begin = _end = allocate();
802     }
803 
804     static private Node allocate()
805     {
806         return new RBNode;
807     }
808 
809     static private Node allocate(Elem v)
810     {
811         return new RBNode(null, null, null, v);
812     }
813 
814     /**
815      * The range types for `RedBlackTree`
816      */
817     alias Range = RBRange!(RBNode*);
818     alias ConstRange = RBRange!(const(RBNode)*); /// Ditto
819     alias ImmutableRange = RBRange!(immutable(RBNode)*); /// Ditto
820 
821     static if (doUnittest) @safe pure unittest
822     {
823         import std.algorithm.comparison : equal;
824         import std.range.primitives;
825         auto ts = new RedBlackTree(1, 2, 3, 4, 5);
826         assert(ts.length == 5);
827         auto r = ts[];
828 
829         static if (less == "a < b")
830             auto vals = [1, 2, 3, 4, 5];
831         else
832             auto vals = [5, 4, 3, 2, 1];
833         assert(equal(r, vals));
834 
835         assert(r.front == vals.front);
836         assert(r.back != r.front);
837         auto oldfront = r.front;
838         auto oldback = r.back;
839         r.popFront();
840         r.popBack();
841         assert(r.front != r.back);
842         assert(r.front != oldfront);
843         assert(r.back != oldback);
844         assert(ts.length == 5);
845     }
846 
847     // find a node based on an element value
848     private inout(RBNode)* _find(Elem e) inout
849     {
850         static if (allowDuplicates)
851         {
852             inout(RBNode)* cur = _end.left;
853             inout(RBNode)* result = null;
854             while (cur)
855             {
856                 if (_less(cur.value, e))
857                     cur = cur.right;
858                 else if (_less(e, cur.value))
859                     cur = cur.left;
860                 else
861                 {
862                     // want to find the left-most element
863                     result = cur;
864                     cur = cur.left;
865                 }
866             }
867             return result;
868         }
869         else
870         {
871             inout(RBNode)* cur = _end.left;
872             while (cur)
873             {
874                 if (_less(cur.value, e))
875                     cur = cur.right;
876                 else if (_less(e, cur.value))
877                     cur = cur.left;
878                 else
879                     return cur;
880             }
881             return null;
882         }
883     }
884 
885     /* add an element to the tree, returns the node added, or the existing node
886      * if it has already been added and allowDuplicates is false
887      * Returns:
888      *   true if node was added
889      */
890     private bool _add(return scope Elem n)
891     {
892         Node result;
893         static if (!allowDuplicates)
894             bool added = true;
895 
896         if (!_end.left)
897         {
898             result = allocate(n);
899             (() @trusted { _end.left = _begin = result; }) ();
900         }
901         else
902         {
903             Node newParent = _end.left;
904             Node nxt;
905             while (true)
906             {
907                 if (_less(n, newParent.value))
908                 {
909                     nxt = newParent.left;
910                     if (nxt is null)
911                     {
912                         //
913                         // add to right of new parent
914                         //
915                         result = allocate(n);
916                         (() @trusted { newParent.left = result; }) ();
917                         break;
918                     }
919                 }
920                 else
921                 {
922                     static if (!allowDuplicates)
923                     {
924                         if (!_less(newParent.value, n))
925                         {
926                             result = newParent;
927                             added = false;
928                             break;
929                         }
930                     }
931                     nxt = newParent.right;
932                     if (nxt is null)
933                     {
934                         //
935                         // add to right of new parent
936                         //
937                         result = allocate(n);
938                         (() @trusted { newParent.right = result; }) ();
939                         break;
940                     }
941                 }
942                 newParent = nxt;
943             }
944             if (_begin.left)
945                 _begin = _begin.left;
946         }
947         static if (allowDuplicates)
948         {
949             result.setColor(_end);
950             debug(RBDoChecks)
951                 check();
952             ++_length;
953             return true;
954         }
955         else
956         {
957             if (added)
958             {
959                 ++_length;
960                 result.setColor(_end);
961             }
962             debug(RBDoChecks)
963                 check();
964             return added;
965         }
966     }
967 
968 
969     /**
970      * Check if any elements exist in the container.  Returns `false` if at least
971      * one element exists.
972      */
973     @property bool empty() const // pure, nothrow, @safe, @nogc: are inferred
974     {
975         return _end.left is null;
976     }
977 
978     /++
979         Returns the number of elements in the container.
980 
981         Complexity: $(BIGOH 1).
982     +/
983     @property size_t length() const
984     {
985         return _length;
986     }
987 
988     /**
989      * Duplicate this container.  The resulting container contains a shallow
990      * copy of the elements.
991      *
992      * Complexity: $(BIGOH n)
993      */
994     @property RedBlackTree dup()
995     {
996         return new RedBlackTree(_end.dup(), _length);
997     }
998 
999     static if (doUnittest) @safe pure unittest
1000     {
1001         import std.algorithm.comparison : equal;
1002         auto ts = new RedBlackTree(1, 2, 3, 4, 5);
1003         assert(ts.length == 5);
1004         auto ts2 = ts.dup;
1005         assert(ts2.length == 5);
1006         assert(equal(ts[], ts2[]));
1007         ts2.insert(cast(Elem) 6);
1008         assert(!equal(ts[], ts2[]));
1009         assert(ts.length == 5 && ts2.length == 6);
1010     }
1011 
1012     /**
1013      * Fetch a range that spans all the elements in the container.
1014      *
1015      * Complexity: $(BIGOH 1)
1016      */
1017     Range opSlice()
1018     {
1019         return Range(_begin, _end);
1020     }
1021 
1022     /// Ditto
1023     ConstRange opSlice() const
1024     {
1025         return ConstRange(_begin, _end);
1026     }
1027 
1028     /// Ditto
1029     ImmutableRange opSlice() immutable
1030     {
1031         return ImmutableRange(_begin, _end);
1032     }
1033 
1034     /**
1035      * The front element in the container
1036      *
1037      * Complexity: $(BIGOH 1)
1038      */
1039     inout(Elem) front() inout
1040     {
1041         return _begin.value;
1042     }
1043 
1044     /**
1045      * The last element in the container
1046      *
1047      * Complexity: $(BIGOH log(n))
1048      */
1049     inout(Elem) back() inout
1050     {
1051         return _end.prev.value;
1052     }
1053 
1054     /++
1055         `in` operator. Check to see if the given element exists in the
1056         container.
1057 
1058        Complexity: $(BIGOH log(n))
1059      +/
1060     bool opBinaryRight(string op)(Elem e) const
1061     if (op == "in")
1062     {
1063         return _find(e) !is null;
1064     }
1065 
1066     static if (doUnittest) @safe pure unittest
1067     {
1068         auto ts = new RedBlackTree(1, 2, 3, 4, 5);
1069         assert(cast(Elem) 3 in ts);
1070         assert(cast(Elem) 6 !in ts);
1071     }
1072 
1073     /**
1074      * Compares two trees for equality.
1075      *
1076      * Complexity: $(BIGOH n)
1077      */
1078     override bool opEquals(Object rhs)
1079     {
1080         import std.algorithm.comparison : equal;
1081 
1082         RedBlackTree that = cast(RedBlackTree) rhs;
1083         if (that is null) return false;
1084 
1085         // If there aren't the same number of nodes, we can't be equal.
1086         if (this._length != that._length) return false;
1087 
1088         auto thisRange = this[];
1089         auto thatRange = that[];
1090         return equal!((Elem a, Elem b) => !_less(a,b) && !_less(b,a))
1091                      (thisRange, thatRange);
1092     }
1093 
1094     static if (doUnittest) @system unittest
1095     {
1096         auto t1 = new RedBlackTree(1,2,3,4);
1097         auto t2 = new RedBlackTree(1,2,3,4);
1098         auto t3 = new RedBlackTree(1,2,3,5);
1099         auto t4 = new RedBlackTree(1,2,3,4,5);
1100         auto o = new Object();
1101 
1102         assert(t1 == t1);
1103         assert(t1 == t2);
1104         assert(t1 != t3);
1105         assert(t1 != t4);
1106         assert(t1 != o);  // pathological case, must not crash
1107     }
1108 
1109     /**
1110      * Generates a hash for the tree. Note that with a custom comparison function
1111      * it may not hold that if two rbtrees are equal, the hashes of the trees
1112      * will be equal.
1113      */
1114     override size_t toHash() nothrow @safe
1115     {
1116         size_t hash = cast(size_t) 0x6b63_616c_4264_6552UL;
1117         foreach (ref e; this[])
1118             // As in boost::hash_combine
1119             // https://www.boost.org/doc/libs/1_55_0/doc/html/hash/reference.html#boost.hash_combine
1120             hash += .hashOf(e) + 0x9e3779b9 + (hash << 6) + (hash >>> 2);
1121         return hash;
1122     }
1123 
1124     static if (doUnittest) @system unittest
1125     {
1126         auto t1 = new RedBlackTree(1,2,3,4);
1127         auto t2 = new RedBlackTree(1,2,3,4);
1128         auto t3 = new RedBlackTree(1,2,3,5);
1129         auto t4 = new RedBlackTree(1,2,3,4,5);
1130 
1131         assert(t1.toHash() == t2.toHash);
1132 
1133         assert(t1.toHash() != t3.toHash);
1134         assert(t2.toHash() != t3.toHash);
1135 
1136         assert(t3.toHash() != t4.toHash);
1137         assert(t1.toHash() != t4.toHash);
1138 
1139         // empty tree
1140         auto t5 = new RedBlackTree();
1141         auto t6 = new RedBlackTree();
1142 
1143         assert(t5.toHash() == t6.toHash());
1144 
1145         auto t7 = new RedBlackTree!string("red", "black");
1146         auto t8 = new RedBlackTree!string("white", "black");
1147         auto t9 = new RedBlackTree!string("red", "black");
1148 
1149         assert(t7.toHash() == t9.toHash());
1150         assert(t7.toHash() != t8.toHash());
1151 
1152         static struct MyInt
1153         {
1154             int x;
1155 
1156           @safe:
1157 
1158             this(int init_x)
1159             {
1160                 x = init_x;
1161             }
1162 
1163             size_t toHash() const nothrow
1164             {
1165                 return typeid(x).getHash(&x) ^ 0xF0F0_F0F0;
1166             }
1167 
1168             int opCmp(const MyInt that) const
1169             {
1170                 return (x > that.x) - (x < that.x);
1171             }
1172 
1173             bool opEquals(const MyInt that) const
1174             {
1175                 return (this.x == that.x);
1176             }
1177         }
1178 
1179         auto rbt1 = new RedBlackTree!MyInt(MyInt(1), MyInt(2), MyInt(3), MyInt(4));
1180         auto rbt2 = new RedBlackTree!MyInt(MyInt(1), MyInt(2), MyInt(3), MyInt(4));
1181 
1182         assert(rbt1.toHash() == rbt2.toHash());
1183         assert(rbt1.toHash() != t1.toHash());
1184 
1185         auto rbt3 = new RedBlackTree!MyInt(MyInt(4), MyInt(2), MyInt(3), MyInt(4));
1186 
1187         assert(rbt1.toHash() != rbt3.toHash());
1188 
1189         class MyInt2
1190         {
1191             int x;
1192 
1193             this(int init_x)
1194             {
1195                 x = init_x;
1196             }
1197 
1198             override size_t toHash() const @safe nothrow
1199             {
1200                 return typeid(x).getHash(&x) ^ 0xF0F0_F0F0;
1201             }
1202 
1203             int opCmp(const MyInt2 that) const
1204             {
1205                 return (x > that.x) - (x < that.x);
1206             }
1207 
1208             bool opEquals(const MyInt2 that) const
1209             {
1210                 return (this.x == that.x);
1211             }
1212         }
1213 
1214         static bool nullSafeLess(scope const MyInt2 a, scope const MyInt2 b)
1215         {
1216             return a is null ? b !is null : (b !is null && a < b);
1217         }
1218 
1219         auto rbt4 = new RedBlackTree!MyInt2(new MyInt2(1), new MyInt2(9), new MyInt2(3), new MyInt2(42));
1220         auto rbt5 = new RedBlackTree!MyInt2(new MyInt2(1), new MyInt2(9), new MyInt2(3), new MyInt2(42));
1221         auto rbt6 = new RedBlackTree!(MyInt2, nullSafeLess)(new MyInt2(9), new MyInt2(3), new MyInt2(42));
1222         auto rbt7 = new RedBlackTree!(MyInt2, nullSafeLess)(null);
1223 
1224         assert(rbt6.toHash() != rbt5.toHash());
1225         assert(rbt6.toHash() != rbt4.toHash());
1226         assert(rbt6.toHash() != rbt7.toHash());
1227         assert(rbt4.toHash() == rbt5.toHash());
1228 
1229         auto rbt8 = new RedBlackTree!(MyInt2, nullSafeLess)(null, new MyInt2(9), null, new MyInt2(42));
1230         auto rbt9 = new RedBlackTree!(MyInt2, nullSafeLess)(null, new MyInt2(9), null, new MyInt2(42));
1231         auto rbt10 = new RedBlackTree!(MyInt2, nullSafeLess)(new MyInt2(94), null, new MyInt2(147));
1232 
1233         assert(rbt8.toHash() == rbt9.toHash());
1234         assert(rbt8.toHash() != rbt10.toHash());
1235     }
1236 
1237     /**
1238      * Removes all elements from the container.
1239      *
1240      * Complexity: $(BIGOH 1)
1241      */
1242     void clear()
1243     {
1244         _end.left = null;
1245         _begin = _end;
1246         _length = 0;
1247     }
1248 
1249     static if (doUnittest) @safe pure unittest
1250     {
1251         auto ts = new RedBlackTree(1,2,3,4,5);
1252         assert(ts.length == 5);
1253         ts.clear();
1254         assert(ts.empty && ts.length == 0);
1255     }
1256 
1257     /**
1258      * Insert a single element in the container.  Note that this does not
1259      * invalidate any ranges currently iterating the container.
1260      *
1261      * Returns: The number of elements inserted.
1262      *
1263      * Complexity: $(BIGOH log(n))
1264      */
1265     size_t stableInsert(Stuff)(Stuff stuff)
1266     if (isImplicitlyConvertible!(Stuff, Elem))
1267     {
1268         static if (allowDuplicates)
1269         {
1270             _add(stuff);
1271             return 1;
1272         }
1273         else
1274         {
1275             return _add(stuff);
1276         }
1277     }
1278 
1279     /**
1280      * Insert a range of elements in the container.  Note that this does not
1281      * invalidate any ranges currently iterating the container.
1282      *
1283      * Returns: The number of elements inserted.
1284      *
1285      * Complexity: $(BIGOH m * log(n))
1286      */
1287     size_t stableInsert(Stuff)(scope Stuff stuff)
1288     if (isInputRange!Stuff &&
1289         isImplicitlyConvertible!(ElementType!Stuff, Elem))
1290     {
1291         size_t result = 0;
1292         static if (allowDuplicates)
1293         {
1294             foreach (e; stuff)
1295             {
1296                 ++result;
1297                 _add(e);
1298             }
1299         }
1300         else
1301         {
1302             foreach (e; stuff)
1303             {
1304                 result += _add(e);
1305             }
1306         }
1307         return result;
1308     }
1309 
1310     /// ditto
1311     alias insert = stableInsert;
1312 
1313     static if (doUnittest) @safe pure unittest
1314     {
1315         auto ts = new RedBlackTree(2,1,3,4,5,2,5);
1316         static if (allowDuplicates)
1317         {
1318             assert(ts.length == 7);
1319             assert(ts.stableInsert(cast(Elem[])[7, 8, 6, 9, 10, 8]) == 6);
1320             assert(ts.length == 13);
1321             assert(ts.stableInsert(cast(Elem) 11) == 1 && ts.length == 14);
1322             assert(ts.stableInsert(cast(Elem) 7) == 1 && ts.length == 15);
1323 
1324             static if (less == "a < b")
1325                 assert(ts.arrayEqual([1,2,2,3,4,5,5,6,7,7,8,8,9,10,11]));
1326             else
1327                 assert(ts.arrayEqual([11,10,9,8,8,7,7,6,5,5,4,3,2,2,1]));
1328         }
1329         else
1330         {
1331             assert(ts.length == 5);
1332             Elem[] elems = [7, 8, 6, 9, 10, 8];
1333             assert(ts.stableInsert(elems) == 5);
1334             assert(ts.length == 10);
1335             assert(ts.stableInsert(cast(Elem) 11) == 1 && ts.length == 11);
1336             assert(ts.stableInsert(cast(Elem) 7) == 0 && ts.length == 11);
1337 
1338             static if (less == "a < b")
1339                 assert(ts.arrayEqual([1,2,3,4,5,6,7,8,9,10,11]));
1340             else
1341                 assert(ts.arrayEqual([11,10,9,8,7,6,5,4,3,2,1]));
1342         }
1343     }
1344 
1345     /**
1346      * Remove an element from the container and return its value.
1347      *
1348      * Complexity: $(BIGOH log(n))
1349      */
1350     Elem removeAny()
1351     {
1352         scope(success)
1353             --_length;
1354         auto n = _begin;
1355         auto result = n.value;
1356         _begin = n.remove(_end);
1357         debug(RBDoChecks)
1358             check();
1359         return result;
1360     }
1361 
1362     static if (doUnittest) @safe pure unittest
1363     {
1364         auto ts = new RedBlackTree(1,2,3,4,5);
1365         assert(ts.length == 5);
1366         auto x = ts.removeAny();
1367         assert(ts.length == 4);
1368         Elem[] arr;
1369         foreach (Elem i; 1 .. 6)
1370             if (i != x) arr ~= i;
1371         assert(ts.arrayEqual(arr));
1372     }
1373 
1374     /**
1375      * Remove the front element from the container.
1376      *
1377      * Complexity: $(BIGOH log(n))
1378      */
1379     void removeFront()
1380     {
1381         scope(success)
1382             --_length;
1383         _begin = _begin.remove(_end);
1384         debug(RBDoChecks)
1385             check();
1386     }
1387 
1388     /**
1389      * Remove the back element from the container.
1390      *
1391      * Complexity: $(BIGOH log(n))
1392      */
1393     void removeBack()
1394     {
1395         scope(success)
1396             --_length;
1397         auto lastnode = _end.prev;
1398         if (lastnode is _begin)
1399             _begin = _begin.remove(_end);
1400         else
1401             lastnode.remove(_end);
1402         debug(RBDoChecks)
1403             check();
1404     }
1405 
1406     static if (doUnittest) @safe pure unittest
1407     {
1408         auto ts = new RedBlackTree(1,2,3,4,5);
1409         assert(ts.length == 5);
1410         ts.removeBack();
1411         assert(ts.length == 4);
1412 
1413         static if (less == "a < b")
1414             assert(ts.arrayEqual([1,2,3,4]));
1415         else
1416             assert(ts.arrayEqual([2,3,4,5]));
1417 
1418         ts.removeFront();
1419         assert(ts.arrayEqual([2,3,4]) && ts.length == 3);
1420     }
1421 
1422     /++
1423         Removes the given range from the container.
1424 
1425         Returns: A range containing all of the elements that were after the
1426                  given range.
1427 
1428         Complexity: $(BIGOH m * log(n)) (where m is the number of elements in
1429                     the range)
1430      +/
1431     Range remove(Range r)
1432     {
1433         auto b = r._begin;
1434         auto e = r._end;
1435         if (_begin is b)
1436             _begin = e;
1437         while (b !is e)
1438         {
1439             b = b.remove(_end);
1440             --_length;
1441         }
1442         debug(RBDoChecks)
1443             check();
1444         return Range(e, _end);
1445     }
1446 
1447     static if (doUnittest) @safe pure unittest
1448     {
1449         import std.algorithm.comparison : equal;
1450         auto ts = new RedBlackTree(1,2,3,4,5);
1451         assert(ts.length == 5);
1452         auto r = ts[];
1453         r.popFront();
1454         r.popBack();
1455         assert(ts.length == 5);
1456         auto r2 = ts.remove(r);
1457         assert(ts.length == 2);
1458         assert(ts.arrayEqual([1,5]));
1459 
1460         static if (less == "a < b")
1461             assert(equal(r2, [5]));
1462         else
1463             assert(equal(r2, [1]));
1464     }
1465 
1466     /++
1467         Removes the given `Take!Range` from the container
1468 
1469         Returns: A range containing all of the elements that were after the
1470                  given range.
1471 
1472         Complexity: $(BIGOH m * log(n)) (where m is the number of elements in
1473                     the range)
1474      +/
1475     Range remove(Take!Range r)
1476     {
1477         immutable isBegin = (r.source._begin is _begin);
1478         auto b = r.source._begin;
1479 
1480         while (!r.empty)
1481         {
1482             r.popFront();
1483             b = b.remove(_end);
1484             --_length;
1485         }
1486 
1487         if (isBegin)
1488             _begin = b;
1489 
1490         return Range(b, _end);
1491     }
1492 
1493     static if (doUnittest) @safe pure unittest
1494     {
1495         import std.algorithm.comparison : equal;
1496         import std.range : take;
1497         auto ts = new RedBlackTree(1,2,3,4,5);
1498         auto r = ts[];
1499         r.popFront();
1500         assert(ts.length == 5);
1501         auto r2 = ts.remove(take(r, 0));
1502 
1503         static if (less == "a < b")
1504         {
1505             assert(equal(r2, [2,3,4,5]));
1506             auto r3 = ts.remove(take(r, 2));
1507             assert(ts.arrayEqual([1,4,5]) && ts.length == 3);
1508             assert(equal(r3, [4,5]));
1509         }
1510         else
1511         {
1512             assert(equal(r2, [4,3,2,1]));
1513             auto r3 = ts.remove(take(r, 2));
1514             assert(ts.arrayEqual([5,2,1]) && ts.length == 3);
1515             assert(equal(r3, [2,1]));
1516         }
1517     }
1518 
1519     /++
1520        Removes elements from the container that are equal to the given values
1521        according to the less comparator. One element is removed for each value
1522        given which is in the container. If `allowDuplicates` is true,
1523        duplicates are removed only if duplicate values are given.
1524 
1525        Returns: The number of elements removed.
1526 
1527        Complexity: $(BIGOH m log(n)) (where m is the number of elements to remove)
1528 
1529        Example:
1530 --------------------
1531 auto rbt = redBlackTree!true(0, 1, 1, 1, 4, 5, 7);
1532 rbt.removeKey(1, 4, 7);
1533 assert(equal(rbt[], [0, 1, 1, 5]));
1534 rbt.removeKey(1, 1, 0);
1535 assert(equal(rbt[], [5]));
1536 --------------------
1537       +/
1538     size_t removeKey(U...)(U elems)
1539     if (allSatisfy!(isImplicitlyConvertibleToElem, U))
1540     {
1541         Elem[U.length] toRemove = [elems];
1542         return removeKey(toRemove[]);
1543     }
1544 
1545     /++ Ditto +/
1546     size_t removeKey(U)(scope U[] elems)
1547     if (isImplicitlyConvertible!(U, Elem))
1548     {
1549         immutable lenBefore = length;
1550 
1551         foreach (e; elems)
1552         {
1553             auto beg = _firstGreaterEqual(e);
1554             if (beg is _end || _less(e, beg.value))
1555                 // no values are equal
1556                 continue;
1557             immutable isBegin = (beg is _begin);
1558             beg = beg.remove(_end);
1559             if (isBegin)
1560                 _begin = beg;
1561             --_length;
1562         }
1563 
1564         return lenBefore - length;
1565     }
1566 
1567     /++ Ditto +/
1568     size_t removeKey(Stuff)(Stuff stuff)
1569     if (isInputRange!Stuff &&
1570         isImplicitlyConvertible!(ElementType!Stuff, Elem) &&
1571         !isDynamicArray!Stuff)
1572     {
1573         import std.array : array;
1574         //We use array in case stuff is a Range from this RedBlackTree - either
1575         //directly or indirectly.
1576         return removeKey(array(stuff));
1577     }
1578 
1579     //Helper for removeKey.
1580     private template isImplicitlyConvertibleToElem(U)
1581     {
1582         enum isImplicitlyConvertibleToElem = isImplicitlyConvertible!(U, Elem);
1583     }
1584 
1585     static if (doUnittest) @safe pure unittest
1586     {
1587         import std.algorithm.comparison : equal;
1588         import std.range : take;
1589         auto rbt = new RedBlackTree(5, 4, 3, 7, 2, 1, 7, 6, 2, 19, 45);
1590 
1591         //The cast(Elem) is because these tests are instantiated with a variety
1592         //of numeric types, and the literals are all int, which is not always
1593         //implicitly convertible to Elem (e.g. short).
1594         static if (allowDuplicates)
1595         {
1596             assert(rbt.length == 11);
1597             assert(rbt.removeKey(cast(Elem) 4) == 1 && rbt.length == 10);
1598             assert(rbt.arrayEqual([1,2,2,3,5,6,7,7,19,45]) && rbt.length == 10);
1599 
1600             assert(rbt.removeKey(cast(Elem) 6, cast(Elem) 2, cast(Elem) 1) == 3);
1601             assert(rbt.arrayEqual([2,3,5,7,7,19,45]) && rbt.length == 7);
1602 
1603             assert(rbt.removeKey(cast(Elem)(42)) == 0 && rbt.length == 7);
1604             assert(rbt.removeKey(take(rbt[], 3)) == 3 && rbt.length == 4);
1605 
1606             static if (less == "a < b")
1607                 assert(equal(rbt[], [7,7,19,45]));
1608             else
1609                 assert(equal(rbt[], [7,5,3,2]));
1610         }
1611         else
1612         {
1613             assert(rbt.length == 9);
1614             assert(rbt.removeKey(cast(Elem) 4) == 1 && rbt.length == 8);
1615             assert(rbt.arrayEqual([1,2,3,5,6,7,19,45]));
1616 
1617             assert(rbt.removeKey(cast(Elem) 6, cast(Elem) 2, cast(Elem) 1) == 3);
1618             assert(rbt.arrayEqual([3,5,7,19,45]) && rbt.length == 5);
1619 
1620             assert(rbt.removeKey(cast(Elem)(42)) == 0 && rbt.length == 5);
1621             assert(rbt.removeKey(take(rbt[], 3)) == 3 && rbt.length == 2);
1622 
1623             static if (less == "a < b")
1624                 assert(equal(rbt[], [19,45]));
1625             else
1626                 assert(equal(rbt[], [5,3]));
1627         }
1628     }
1629 
1630     // find the first node where the value is > e
1631     private inout(RBNode)* _firstGreater(Elem e) inout
1632     {
1633         // can't use _find, because we cannot return null
1634         auto cur = _end.left;
1635         inout(RBNode)* result = _end;
1636         while (cur)
1637         {
1638             if (_less(e, cur.value))
1639             {
1640                 result = cur;
1641                 cur = cur.left;
1642             }
1643             else
1644                 cur = cur.right;
1645         }
1646         return result;
1647     }
1648 
1649     // find the first node where the value is >= e
1650     private inout(RBNode)* _firstGreaterEqual(Elem e) inout
1651     {
1652         // can't use _find, because we cannot return null.
1653         auto cur = _end.left;
1654         inout(RBNode)* result = _end;
1655         while (cur)
1656         {
1657             if (_less(cur.value, e))
1658                 cur = cur.right;
1659             else
1660             {
1661                 result = cur;
1662                 cur = cur.left;
1663             }
1664 
1665         }
1666         return result;
1667     }
1668 
1669     /**
1670      * Get a range from the container with all elements that are > e according
1671      * to the less comparator
1672      *
1673      * Complexity: $(BIGOH log(n))
1674      */
1675     Range upperBound(Elem e)
1676     {
1677         return Range(_firstGreater(e), _end);
1678     }
1679 
1680     /// Ditto
1681     ConstRange upperBound(Elem e) const
1682     {
1683         return ConstRange(_firstGreater(e), _end);
1684     }
1685 
1686     /// Ditto
1687     ImmutableRange upperBound(Elem e) immutable
1688     {
1689         return ImmutableRange(_firstGreater(e), _end);
1690     }
1691 
1692     /**
1693      * Get a range from the container with all elements that are < e according
1694      * to the less comparator
1695      *
1696      * Complexity: $(BIGOH log(n))
1697      */
1698     Range lowerBound(Elem e)
1699     {
1700         return Range(_begin, _firstGreaterEqual(e));
1701     }
1702 
1703     /// Ditto
1704     ConstRange lowerBound(Elem e) const
1705     {
1706         return ConstRange(_begin, _firstGreaterEqual(e));
1707     }
1708 
1709     /// Ditto
1710     ImmutableRange lowerBound(Elem e) immutable
1711     {
1712         return ImmutableRange(_begin, _firstGreaterEqual(e));
1713     }
1714 
1715     /**
1716      * Get a range from the container with all elements that are == e according
1717      * to the less comparator
1718      *
1719      * Complexity: $(BIGOH log(n))
1720      */
1721     auto equalRange(this This)(Elem e)
1722     {
1723         auto beg = _firstGreaterEqual(e);
1724         alias RangeType = RBRange!(typeof(beg));
1725         if (beg is _end || _less(e, beg.value))
1726             // no values are equal
1727             return RangeType(beg, beg);
1728         static if (allowDuplicates)
1729         {
1730             return RangeType(beg, _firstGreater(e));
1731         }
1732         else
1733         {
1734             // no sense in doing a full search, no duplicates are allowed,
1735             // so we just get the next node.
1736             return RangeType(beg, beg.next);
1737         }
1738     }
1739 
1740     static if (doUnittest) @safe pure unittest
1741     {
1742         import std.algorithm.comparison : equal;
1743         auto ts = new RedBlackTree(1, 2, 3, 4, 5);
1744         auto rl = ts.lowerBound(3);
1745         auto ru = ts.upperBound(3);
1746         auto re = ts.equalRange(3);
1747 
1748         static if (less == "a < b")
1749         {
1750             assert(equal(rl, [1,2]));
1751             assert(equal(ru, [4,5]));
1752         }
1753         else
1754         {
1755             assert(equal(rl, [5,4]));
1756             assert(equal(ru, [2,1]));
1757         }
1758 
1759         assert(equal(re, [3]));
1760     }
1761 
1762     debug(RBDoChecks)
1763     {
1764         /*
1765          * Print the tree.  This prints a sideways view of the tree in ASCII form,
1766          * with the number of indentations representing the level of the nodes.
1767          * It does not print values, only the tree structure and color of nodes.
1768          */
1769         void printTree(Node n, int indent = 0)
1770         {
1771             import std.stdio : write, writeln;
1772             if (n !is null)
1773             {
1774                 printTree(n.right, indent + 2);
1775                 for (int i = 0; i < indent; i++)
1776                     write(".");
1777                 writeln(n.color == n.color.Black ? "B" : "R");
1778                 printTree(n.left, indent + 2);
1779             }
1780             else
1781             {
1782                 for (int i = 0; i < indent; i++)
1783                     write(".");
1784                 writeln("N");
1785             }
1786             if (indent is 0)
1787                 writeln();
1788         }
1789 
1790         /*
1791          * Check the tree for validity.  This is called after every add or remove.
1792          * This should only be enabled to debug the implementation of the RB Tree.
1793          */
1794         void check() @trusted
1795         {
1796             //
1797             // check implementation of the tree
1798             //
1799             int recurse(Node n, string path)
1800             {
1801                 import std.stdio : writeln;
1802                 if (n is null)
1803                     return 1;
1804                 if (n.parent.left !is n && n.parent.right !is n)
1805                     throw new Exception("Node at path " ~ path ~ " has inconsistent pointers");
1806                 Node next = n.next;
1807                 static if (allowDuplicates)
1808                 {
1809                     if (next !is _end && _less(next.value, n.value))
1810                         throw new Exception("ordering invalid at path " ~ path);
1811                 }
1812                 else
1813                 {
1814                     if (next !is _end && !_less(n.value, next.value))
1815                         throw new Exception("ordering invalid at path " ~ path);
1816                 }
1817                 if (n.color == n.color.Red)
1818                 {
1819                     if ((n.left !is null && n.left.color == n.color.Red) ||
1820                             (n.right !is null && n.right.color == n.color.Red))
1821                         throw new Exception("Node at path " ~ path ~ " is red with a red child");
1822                 }
1823 
1824                 int l = recurse(n.left, path ~ "L");
1825                 int r = recurse(n.right, path ~ "R");
1826                 if (l != r)
1827                 {
1828                     writeln("bad tree at:");
1829                     debug printTree(n);
1830                     throw new Exception(
1831                         "Node at path " ~ path ~ " has different number of black nodes on left and right paths"
1832                     );
1833                 }
1834                 return l + (n.color == n.color.Black ? 1 : 0);
1835             }
1836 
1837             try
1838             {
1839                 recurse(_end.left, "");
1840             }
1841             catch (Exception e)
1842             {
1843                 debug printTree(_end.left, 0);
1844                 throw e;
1845             }
1846         }
1847     }
1848 
1849     /**
1850       Formats the RedBlackTree into a sink function. For more info see $(D
1851       std.format.formatValue). Note that this only is available when the
1852       element type can be formatted. Otherwise, the default toString from
1853       Object is used.
1854      */
1855     static if (is(typeof((){FormatSpec!(char) fmt; formatValue((const(char)[]) {}, ConstRange.init, fmt);})))
1856     {
1857         void toString(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt) const
1858         {
1859             sink("RedBlackTree(");
1860             sink.formatValue(this[], fmt);
1861             sink(")");
1862         }
1863     }
1864 
1865     /**
1866      * Constructor. Pass in an array of elements, or individual elements to
1867      * initialize the tree with.
1868      */
1869     this(Elem[] elems...)
1870     {
1871         _setup();
1872         stableInsert(elems);
1873     }
1874 
1875     /**
1876      * Constructor. Pass in a range of elements to initialize the tree with.
1877      */
1878     this(Stuff)(Stuff stuff)
1879     if (isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, Elem))
1880     {
1881         _setup();
1882         stableInsert(stuff);
1883     }
1884 
1885     ///
1886     this()
1887     {
1888         _setup();
1889     }
1890 
1891     private this(Node end, size_t length)
1892     {
1893         _end = end;
1894         _begin = end.leftmost;
1895         _length = length;
1896     }
1897 }
1898 
1899 //Verify Example for removeKey.
1900 @safe pure unittest
1901 {
1902     import std.algorithm.comparison : equal;
1903     auto rbt = redBlackTree!true(0, 1, 1, 1, 4, 5, 7);
1904     rbt.removeKey(1, 4, 7);
1905     assert(equal(rbt[], [0, 1, 1, 5]));
1906     rbt.removeKey(1, 1, 0);
1907     assert(equal(rbt[], [5]));
1908 }
1909 
1910 //Tests for removeKey
1911 @safe pure unittest
1912 {
1913     import std.algorithm.comparison : equal;
1914     {
1915         auto rbt = redBlackTree(["hello", "world", "foo", "bar"]);
1916         assert(equal(rbt[], ["bar", "foo", "hello", "world"]));
1917         assert(rbt.removeKey("hello") == 1);
1918         assert(equal(rbt[], ["bar", "foo", "world"]));
1919         assert(rbt.removeKey("hello") == 0);
1920         assert(equal(rbt[], ["bar", "foo", "world"]));
1921         assert(rbt.removeKey("hello", "foo", "bar") == 2);
1922         assert(equal(rbt[], ["world"]));
1923         assert(rbt.removeKey(["", "world", "hello"]) == 1);
1924         assert(rbt.empty);
1925     }
1926 
1927     {
1928         auto rbt = redBlackTree([1, 2, 12, 27, 4, 500]);
1929         assert(equal(rbt[], [1, 2, 4, 12, 27, 500]));
1930         assert(rbt.removeKey(1u) == 1);
1931         assert(equal(rbt[], [2, 4, 12, 27, 500]));
1932         assert(rbt.removeKey(cast(byte) 1) == 0);
1933         assert(equal(rbt[], [2, 4, 12, 27, 500]));
1934         assert(rbt.removeKey(1, 12u, cast(byte) 27) == 2);
1935         assert(equal(rbt[], [2, 4, 500]));
1936         assert(rbt.removeKey([cast(short) 0, cast(short) 500, cast(short) 1]) == 1);
1937         assert(equal(rbt[], [2, 4]));
1938     }
1939 }
1940 
1941 @safe pure unittest
1942 {
1943     void test(T)()
1944     {
1945         auto rt1 = new RedBlackTree!(T, "a < b", false)();
1946         auto rt2 = new RedBlackTree!(T, "a < b", true)();
1947         auto rt3 = new RedBlackTree!(T, "a > b", false)();
1948         auto rt4 = new RedBlackTree!(T, "a > b", true)();
1949     }
1950 
1951     test!long();
1952     test!ulong();
1953     test!int();
1954     test!uint();
1955     test!short();
1956     test!ushort();
1957     test!byte();
1958     test!byte();
1959 }
1960 
1961 // https://issues.dlang.org/show_bug.cgi?id=19626
1962 @safe pure unittest
1963 {
1964     enum T { a, b }
1965     alias t = RedBlackTree!T;
1966 }
1967 
1968 import std.range.primitives : isInputRange, ElementType;
1969 import std.traits : isArray, isSomeString;
1970 
1971 /++
1972     Convenience function for creating a `RedBlackTree!E` from a list of
1973     values.
1974 
1975     Params:
1976         allowDuplicates =  Whether duplicates should be allowed (optional, default: false)
1977         less = predicate to sort by (optional)
1978         elems = elements to insert into the rbtree (variadic arguments)
1979         range = range elements to insert into the rbtree (alternative to elems)
1980   +/
1981 auto redBlackTree(E)(E[] elems...)
1982 {
1983     return new RedBlackTree!E(elems);
1984 }
1985 
1986 /++ Ditto +/
1987 auto redBlackTree(bool allowDuplicates, E)(E[] elems...)
1988 {
1989     return new RedBlackTree!(E, "a < b", allowDuplicates)(elems);
1990 }
1991 
1992 /++ Ditto +/
1993 auto redBlackTree(alias less, E)(E[] elems...)
1994 if (is(typeof(binaryFun!less(E.init, E.init))))
1995 {
1996     return new RedBlackTree!(E, less)(elems);
1997 }
1998 
1999 /++ Ditto +/
2000 auto redBlackTree(alias less, bool allowDuplicates, E)(E[] elems...)
2001 if (is(typeof(binaryFun!less(E.init, E.init))))
2002 {
2003     //We shouldn't need to instantiate less here, but for some reason,
2004     //dmd can't handle it if we don't (even though the template which
2005     //takes less but not allowDuplicates works just fine).
2006     return new RedBlackTree!(E, binaryFun!less, allowDuplicates)(elems);
2007 }
2008 
2009 /++ Ditto +/
2010 auto redBlackTree(Stuff)(Stuff range)
2011 if (isInputRange!Stuff && !isArray!(Stuff))
2012 {
2013     return new RedBlackTree!(ElementType!Stuff)(range);
2014 }
2015 
2016 /++ Ditto +/
2017 auto redBlackTree(bool allowDuplicates, Stuff)(Stuff range)
2018 if (isInputRange!Stuff && !isArray!(Stuff))
2019 {
2020     return new RedBlackTree!(ElementType!Stuff, "a < b", allowDuplicates)(range);
2021 }
2022 
2023 /++ Ditto +/
2024 auto redBlackTree(alias less, Stuff)(Stuff range)
2025 if ( is(typeof(binaryFun!less((ElementType!Stuff).init, (ElementType!Stuff).init)))
2026     && isInputRange!Stuff && !isArray!(Stuff))
2027 {
2028     return new RedBlackTree!(ElementType!Stuff, less)(range);
2029 }
2030 
2031 /++ Ditto +/
2032 auto redBlackTree(alias less, bool allowDuplicates, Stuff)(Stuff range)
2033 if ( is(typeof(binaryFun!less((ElementType!Stuff).init, (ElementType!Stuff).init)))
2034     && isInputRange!Stuff && !isArray!(Stuff))
2035 {
2036     //We shouldn't need to instantiate less here, but for some reason,
2037     //dmd can't handle it if we don't (even though the template which
2038     //takes less but not allowDuplicates works just fine).
2039     return new RedBlackTree!(ElementType!Stuff, binaryFun!less, allowDuplicates)(range);
2040 }
2041 
2042 ///
2043 @safe pure unittest
2044 {
2045     import std.range : iota;
2046 
2047     auto rbt1 = redBlackTree(0, 1, 5, 7);
2048     auto rbt2 = redBlackTree!string("hello", "world");
2049     auto rbt3 = redBlackTree!true(0, 1, 5, 7, 5);
2050     auto rbt4 = redBlackTree!"a > b"(0, 1, 5, 7);
2051     auto rbt5 = redBlackTree!("a > b", true)(0.1, 1.3, 5.9, 7.2, 5.9);
2052 
2053     // also works with ranges
2054     auto rbt6 = redBlackTree(iota(3));
2055     auto rbt7 = redBlackTree!true(iota(3));
2056     auto rbt8 = redBlackTree!"a > b"(iota(3));
2057     auto rbt9 = redBlackTree!("a > b", true)(iota(3));
2058 }
2059 
2060 //Combinations not in examples.
2061 @system pure unittest
2062 {
2063     auto rbt1 = redBlackTree!(true, string)("hello", "hello");
2064     auto rbt2 = redBlackTree!((a, b){return a < b;}, double)(5.1, 2.3);
2065     auto rbt3 = redBlackTree!("a > b", true, string)("hello", "world");
2066 }
2067 
2068 //Range construction.
2069 @safe pure unittest
2070 {
2071     import std.algorithm.comparison : equal;
2072     import std.range : iota;
2073     auto rbt = new RedBlackTree!(int, "a > b")(iota(5));
2074     assert(equal(rbt[], [4, 3, 2, 1, 0]));
2075 }
2076 
2077 
2078 // construction with arrays
2079 @safe pure unittest
2080 {
2081     import std.algorithm.comparison : equal;
2082 
2083     auto rbt = redBlackTree!"a > b"([0, 1, 2, 3, 4]);
2084     assert(equal(rbt[], [4, 3, 2, 1, 0]));
2085 
2086     auto rbt2 = redBlackTree!"a > b"(["a", "b"]);
2087     assert(equal(rbt2[], ["b", "a"]));
2088 
2089     auto rbt3 = redBlackTree!"a > b"([1, 2]);
2090     assert(equal(rbt3[], [2, 1]));
2091 
2092     auto rbt4 = redBlackTree([0, 1, 7, 5]);
2093     assert(equal(rbt4[], [0, 1, 5, 7]));
2094 
2095     auto rbt5 = redBlackTree(["hello", "world"]);
2096     assert(equal(rbt5[], ["hello", "world"]));
2097 
2098     auto rbt6 = redBlackTree!true([0, 1, 5, 7, 5]);
2099     assert(equal(rbt6[], [0, 1, 5, 5, 7]));
2100 
2101     auto rbt7 = redBlackTree!"a > b"([0, 1, 5, 7]);
2102     assert(equal(rbt7[], [7, 5, 1, 0]));
2103 
2104     auto rbt8 = redBlackTree!("a > b", true)([0.1, 1.3, 5.9, 7.2, 5.9]);
2105     assert(equal(rbt8[], [7.2, 5.9, 5.9, 1.3, 0.1]));
2106 }
2107 
2108 // convenience wrapper range construction
2109 @safe pure unittest
2110 {
2111     import std.algorithm.comparison : equal;
2112     import std.range : chain, iota;
2113 
2114     auto rbt = redBlackTree(iota(3));
2115     assert(equal(rbt[], [0, 1, 2]));
2116 
2117     auto rbt2 = redBlackTree!"a > b"(iota(2));
2118     assert(equal(rbt2[], [1, 0]));
2119 
2120     auto rbt3 = redBlackTree(chain([0, 1], [7, 5]));
2121     assert(equal(rbt3[], [0, 1, 5, 7]));
2122 
2123     auto rbt4 = redBlackTree(chain(["hello"], ["world"]));
2124     assert(equal(rbt4[], ["hello", "world"]));
2125 
2126     auto rbt5 = redBlackTree!true(chain([0, 1], [5, 7, 5]));
2127     assert(equal(rbt5[], [0, 1, 5, 5, 7]));
2128 
2129     auto rbt6 = redBlackTree!("a > b", true)(chain([0.1, 1.3], [5.9, 7.2, 5.9]));
2130     assert(equal(rbt6[], [7.2, 5.9, 5.9, 1.3, 0.1]));
2131 }
2132 
2133 @safe pure unittest
2134 {
2135     import std.array : array;
2136 
2137     auto rt1 = redBlackTree(5, 4, 3, 2, 1);
2138     assert(rt1.length == 5);
2139     assert(array(rt1[]) == [1, 2, 3, 4, 5]);
2140 
2141     auto rt2 = redBlackTree!"a > b"(1.1, 2.1);
2142     assert(rt2.length == 2);
2143     assert(array(rt2[]) == [2.1, 1.1]);
2144 
2145     auto rt3 = redBlackTree!true(5, 5, 4);
2146     assert(rt3.length == 3);
2147     assert(array(rt3[]) == [4, 5, 5]);
2148 
2149     auto rt4 = redBlackTree!string("hello", "hello");
2150     assert(rt4.length == 1);
2151     assert(array(rt4[]) == ["hello"]);
2152 }
2153 
2154 @system unittest
2155 {
2156     import std.conv : to;
2157 
2158     auto rt1 = redBlackTree!string();
2159     assert(rt1.to!string == "RedBlackTree([])");
2160 
2161     auto rt2 = redBlackTree!string("hello");
2162     assert(rt2.to!string == "RedBlackTree([\"hello\"])");
2163 
2164     auto rt3 = redBlackTree!string("hello", "world", "!");
2165     assert(rt3.to!string == "RedBlackTree([\"!\", \"hello\", \"world\"])");
2166 
2167     // type deduction can be done automatically
2168     auto rt4 = redBlackTree(["hello"]);
2169     assert(rt4.to!string == "RedBlackTree([\"hello\"])");
2170 }
2171 
2172 //constness checks
2173 @safe pure unittest
2174 {
2175     const rt1 = redBlackTree(5,4,3,2,1);
2176     void allQualifiers() pure nothrow @safe @nogc {
2177         assert(!rt1.empty);
2178         assert(rt1.length == 5);
2179         assert(5 in rt1);
2180     }
2181     allQualifiers();
2182 
2183     static assert(is(typeof(rt1.upperBound(3).front) == const(int)));
2184     import std.algorithm.comparison : equal;
2185     assert(rt1.upperBound(3).equal([4, 5]));
2186     assert(rt1.lowerBound(3).equal([1, 2]));
2187     assert(rt1.equalRange(3).equal([3]));
2188     assert(rt1[].equal([1, 2, 3, 4, 5]));
2189 }
2190 
2191 //immutable checks
2192 @safe pure unittest
2193 {
2194     immutable rt1 = redBlackTree(5,4,3,2,1);
2195     static assert(is(typeof(rt1.empty)));
2196     static assert(is(typeof(rt1.length)));
2197     static assert(is(typeof(5 in rt1)));
2198 
2199     static assert(is(typeof(rt1.upperBound(3).front) == immutable(int)));
2200     import std.algorithm.comparison : equal;
2201     assert(rt1.upperBound(2).equal([3, 4, 5]));
2202 }
2203 
2204 // https://issues.dlang.org/show_bug.cgi?id=15941
2205 @safe pure unittest
2206 {
2207     class C {}
2208     RedBlackTree!(C, "cast(void*)a < cast(void*) b") tree;
2209 }
2210 
2211 // const/immutable elements (https://issues.dlang.org/show_bug.cgi?id=17519)
2212 @safe pure unittest
2213 {
2214     RedBlackTree!(immutable int) t1;
2215     RedBlackTree!(const int) t2;
2216 
2217     import std.algorithm.iteration : map;
2218     static struct S { int* p; }
2219     auto t3 = new RedBlackTree!(immutable S, (a, b) => *a.p < *b.p);
2220     t3.insert([1, 2, 3].map!(x => immutable S(new int(x))));
2221     static assert(!__traits(compiles, *t3.front.p = 4));
2222     assert(*t3.front.p == 1);
2223 }
2224 
2225 // make sure the comparator can be a delegate
2226 @safe pure unittest
2227 {
2228     import std.algorithm.comparison : equal;
2229 
2230     auto t = new RedBlackTree!(int, delegate(a, b) => a > b);
2231     t.insert([1, 3, 5, 4, 2]);
2232     assert(t[].equal([5, 4, 3, 2, 1]));
2233 }