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     ref @property Elem front()
683     {
684         return _begin.value;
685     }
686 
687     /**
688      * Returns the last element in the range
689      */
690     ref @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  * Care should also be taken to not modify elements in the tree (e.g. via `front` /
741  * `back`, which return by `ref`) in a way which would affect the order defined by
742  * the `less` predicate.
743  *
744  * If `allowDuplicates` is set to `true`, then inserting the same element more than
745  * once continues to add more elements.  If it is `false`, duplicate elements are
746  * ignored on insertion.  If duplicates are allowed, then new elements are
747  * inserted after all existing duplicate elements.
748  */
749 final class RedBlackTree(T, alias less = "a < b", bool allowDuplicates = false)
750 if (is(typeof((ref const T a) => binaryFun!less(a, a))))
751 {
752     import std.meta : allSatisfy;
753     import std.range : Take;
754     import std.range.primitives : isInputRange, walkLength;
755     import std.traits : isIntegral, isDynamicArray, isImplicitlyConvertible;
756 
757     alias _less = binaryFun!less;
758 
759     version (StdUnittest)
760     {
761         static if (is(typeof(less) == string))
762         {
763             private enum doUnittest = is(byte : T) && isIntegral!T && (less == "a < b" || less == "a > b");
764         }
765         else
766             enum doUnittest = false;
767 
768         // note, this must be final so it does not affect the vtable layout
769         bool arrayEqual(T[] arr)
770         {
771             if (walkLength(this[]) == arr.length)
772             {
773                 foreach (v; arr)
774                 {
775                     if (!(v in this))
776                         return false;
777                 }
778                 return true;
779             }
780             return false;
781         }
782     }
783     else
784     {
785         private enum doUnittest = false;
786     }
787 
788     /**
789       * Element type for the tree
790       */
791     alias Elem = T;
792 
793     // used for convenience
794     private alias RBNode = .RBNode!Elem;
795     private alias Node = RBNode.Node;
796 
797     private Node   _end;
798     private Node   _begin;
799     private size_t _length;
800 
801     private void _setup()
802     {
803         //Make sure that _setup isn't run more than once.
804         assert(!_end, "Setup must only be run once");
805         _begin = _end = allocate();
806     }
807 
808     static private Node allocate()
809     {
810         return new RBNode;
811     }
812 
813     static private Node allocate(Elem v)
814     {
815         return new RBNode(null, null, null, v);
816     }
817 
818     /**
819      * The range types for `RedBlackTree`
820      */
821     alias Range = RBRange!(RBNode*);
822     alias ConstRange = RBRange!(const(RBNode)*); /// Ditto
823     alias ImmutableRange = RBRange!(immutable(RBNode)*); /// Ditto
824 
825     static if (doUnittest) @safe pure unittest
826     {
827         import std.algorithm.comparison : equal;
828         import std.range.primitives;
829         auto ts = new RedBlackTree(1, 2, 3, 4, 5);
830         assert(ts.length == 5);
831         auto r = ts[];
832 
833         static if (less == "a < b")
834             auto vals = [1, 2, 3, 4, 5];
835         else
836             auto vals = [5, 4, 3, 2, 1];
837         assert(equal(r, vals));
838 
839         assert(r.front == vals.front);
840         assert(r.back != r.front);
841         auto oldfront = r.front;
842         auto oldback = r.back;
843         r.popFront();
844         r.popBack();
845         assert(r.front != r.back);
846         assert(r.front != oldfront);
847         assert(r.back != oldback);
848         assert(ts.length == 5);
849     }
850 
851     // find a node based on an element value
852     private inout(RBNode)* _find(Elem e) inout
853     {
854         static if (allowDuplicates)
855         {
856             inout(RBNode)* cur = _end.left;
857             inout(RBNode)* result = null;
858             while (cur)
859             {
860                 if (_less(cur.value, e))
861                     cur = cur.right;
862                 else if (_less(e, cur.value))
863                     cur = cur.left;
864                 else
865                 {
866                     // want to find the left-most element
867                     result = cur;
868                     cur = cur.left;
869                 }
870             }
871             return result;
872         }
873         else
874         {
875             inout(RBNode)* cur = _end.left;
876             while (cur)
877             {
878                 if (_less(cur.value, e))
879                     cur = cur.right;
880                 else if (_less(e, cur.value))
881                     cur = cur.left;
882                 else
883                     return cur;
884             }
885             return null;
886         }
887     }
888 
889     /* add an element to the tree, returns the node added, or the existing node
890      * if it has already been added and allowDuplicates is false
891      * Returns:
892      *   true if node was added
893      */
894     private bool _add(return scope Elem n)
895     {
896         Node result;
897         static if (!allowDuplicates)
898             bool added = true;
899 
900         if (!_end.left)
901         {
902             result = allocate(n);
903             (() @trusted { _end.left = _begin = result; }) ();
904         }
905         else
906         {
907             Node newParent = _end.left;
908             Node nxt;
909             while (true)
910             {
911                 if (_less(n, newParent.value))
912                 {
913                     nxt = newParent.left;
914                     if (nxt is null)
915                     {
916                         //
917                         // add to right of new parent
918                         //
919                         result = allocate(n);
920                         (() @trusted { newParent.left = result; }) ();
921                         break;
922                     }
923                 }
924                 else
925                 {
926                     static if (!allowDuplicates)
927                     {
928                         if (!_less(newParent.value, n))
929                         {
930                             result = newParent;
931                             added = false;
932                             break;
933                         }
934                     }
935                     nxt = newParent.right;
936                     if (nxt is null)
937                     {
938                         //
939                         // add to right of new parent
940                         //
941                         result = allocate(n);
942                         (() @trusted { newParent.right = result; }) ();
943                         break;
944                     }
945                 }
946                 newParent = nxt;
947             }
948             if (_begin.left)
949                 _begin = _begin.left;
950         }
951         static if (allowDuplicates)
952         {
953             result.setColor(_end);
954             debug(RBDoChecks)
955                 check();
956             ++_length;
957             return true;
958         }
959         else
960         {
961             if (added)
962             {
963                 ++_length;
964                 result.setColor(_end);
965             }
966             debug(RBDoChecks)
967                 check();
968             return added;
969         }
970     }
971 
972 
973     /**
974      * Check if any elements exist in the container.  Returns `false` if at least
975      * one element exists.
976      */
977     @property bool empty() const // pure, nothrow, @safe, @nogc: are inferred
978     {
979         return _end.left is null;
980     }
981 
982     /++
983         Returns the number of elements in the container.
984 
985         Complexity: $(BIGOH 1).
986     +/
987     @property size_t length() const
988     {
989         return _length;
990     }
991 
992     /**
993      * Duplicate this container.  The resulting container contains a shallow
994      * copy of the elements.
995      *
996      * Complexity: $(BIGOH n)
997      */
998     @property RedBlackTree dup()
999     {
1000         return new RedBlackTree(_end.dup(), _length);
1001     }
1002 
1003     static if (doUnittest) @safe pure unittest
1004     {
1005         import std.algorithm.comparison : equal;
1006         auto ts = new RedBlackTree(1, 2, 3, 4, 5);
1007         assert(ts.length == 5);
1008         auto ts2 = ts.dup;
1009         assert(ts2.length == 5);
1010         assert(equal(ts[], ts2[]));
1011         ts2.insert(cast(Elem) 6);
1012         assert(!equal(ts[], ts2[]));
1013         assert(ts.length == 5 && ts2.length == 6);
1014     }
1015 
1016     /**
1017      * Fetch a range that spans all the elements in the container.
1018      *
1019      * Complexity: $(BIGOH 1)
1020      */
1021     Range opSlice()
1022     {
1023         return Range(_begin, _end);
1024     }
1025 
1026     /// Ditto
1027     ConstRange opSlice() const
1028     {
1029         return ConstRange(_begin, _end);
1030     }
1031 
1032     /// Ditto
1033     ImmutableRange opSlice() immutable
1034     {
1035         return ImmutableRange(_begin, _end);
1036     }
1037 
1038     /**
1039      * The front element in the container
1040      *
1041      * Complexity: $(BIGOH 1)
1042      */
1043     ref inout(Elem) front() inout
1044     {
1045         return _begin.value;
1046     }
1047 
1048     /**
1049      * The last element in the container
1050      *
1051      * Complexity: $(BIGOH log(n))
1052      */
1053     ref inout(Elem) back() inout
1054     {
1055         return _end.prev.value;
1056     }
1057 
1058     /++
1059         `in` operator. Check to see if the given element exists in the
1060         container.
1061 
1062        Complexity: $(BIGOH log(n))
1063      +/
1064     bool opBinaryRight(string op)(Elem e) const
1065     if (op == "in")
1066     {
1067         return _find(e) !is null;
1068     }
1069 
1070     static if (doUnittest) @safe pure unittest
1071     {
1072         auto ts = new RedBlackTree(1, 2, 3, 4, 5);
1073         assert(cast(Elem) 3 in ts);
1074         assert(cast(Elem) 6 !in ts);
1075     }
1076 
1077     /**
1078      * Compares two trees for equality.
1079      *
1080      * Complexity: $(BIGOH n)
1081      */
1082     override bool opEquals(Object rhs)
1083     {
1084         import std.algorithm.comparison : equal;
1085 
1086         RedBlackTree that = cast(RedBlackTree) rhs;
1087         if (that is null) return false;
1088 
1089         // If there aren't the same number of nodes, we can't be equal.
1090         if (this._length != that._length) return false;
1091 
1092         auto thisRange = this[];
1093         auto thatRange = that[];
1094         return equal!((Elem a, Elem b) => !_less(a,b) && !_less(b,a))
1095                      (thisRange, thatRange);
1096     }
1097 
1098     static if (doUnittest) @system unittest
1099     {
1100         auto t1 = new RedBlackTree(1,2,3,4);
1101         auto t2 = new RedBlackTree(1,2,3,4);
1102         auto t3 = new RedBlackTree(1,2,3,5);
1103         auto t4 = new RedBlackTree(1,2,3,4,5);
1104         auto o = new Object();
1105 
1106         assert(t1 == t1);
1107         assert(t1 == t2);
1108         assert(t1 != t3);
1109         assert(t1 != t4);
1110         assert(t1 != o);  // pathological case, must not crash
1111     }
1112 
1113     /**
1114      * Generates a hash for the tree. Note that with a custom comparison function
1115      * it may not hold that if two rbtrees are equal, the hashes of the trees
1116      * will be equal.
1117      */
1118     override size_t toHash() nothrow @safe
1119     {
1120         size_t hash = cast(size_t) 0x6b63_616c_4264_6552UL;
1121         foreach (ref e; this[])
1122             // As in boost::hash_combine
1123             // https://www.boost.org/doc/libs/1_55_0/doc/html/hash/reference.html#boost.hash_combine
1124             hash += .hashOf(e) + 0x9e3779b9 + (hash << 6) + (hash >>> 2);
1125         return hash;
1126     }
1127 
1128     static if (doUnittest) @system unittest
1129     {
1130         auto t1 = new RedBlackTree(1,2,3,4);
1131         auto t2 = new RedBlackTree(1,2,3,4);
1132         auto t3 = new RedBlackTree(1,2,3,5);
1133         auto t4 = new RedBlackTree(1,2,3,4,5);
1134 
1135         assert(t1.toHash() == t2.toHash);
1136 
1137         assert(t1.toHash() != t3.toHash);
1138         assert(t2.toHash() != t3.toHash);
1139 
1140         assert(t3.toHash() != t4.toHash);
1141         assert(t1.toHash() != t4.toHash);
1142 
1143         // empty tree
1144         auto t5 = new RedBlackTree();
1145         auto t6 = new RedBlackTree();
1146 
1147         assert(t5.toHash() == t6.toHash());
1148 
1149         auto t7 = new RedBlackTree!string("red", "black");
1150         auto t8 = new RedBlackTree!string("white", "black");
1151         auto t9 = new RedBlackTree!string("red", "black");
1152 
1153         assert(t7.toHash() == t9.toHash());
1154         assert(t7.toHash() != t8.toHash());
1155 
1156         static struct MyInt
1157         {
1158             int x;
1159 
1160           @safe:
1161 
1162             this(int init_x)
1163             {
1164                 x = init_x;
1165             }
1166 
1167             size_t toHash() const nothrow
1168             {
1169                 return typeid(x).getHash(&x) ^ 0xF0F0_F0F0;
1170             }
1171 
1172             int opCmp(const MyInt that) const
1173             {
1174                 return (x > that.x) - (x < that.x);
1175             }
1176 
1177             bool opEquals(const MyInt that) const
1178             {
1179                 return (this.x == that.x);
1180             }
1181         }
1182 
1183         auto rbt1 = new RedBlackTree!MyInt(MyInt(1), MyInt(2), MyInt(3), MyInt(4));
1184         auto rbt2 = new RedBlackTree!MyInt(MyInt(1), MyInt(2), MyInt(3), MyInt(4));
1185 
1186         assert(rbt1.toHash() == rbt2.toHash());
1187         assert(rbt1.toHash() != t1.toHash());
1188 
1189         auto rbt3 = new RedBlackTree!MyInt(MyInt(4), MyInt(2), MyInt(3), MyInt(4));
1190 
1191         assert(rbt1.toHash() != rbt3.toHash());
1192 
1193         class MyInt2
1194         {
1195             int x;
1196 
1197             this(int init_x)
1198             {
1199                 x = init_x;
1200             }
1201 
1202             override size_t toHash() const @safe nothrow
1203             {
1204                 return typeid(x).getHash(&x) ^ 0xF0F0_F0F0;
1205             }
1206 
1207             int opCmp(const MyInt2 that) const
1208             {
1209                 return (x > that.x) - (x < that.x);
1210             }
1211 
1212             bool opEquals(const MyInt2 that) const
1213             {
1214                 return (this.x == that.x);
1215             }
1216         }
1217 
1218         static bool nullSafeLess(scope const MyInt2 a, scope const MyInt2 b)
1219         {
1220             return a is null ? b !is null : (b !is null && a < b);
1221         }
1222 
1223         auto rbt4 = new RedBlackTree!MyInt2(new MyInt2(1), new MyInt2(9), new MyInt2(3), new MyInt2(42));
1224         auto rbt5 = new RedBlackTree!MyInt2(new MyInt2(1), new MyInt2(9), new MyInt2(3), new MyInt2(42));
1225         auto rbt6 = new RedBlackTree!(MyInt2, nullSafeLess)(new MyInt2(9), new MyInt2(3), new MyInt2(42));
1226         auto rbt7 = new RedBlackTree!(MyInt2, nullSafeLess)(null);
1227 
1228         assert(rbt6.toHash() != rbt5.toHash());
1229         assert(rbt6.toHash() != rbt4.toHash());
1230         assert(rbt6.toHash() != rbt7.toHash());
1231         assert(rbt4.toHash() == rbt5.toHash());
1232 
1233         auto rbt8 = new RedBlackTree!(MyInt2, nullSafeLess)(null, new MyInt2(9), null, new MyInt2(42));
1234         auto rbt9 = new RedBlackTree!(MyInt2, nullSafeLess)(null, new MyInt2(9), null, new MyInt2(42));
1235         auto rbt10 = new RedBlackTree!(MyInt2, nullSafeLess)(new MyInt2(94), null, new MyInt2(147));
1236 
1237         assert(rbt8.toHash() == rbt9.toHash());
1238         assert(rbt8.toHash() != rbt10.toHash());
1239     }
1240 
1241     /**
1242      * Removes all elements from the container.
1243      *
1244      * Complexity: $(BIGOH 1)
1245      */
1246     void clear()
1247     {
1248         _end.left = null;
1249         _begin = _end;
1250         _length = 0;
1251     }
1252 
1253     static if (doUnittest) @safe pure unittest
1254     {
1255         auto ts = new RedBlackTree(1,2,3,4,5);
1256         assert(ts.length == 5);
1257         ts.clear();
1258         assert(ts.empty && ts.length == 0);
1259     }
1260 
1261     /**
1262      * Insert a single element in the container.  Note that this does not
1263      * invalidate any ranges currently iterating the container.
1264      *
1265      * Returns: The number of elements inserted.
1266      *
1267      * Complexity: $(BIGOH log(n))
1268      */
1269     size_t stableInsert(Stuff)(Stuff stuff)
1270     if (isImplicitlyConvertible!(Stuff, Elem))
1271     {
1272         static if (allowDuplicates)
1273         {
1274             _add(stuff);
1275             return 1;
1276         }
1277         else
1278         {
1279             return _add(stuff);
1280         }
1281     }
1282 
1283     /**
1284      * Insert a range of elements in the container.  Note that this does not
1285      * invalidate any ranges currently iterating the container.
1286      *
1287      * Returns: The number of elements inserted.
1288      *
1289      * Complexity: $(BIGOH m * log(n))
1290      */
1291     size_t stableInsert(Stuff)(scope Stuff stuff)
1292     if (isInputRange!Stuff &&
1293         isImplicitlyConvertible!(ElementType!Stuff, Elem))
1294     {
1295         size_t result = 0;
1296         static if (allowDuplicates)
1297         {
1298             foreach (e; stuff)
1299             {
1300                 ++result;
1301                 _add(e);
1302             }
1303         }
1304         else
1305         {
1306             foreach (e; stuff)
1307             {
1308                 result += _add(e);
1309             }
1310         }
1311         return result;
1312     }
1313 
1314     /// ditto
1315     alias insert = stableInsert;
1316 
1317     static if (doUnittest) @safe pure unittest
1318     {
1319         auto ts = new RedBlackTree(2,1,3,4,5,2,5);
1320         static if (allowDuplicates)
1321         {
1322             assert(ts.length == 7);
1323             assert(ts.stableInsert(cast(Elem[])[7, 8, 6, 9, 10, 8]) == 6);
1324             assert(ts.length == 13);
1325             assert(ts.stableInsert(cast(Elem) 11) == 1 && ts.length == 14);
1326             assert(ts.stableInsert(cast(Elem) 7) == 1 && ts.length == 15);
1327 
1328             static if (less == "a < b")
1329                 assert(ts.arrayEqual([1,2,2,3,4,5,5,6,7,7,8,8,9,10,11]));
1330             else
1331                 assert(ts.arrayEqual([11,10,9,8,8,7,7,6,5,5,4,3,2,2,1]));
1332         }
1333         else
1334         {
1335             assert(ts.length == 5);
1336             Elem[] elems = [7, 8, 6, 9, 10, 8];
1337             assert(ts.stableInsert(elems) == 5);
1338             assert(ts.length == 10);
1339             assert(ts.stableInsert(cast(Elem) 11) == 1 && ts.length == 11);
1340             assert(ts.stableInsert(cast(Elem) 7) == 0 && ts.length == 11);
1341 
1342             static if (less == "a < b")
1343                 assert(ts.arrayEqual([1,2,3,4,5,6,7,8,9,10,11]));
1344             else
1345                 assert(ts.arrayEqual([11,10,9,8,7,6,5,4,3,2,1]));
1346         }
1347     }
1348 
1349     /**
1350      * Remove an element from the container and return its value.
1351      *
1352      * Complexity: $(BIGOH log(n))
1353      */
1354     Elem removeAny()
1355     {
1356         scope(success)
1357             --_length;
1358         auto n = _begin;
1359         auto result = n.value;
1360         _begin = n.remove(_end);
1361         debug(RBDoChecks)
1362             check();
1363         return result;
1364     }
1365 
1366     static if (doUnittest) @safe pure unittest
1367     {
1368         auto ts = new RedBlackTree(1,2,3,4,5);
1369         assert(ts.length == 5);
1370         auto x = ts.removeAny();
1371         assert(ts.length == 4);
1372         Elem[] arr;
1373         foreach (Elem i; 1 .. 6)
1374             if (i != x) arr ~= i;
1375         assert(ts.arrayEqual(arr));
1376     }
1377 
1378     /**
1379      * Remove the front element from the container.
1380      *
1381      * Complexity: $(BIGOH log(n))
1382      */
1383     void removeFront()
1384     {
1385         scope(success)
1386             --_length;
1387         _begin = _begin.remove(_end);
1388         debug(RBDoChecks)
1389             check();
1390     }
1391 
1392     /**
1393      * Remove the back element from the container.
1394      *
1395      * Complexity: $(BIGOH log(n))
1396      */
1397     void removeBack()
1398     {
1399         scope(success)
1400             --_length;
1401         auto lastnode = _end.prev;
1402         if (lastnode is _begin)
1403             _begin = _begin.remove(_end);
1404         else
1405             lastnode.remove(_end);
1406         debug(RBDoChecks)
1407             check();
1408     }
1409 
1410     static if (doUnittest) @safe pure unittest
1411     {
1412         auto ts = new RedBlackTree(1,2,3,4,5);
1413         assert(ts.length == 5);
1414         ts.removeBack();
1415         assert(ts.length == 4);
1416 
1417         static if (less == "a < b")
1418             assert(ts.arrayEqual([1,2,3,4]));
1419         else
1420             assert(ts.arrayEqual([2,3,4,5]));
1421 
1422         ts.removeFront();
1423         assert(ts.arrayEqual([2,3,4]) && ts.length == 3);
1424     }
1425 
1426     /++
1427         Removes the given range from the container.
1428 
1429         Returns: A range containing all of the elements that were after the
1430                  given range.
1431 
1432         Complexity: $(BIGOH m * log(n)) (where m is the number of elements in
1433                     the range)
1434      +/
1435     Range remove(Range r)
1436     {
1437         auto b = r._begin;
1438         auto e = r._end;
1439         if (_begin is b)
1440             _begin = e;
1441         while (b !is e)
1442         {
1443             b = b.remove(_end);
1444             --_length;
1445         }
1446         debug(RBDoChecks)
1447             check();
1448         return Range(e, _end);
1449     }
1450 
1451     static if (doUnittest) @safe pure unittest
1452     {
1453         import std.algorithm.comparison : equal;
1454         auto ts = new RedBlackTree(1,2,3,4,5);
1455         assert(ts.length == 5);
1456         auto r = ts[];
1457         r.popFront();
1458         r.popBack();
1459         assert(ts.length == 5);
1460         auto r2 = ts.remove(r);
1461         assert(ts.length == 2);
1462         assert(ts.arrayEqual([1,5]));
1463 
1464         static if (less == "a < b")
1465             assert(equal(r2, [5]));
1466         else
1467             assert(equal(r2, [1]));
1468     }
1469 
1470     /++
1471         Removes the given `Take!Range` from the container
1472 
1473         Returns: A range containing all of the elements that were after the
1474                  given range.
1475 
1476         Complexity: $(BIGOH m * log(n)) (where m is the number of elements in
1477                     the range)
1478      +/
1479     Range remove(Take!Range r)
1480     {
1481         immutable isBegin = (r.source._begin is _begin);
1482         auto b = r.source._begin;
1483 
1484         while (!r.empty)
1485         {
1486             r.popFront();
1487             b = b.remove(_end);
1488             --_length;
1489         }
1490 
1491         if (isBegin)
1492             _begin = b;
1493 
1494         return Range(b, _end);
1495     }
1496 
1497     static if (doUnittest) @safe pure unittest
1498     {
1499         import std.algorithm.comparison : equal;
1500         import std.range : take;
1501         auto ts = new RedBlackTree(1,2,3,4,5);
1502         auto r = ts[];
1503         r.popFront();
1504         assert(ts.length == 5);
1505         auto r2 = ts.remove(take(r, 0));
1506 
1507         static if (less == "a < b")
1508         {
1509             assert(equal(r2, [2,3,4,5]));
1510             auto r3 = ts.remove(take(r, 2));
1511             assert(ts.arrayEqual([1,4,5]) && ts.length == 3);
1512             assert(equal(r3, [4,5]));
1513         }
1514         else
1515         {
1516             assert(equal(r2, [4,3,2,1]));
1517             auto r3 = ts.remove(take(r, 2));
1518             assert(ts.arrayEqual([5,2,1]) && ts.length == 3);
1519             assert(equal(r3, [2,1]));
1520         }
1521     }
1522 
1523     /++
1524        Removes elements from the container that are equal to the given values
1525        according to the less comparator. One element is removed for each value
1526        given which is in the container. If `allowDuplicates` is true,
1527        duplicates are removed only if duplicate values are given.
1528 
1529        Returns: The number of elements removed.
1530 
1531        Complexity: $(BIGOH m log(n)) (where m is the number of elements to remove)
1532 
1533        Example:
1534 $(RUNNABLE_EXAMPLE
1535 --------------------
1536 import std.algorithm, std.container;
1537 
1538 auto rbt = redBlackTree!true(0, 1, 1, 1, 4, 5, 7);
1539 rbt.removeKey(1, 4, 7);
1540 assert(equal(rbt[], [0, 1, 1, 5]));
1541 
1542 rbt.removeKey(1, 1, 0);
1543 assert(equal(rbt[], [5]));
1544 --------------------
1545 )
1546       +/
1547     size_t removeKey(U...)(U elems)
1548     if (allSatisfy!(isImplicitlyConvertibleToElem, U))
1549     {
1550         Elem[U.length] toRemove = [elems];
1551         return removeKey(toRemove[]);
1552     }
1553 
1554     /++ Ditto +/
1555     size_t removeKey(U)(scope U[] elems)
1556     if (isImplicitlyConvertible!(U, Elem))
1557     {
1558         immutable lenBefore = length;
1559 
1560         foreach (e; elems)
1561         {
1562             auto beg = _firstGreaterEqual(e);
1563             if (beg is _end || _less(e, beg.value))
1564                 // no values are equal
1565                 continue;
1566             immutable isBegin = (beg is _begin);
1567             beg = beg.remove(_end);
1568             if (isBegin)
1569                 _begin = beg;
1570             --_length;
1571         }
1572 
1573         return lenBefore - length;
1574     }
1575 
1576     /++ Ditto +/
1577     size_t removeKey(Stuff)(Stuff stuff)
1578     if (isInputRange!Stuff &&
1579         isImplicitlyConvertible!(ElementType!Stuff, Elem) &&
1580         !isDynamicArray!Stuff)
1581     {
1582         import std.array : array;
1583         //We use array in case stuff is a Range from this RedBlackTree - either
1584         //directly or indirectly.
1585         return removeKey(array(stuff));
1586     }
1587 
1588     //Helper for removeKey.
1589     private template isImplicitlyConvertibleToElem(U)
1590     {
1591         enum isImplicitlyConvertibleToElem = isImplicitlyConvertible!(U, Elem);
1592     }
1593 
1594     static if (doUnittest) @safe pure unittest
1595     {
1596         import std.algorithm.comparison : equal;
1597         import std.range : take;
1598         auto rbt = new RedBlackTree(5, 4, 3, 7, 2, 1, 7, 6, 2, 19, 45);
1599 
1600         //The cast(Elem) is because these tests are instantiated with a variety
1601         //of numeric types, and the literals are all int, which is not always
1602         //implicitly convertible to Elem (e.g. short).
1603         static if (allowDuplicates)
1604         {
1605             assert(rbt.length == 11);
1606             assert(rbt.removeKey(cast(Elem) 4) == 1 && rbt.length == 10);
1607             assert(rbt.arrayEqual([1,2,2,3,5,6,7,7,19,45]) && rbt.length == 10);
1608 
1609             assert(rbt.removeKey(cast(Elem) 6, cast(Elem) 2, cast(Elem) 1) == 3);
1610             assert(rbt.arrayEqual([2,3,5,7,7,19,45]) && rbt.length == 7);
1611 
1612             assert(rbt.removeKey(cast(Elem)(42)) == 0 && rbt.length == 7);
1613             assert(rbt.removeKey(take(rbt[], 3)) == 3 && rbt.length == 4);
1614 
1615             static if (less == "a < b")
1616                 assert(equal(rbt[], [7,7,19,45]));
1617             else
1618                 assert(equal(rbt[], [7,5,3,2]));
1619         }
1620         else
1621         {
1622             assert(rbt.length == 9);
1623             assert(rbt.removeKey(cast(Elem) 4) == 1 && rbt.length == 8);
1624             assert(rbt.arrayEqual([1,2,3,5,6,7,19,45]));
1625 
1626             assert(rbt.removeKey(cast(Elem) 6, cast(Elem) 2, cast(Elem) 1) == 3);
1627             assert(rbt.arrayEqual([3,5,7,19,45]) && rbt.length == 5);
1628 
1629             assert(rbt.removeKey(cast(Elem)(42)) == 0 && rbt.length == 5);
1630             assert(rbt.removeKey(take(rbt[], 3)) == 3 && rbt.length == 2);
1631 
1632             static if (less == "a < b")
1633                 assert(equal(rbt[], [19,45]));
1634             else
1635                 assert(equal(rbt[], [5,3]));
1636         }
1637     }
1638 
1639     // find the first node where the value is > e
1640     private inout(RBNode)* _firstGreater(Elem e) inout
1641     {
1642         // can't use _find, because we cannot return null
1643         auto cur = _end.left;
1644         inout(RBNode)* result = _end;
1645         while (cur)
1646         {
1647             if (_less(e, cur.value))
1648             {
1649                 result = cur;
1650                 cur = cur.left;
1651             }
1652             else
1653                 cur = cur.right;
1654         }
1655         return result;
1656     }
1657 
1658     // find the first node where the value is >= e
1659     private inout(RBNode)* _firstGreaterEqual(Elem e) inout
1660     {
1661         // can't use _find, because we cannot return null.
1662         auto cur = _end.left;
1663         inout(RBNode)* result = _end;
1664         while (cur)
1665         {
1666             if (_less(cur.value, e))
1667                 cur = cur.right;
1668             else
1669             {
1670                 result = cur;
1671                 cur = cur.left;
1672             }
1673 
1674         }
1675         return result;
1676     }
1677 
1678     /**
1679      * Get a range from the container with all elements that are > e according
1680      * to the less comparator
1681      *
1682      * Complexity: $(BIGOH log(n))
1683      */
1684     Range upperBound(Elem e)
1685     {
1686         return Range(_firstGreater(e), _end);
1687     }
1688 
1689     /// Ditto
1690     ConstRange upperBound(Elem e) const
1691     {
1692         return ConstRange(_firstGreater(e), _end);
1693     }
1694 
1695     /// Ditto
1696     ImmutableRange upperBound(Elem e) immutable
1697     {
1698         return ImmutableRange(_firstGreater(e), _end);
1699     }
1700 
1701     /**
1702      * Get a range from the container with all elements that are < e according
1703      * to the less comparator
1704      *
1705      * Complexity: $(BIGOH log(n))
1706      */
1707     Range lowerBound(Elem e)
1708     {
1709         return Range(_begin, _firstGreaterEqual(e));
1710     }
1711 
1712     /// Ditto
1713     ConstRange lowerBound(Elem e) const
1714     {
1715         return ConstRange(_begin, _firstGreaterEqual(e));
1716     }
1717 
1718     /// Ditto
1719     ImmutableRange lowerBound(Elem e) immutable
1720     {
1721         return ImmutableRange(_begin, _firstGreaterEqual(e));
1722     }
1723 
1724     /**
1725      * Get a range from the container with all elements that are == e according
1726      * to the less comparator
1727      *
1728      * Complexity: $(BIGOH log(n))
1729      */
1730     auto equalRange(this This)(Elem e)
1731     {
1732         auto beg = _firstGreaterEqual(e);
1733         alias RangeType = RBRange!(typeof(beg));
1734         if (beg is _end || _less(e, beg.value))
1735             // no values are equal
1736             return RangeType(beg, beg);
1737         static if (allowDuplicates)
1738         {
1739             return RangeType(beg, _firstGreater(e));
1740         }
1741         else
1742         {
1743             // no sense in doing a full search, no duplicates are allowed,
1744             // so we just get the next node.
1745             return RangeType(beg, beg.next);
1746         }
1747     }
1748 
1749     /**
1750      * Returns a static array of 3 ranges `r` such that `r[0]` is the
1751      * same as the result of `lowerBound(value)`, `r[1]` is the same
1752      * as the result of $(D equalRange(value)), and `r[2]` is the same
1753      * as the result of $(D upperBound(value)).
1754      *
1755      * Complexity: $(BIGOH log(n))
1756      */
1757     auto trisect(this This)(Elem e)
1758     {
1759         auto equalRange = this.equalRange(e);
1760         alias RangeType = typeof(equalRange);
1761         RangeType[3] result = [
1762             RangeType(_begin, equalRange._begin),
1763             equalRange,
1764             RangeType(equalRange._end, _end)
1765         ];
1766         return result;
1767     }
1768 
1769     static if (doUnittest) @safe pure unittest
1770     {
1771         import std.algorithm.comparison : equal;
1772         auto ts = new RedBlackTree(1, 2, 3, 4, 5);
1773         auto rl = ts.lowerBound(3);
1774         auto ru = ts.upperBound(3);
1775         auto re = ts.equalRange(3);
1776 
1777         static if (less == "a < b")
1778         {
1779             assert(equal(rl, [1,2]));
1780             assert(equal(ru, [4,5]));
1781         }
1782         else
1783         {
1784             assert(equal(rl, [5,4]));
1785             assert(equal(ru, [2,1]));
1786         }
1787 
1788         assert(equal(re, [3]));
1789     }
1790 
1791     debug(RBDoChecks)
1792     {
1793         /*
1794          * Print the tree.  This prints a sideways view of the tree in ASCII form,
1795          * with the number of indentations representing the level of the nodes.
1796          * It does not print values, only the tree structure and color of nodes.
1797          */
1798         void printTree(Node n, int indent = 0)
1799         {
1800             import std.stdio : write, writeln;
1801             if (n !is null)
1802             {
1803                 printTree(n.right, indent + 2);
1804                 for (int i = 0; i < indent; i++)
1805                     write(".");
1806                 writeln(n.color == n.color.Black ? "B" : "R");
1807                 printTree(n.left, indent + 2);
1808             }
1809             else
1810             {
1811                 for (int i = 0; i < indent; i++)
1812                     write(".");
1813                 writeln("N");
1814             }
1815             if (indent is 0)
1816                 writeln();
1817         }
1818 
1819         /*
1820          * Check the tree for validity.  This is called after every add or remove.
1821          * This should only be enabled to debug the implementation of the RB Tree.
1822          */
1823         void check() @trusted
1824         {
1825             //
1826             // check implementation of the tree
1827             //
1828             int recurse(Node n, string path)
1829             {
1830                 import std.stdio : writeln;
1831                 if (n is null)
1832                     return 1;
1833                 if (n.parent.left !is n && n.parent.right !is n)
1834                     throw new Exception("Node at path " ~ path ~ " has inconsistent pointers");
1835                 Node next = n.next;
1836                 static if (allowDuplicates)
1837                 {
1838                     if (next !is _end && _less(next.value, n.value))
1839                         throw new Exception("ordering invalid at path " ~ path);
1840                 }
1841                 else
1842                 {
1843                     if (next !is _end && !_less(n.value, next.value))
1844                         throw new Exception("ordering invalid at path " ~ path);
1845                 }
1846                 if (n.color == n.color.Red)
1847                 {
1848                     if ((n.left !is null && n.left.color == n.color.Red) ||
1849                             (n.right !is null && n.right.color == n.color.Red))
1850                         throw new Exception("Node at path " ~ path ~ " is red with a red child");
1851                 }
1852 
1853                 int l = recurse(n.left, path ~ "L");
1854                 int r = recurse(n.right, path ~ "R");
1855                 if (l != r)
1856                 {
1857                     writeln("bad tree at:");
1858                     debug printTree(n);
1859                     throw new Exception(
1860                         "Node at path " ~ path ~ " has different number of black nodes on left and right paths"
1861                     );
1862                 }
1863                 return l + (n.color == n.color.Black ? 1 : 0);
1864             }
1865 
1866             try
1867             {
1868                 recurse(_end.left, "");
1869             }
1870             catch (Exception e)
1871             {
1872                 debug printTree(_end.left, 0);
1873                 throw e;
1874             }
1875         }
1876     }
1877 
1878     /**
1879       Formats the RedBlackTree into a sink function. For more info see $(D
1880       std.format.formatValue). Note that this only is available when the
1881       element type can be formatted. Otherwise, the default toString from
1882       Object is used.
1883      */
1884     static if (is(typeof((){FormatSpec!(char) fmt; formatValue((const(char)[]) {}, ConstRange.init, fmt);})))
1885     {
1886         void toString(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt) const
1887         {
1888             sink("RedBlackTree(");
1889             sink.formatValue(this[], fmt);
1890             sink(")");
1891         }
1892     }
1893 
1894     /**
1895      * Constructor. Pass in an array of elements, or individual elements to
1896      * initialize the tree with.
1897      */
1898     this(Elem[] elems...)
1899     {
1900         _setup();
1901         stableInsert(elems);
1902     }
1903 
1904     /**
1905      * Constructor. Pass in a range of elements to initialize the tree with.
1906      */
1907     this(Stuff)(Stuff stuff)
1908     if (isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, Elem))
1909     {
1910         _setup();
1911         stableInsert(stuff);
1912     }
1913 
1914     ///
1915     this()
1916     {
1917         _setup();
1918     }
1919 
1920     private this(Node end, size_t length)
1921     {
1922         _end = end;
1923         _begin = end.leftmost;
1924         _length = length;
1925     }
1926 }
1927 
1928 //Verify Example for removeKey.
1929 @safe pure unittest
1930 {
1931     import std.algorithm.comparison : equal;
1932     auto rbt = redBlackTree!true(0, 1, 1, 1, 4, 5, 7);
1933     rbt.removeKey(1, 4, 7);
1934     assert(equal(rbt[], [0, 1, 1, 5]));
1935     rbt.removeKey(1, 1, 0);
1936     assert(equal(rbt[], [5]));
1937 }
1938 
1939 //Tests for removeKey
1940 @safe pure unittest
1941 {
1942     import std.algorithm.comparison : equal;
1943     {
1944         auto rbt = redBlackTree(["hello", "world", "foo", "bar"]);
1945         assert(equal(rbt[], ["bar", "foo", "hello", "world"]));
1946         assert(rbt.removeKey("hello") == 1);
1947         assert(equal(rbt[], ["bar", "foo", "world"]));
1948         assert(rbt.removeKey("hello") == 0);
1949         assert(equal(rbt[], ["bar", "foo", "world"]));
1950         assert(rbt.removeKey("hello", "foo", "bar") == 2);
1951         assert(equal(rbt[], ["world"]));
1952         assert(rbt.removeKey(["", "world", "hello"]) == 1);
1953         assert(rbt.empty);
1954     }
1955 
1956     {
1957         auto rbt = redBlackTree([1, 2, 12, 27, 4, 500]);
1958         assert(equal(rbt[], [1, 2, 4, 12, 27, 500]));
1959         assert(rbt.removeKey(1u) == 1);
1960         assert(equal(rbt[], [2, 4, 12, 27, 500]));
1961         assert(rbt.removeKey(cast(byte) 1) == 0);
1962         assert(equal(rbt[], [2, 4, 12, 27, 500]));
1963         assert(rbt.removeKey(1, 12u, cast(byte) 27) == 2);
1964         assert(equal(rbt[], [2, 4, 500]));
1965         assert(rbt.removeKey([cast(short) 0, cast(short) 500, cast(short) 1]) == 1);
1966         assert(equal(rbt[], [2, 4]));
1967     }
1968 }
1969 
1970 @safe pure unittest
1971 {
1972     void test(T)()
1973     {
1974         auto rt1 = new RedBlackTree!(T, "a < b", false)();
1975         auto rt2 = new RedBlackTree!(T, "a < b", true)();
1976         auto rt3 = new RedBlackTree!(T, "a > b", false)();
1977         auto rt4 = new RedBlackTree!(T, "a > b", true)();
1978     }
1979 
1980     test!long();
1981     test!ulong();
1982     test!int();
1983     test!uint();
1984     test!short();
1985     test!ushort();
1986     test!byte();
1987     test!byte();
1988 }
1989 
1990 // https://issues.dlang.org/show_bug.cgi?id=19626
1991 @safe pure unittest
1992 {
1993     enum T { a, b }
1994     alias t = RedBlackTree!T;
1995 }
1996 
1997 import std.range.primitives : isInputRange, ElementType;
1998 import std.traits : isArray, isSomeString;
1999 
2000 /++
2001     Convenience function for creating a `RedBlackTree!E` from a list of
2002     values.
2003 
2004     Params:
2005         allowDuplicates =  Whether duplicates should be allowed (optional, default: false)
2006         less = predicate to sort by (optional)
2007         elems = elements to insert into the rbtree (variadic arguments)
2008         range = range elements to insert into the rbtree (alternative to elems)
2009   +/
2010 auto redBlackTree(E)(E[] elems...)
2011 {
2012     return new RedBlackTree!E(elems);
2013 }
2014 
2015 /++ Ditto +/
2016 auto redBlackTree(bool allowDuplicates, E)(E[] elems...)
2017 {
2018     return new RedBlackTree!(E, "a < b", allowDuplicates)(elems);
2019 }
2020 
2021 /++ Ditto +/
2022 auto redBlackTree(alias less, E)(E[] elems...)
2023 if (is(typeof(binaryFun!less(E.init, E.init))))
2024 {
2025     return new RedBlackTree!(E, less)(elems);
2026 }
2027 
2028 /++ Ditto +/
2029 auto redBlackTree(alias less, bool allowDuplicates, E)(E[] elems...)
2030 if (is(typeof(binaryFun!less(E.init, E.init))))
2031 {
2032     //We shouldn't need to instantiate less here, but for some reason,
2033     //dmd can't handle it if we don't (even though the template which
2034     //takes less but not allowDuplicates works just fine).
2035     return new RedBlackTree!(E, binaryFun!less, allowDuplicates)(elems);
2036 }
2037 
2038 /++ Ditto +/
2039 auto redBlackTree(Stuff)(Stuff range)
2040 if (isInputRange!Stuff && !isArray!(Stuff))
2041 {
2042     return new RedBlackTree!(ElementType!Stuff)(range);
2043 }
2044 
2045 /++ Ditto +/
2046 auto redBlackTree(bool allowDuplicates, Stuff)(Stuff range)
2047 if (isInputRange!Stuff && !isArray!(Stuff))
2048 {
2049     return new RedBlackTree!(ElementType!Stuff, "a < b", allowDuplicates)(range);
2050 }
2051 
2052 /++ Ditto +/
2053 auto redBlackTree(alias less, Stuff)(Stuff range)
2054 if ( is(typeof(binaryFun!less((ElementType!Stuff).init, (ElementType!Stuff).init)))
2055     && isInputRange!Stuff && !isArray!(Stuff))
2056 {
2057     return new RedBlackTree!(ElementType!Stuff, less)(range);
2058 }
2059 
2060 /++ Ditto +/
2061 auto redBlackTree(alias less, bool allowDuplicates, Stuff)(Stuff range)
2062 if ( is(typeof(binaryFun!less((ElementType!Stuff).init, (ElementType!Stuff).init)))
2063     && isInputRange!Stuff && !isArray!(Stuff))
2064 {
2065     //We shouldn't need to instantiate less here, but for some reason,
2066     //dmd can't handle it if we don't (even though the template which
2067     //takes less but not allowDuplicates works just fine).
2068     return new RedBlackTree!(ElementType!Stuff, binaryFun!less, allowDuplicates)(range);
2069 }
2070 
2071 ///
2072 @safe pure unittest
2073 {
2074     import std.range : iota;
2075 
2076     auto rbt1 = redBlackTree(0, 1, 5, 7);
2077     auto rbt2 = redBlackTree!string("hello", "world");
2078     auto rbt3 = redBlackTree!true(0, 1, 5, 7, 5);
2079     auto rbt4 = redBlackTree!"a > b"(0, 1, 5, 7);
2080     auto rbt5 = redBlackTree!("a > b", true)(0.1, 1.3, 5.9, 7.2, 5.9);
2081 
2082     // also works with ranges
2083     auto rbt6 = redBlackTree(iota(3));
2084     auto rbt7 = redBlackTree!true(iota(3));
2085     auto rbt8 = redBlackTree!"a > b"(iota(3));
2086     auto rbt9 = redBlackTree!("a > b", true)(iota(3));
2087 }
2088 
2089 //Combinations not in examples.
2090 @system pure unittest
2091 {
2092     auto rbt1 = redBlackTree!(true, string)("hello", "hello");
2093     auto rbt2 = redBlackTree!((a, b){return a < b;}, double)(5.1, 2.3);
2094     auto rbt3 = redBlackTree!("a > b", true, string)("hello", "world");
2095 }
2096 
2097 //Range construction.
2098 @safe pure unittest
2099 {
2100     import std.algorithm.comparison : equal;
2101     import std.range : iota;
2102     auto rbt = new RedBlackTree!(int, "a > b")(iota(5));
2103     assert(equal(rbt[], [4, 3, 2, 1, 0]));
2104 }
2105 
2106 
2107 // construction with arrays
2108 @safe pure unittest
2109 {
2110     import std.algorithm.comparison : equal;
2111 
2112     auto rbt = redBlackTree!"a > b"([0, 1, 2, 3, 4]);
2113     assert(equal(rbt[], [4, 3, 2, 1, 0]));
2114 
2115     auto rbt2 = redBlackTree!"a > b"(["a", "b"]);
2116     assert(equal(rbt2[], ["b", "a"]));
2117 
2118     auto rbt3 = redBlackTree!"a > b"([1, 2]);
2119     assert(equal(rbt3[], [2, 1]));
2120 
2121     auto rbt4 = redBlackTree([0, 1, 7, 5]);
2122     assert(equal(rbt4[], [0, 1, 5, 7]));
2123 
2124     auto rbt5 = redBlackTree(["hello", "world"]);
2125     assert(equal(rbt5[], ["hello", "world"]));
2126 
2127     auto rbt6 = redBlackTree!true([0, 1, 5, 7, 5]);
2128     assert(equal(rbt6[], [0, 1, 5, 5, 7]));
2129 
2130     auto rbt7 = redBlackTree!"a > b"([0, 1, 5, 7]);
2131     assert(equal(rbt7[], [7, 5, 1, 0]));
2132 
2133     auto rbt8 = redBlackTree!("a > b", true)([0.1, 1.3, 5.9, 7.2, 5.9]);
2134     assert(equal(rbt8[], [7.2, 5.9, 5.9, 1.3, 0.1]));
2135 }
2136 
2137 // convenience wrapper range construction
2138 @safe pure unittest
2139 {
2140     import std.algorithm.comparison : equal;
2141     import std.range : chain, iota;
2142 
2143     auto rbt = redBlackTree(iota(3));
2144     assert(equal(rbt[], [0, 1, 2]));
2145 
2146     auto rbt2 = redBlackTree!"a > b"(iota(2));
2147     assert(equal(rbt2[], [1, 0]));
2148 
2149     auto rbt3 = redBlackTree(chain([0, 1], [7, 5]));
2150     assert(equal(rbt3[], [0, 1, 5, 7]));
2151 
2152     auto rbt4 = redBlackTree(chain(["hello"], ["world"]));
2153     assert(equal(rbt4[], ["hello", "world"]));
2154 
2155     auto rbt5 = redBlackTree!true(chain([0, 1], [5, 7, 5]));
2156     assert(equal(rbt5[], [0, 1, 5, 5, 7]));
2157 
2158     auto rbt6 = redBlackTree!("a > b", true)(chain([0.1, 1.3], [5.9, 7.2, 5.9]));
2159     assert(equal(rbt6[], [7.2, 5.9, 5.9, 1.3, 0.1]));
2160 }
2161 
2162 @safe pure unittest
2163 {
2164     import std.array : array;
2165 
2166     auto rt1 = redBlackTree(5, 4, 3, 2, 1);
2167     assert(rt1.length == 5);
2168     assert(array(rt1[]) == [1, 2, 3, 4, 5]);
2169 
2170     auto rt2 = redBlackTree!"a > b"(1.1, 2.1);
2171     assert(rt2.length == 2);
2172     assert(array(rt2[]) == [2.1, 1.1]);
2173 
2174     auto rt3 = redBlackTree!true(5, 5, 4);
2175     assert(rt3.length == 3);
2176     assert(array(rt3[]) == [4, 5, 5]);
2177 
2178     auto rt4 = redBlackTree!string("hello", "hello");
2179     assert(rt4.length == 1);
2180     assert(array(rt4[]) == ["hello"]);
2181 }
2182 
2183 @system unittest
2184 {
2185     import std.conv : to;
2186 
2187     auto rt1 = redBlackTree!string();
2188     assert(rt1.to!string == "RedBlackTree([])");
2189 
2190     auto rt2 = redBlackTree!string("hello");
2191     assert(rt2.to!string == "RedBlackTree([\"hello\"])");
2192 
2193     auto rt3 = redBlackTree!string("hello", "world", "!");
2194     assert(rt3.to!string == "RedBlackTree([\"!\", \"hello\", \"world\"])");
2195 
2196     // type deduction can be done automatically
2197     auto rt4 = redBlackTree(["hello"]);
2198     assert(rt4.to!string == "RedBlackTree([\"hello\"])");
2199 }
2200 
2201 //constness checks
2202 @safe pure unittest
2203 {
2204     const rt1 = redBlackTree(5,4,3,2,1);
2205     void allQualifiers() pure nothrow @safe @nogc {
2206         assert(!rt1.empty);
2207         assert(rt1.length == 5);
2208         assert(5 in rt1);
2209     }
2210     allQualifiers();
2211 
2212     static assert(is(typeof(rt1.upperBound(3).front) == const(int)));
2213     import std.algorithm.comparison : equal;
2214     assert(rt1.upperBound(3).equal([4, 5]));
2215     assert(rt1.lowerBound(3).equal([1, 2]));
2216     assert(rt1.equalRange(3).equal([3]));
2217     assert(rt1[].equal([1, 2, 3, 4, 5]));
2218 
2219     auto t = rt1.trisect(3);
2220     assert(t[0].equal(rt1.lowerBound(3)));
2221     assert(t[1].equal(rt1.equalRange(3)));
2222     assert(t[2].equal(rt1.upperBound(3)));
2223 }
2224 
2225 //immutable checks
2226 @safe pure unittest
2227 {
2228     immutable rt1 = redBlackTree(5,4,3,2,1);
2229     static assert(is(typeof(rt1.empty)));
2230     static assert(is(typeof(rt1.length)));
2231     static assert(is(typeof(5 in rt1)));
2232 
2233     static assert(is(typeof(rt1.upperBound(3).front) == immutable(int)));
2234     import std.algorithm.comparison : equal;
2235     assert(rt1.upperBound(2).equal([3, 4, 5]));
2236 }
2237 
2238 // https://issues.dlang.org/show_bug.cgi?id=15941
2239 @safe pure unittest
2240 {
2241     class C {}
2242     RedBlackTree!(C, "cast(void*)a < cast(void*) b") tree;
2243 }
2244 
2245 // const/immutable elements (https://issues.dlang.org/show_bug.cgi?id=17519)
2246 @safe pure unittest
2247 {
2248     RedBlackTree!(immutable int) t1;
2249     RedBlackTree!(const int) t2;
2250 
2251     import std.algorithm.iteration : map;
2252     static struct S { int* p; }
2253     auto t3 = new RedBlackTree!(immutable S, (a, b) => *a.p < *b.p);
2254     t3.insert([1, 2, 3].map!(x => immutable S(new int(x))));
2255     static assert(!__traits(compiles, *t3.front.p = 4));
2256     assert(*t3.front.p == 1);
2257 }
2258 
2259 // make sure the comparator can be a delegate
2260 @safe pure unittest
2261 {
2262     import std.algorithm.comparison : equal;
2263 
2264     auto t = new RedBlackTree!(int, delegate(a, b) => a > b);
2265     t.insert([1, 3, 5, 4, 2]);
2266     assert(t[].equal([5, 4, 3, 2, 1]));
2267 }
2268 
2269 // should support `less` predicate taking `ref const`
2270 @safe pure unittest
2271 {
2272     struct S
2273     {
2274         int* value;
2275     }
2276 
2277     cast(void) new RedBlackTree!(S, (ref const S a, ref const S b) => a.value > b.value);
2278 }