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 if (op == "in") 1061 { 1062 return _find(e) !is null; 1063 } 1064 1065 static if (doUnittest) @safe pure unittest 1066 { 1067 auto ts = new RedBlackTree(1, 2, 3, 4, 5); 1068 assert(cast(Elem) 3 in ts); 1069 assert(cast(Elem) 6 !in ts); 1070 } 1071 1072 /** 1073 * Compares two trees for equality. 1074 * 1075 * Complexity: $(BIGOH n) 1076 */ 1077 override bool opEquals(Object rhs) 1078 { 1079 import std.algorithm.comparison : equal; 1080 1081 RedBlackTree that = cast(RedBlackTree) rhs; 1082 if (that is null) return false; 1083 1084 // If there aren't the same number of nodes, we can't be equal. 1085 if (this._length != that._length) return false; 1086 1087 auto thisRange = this[]; 1088 auto thatRange = that[]; 1089 return equal!((Elem a, Elem b) => !_less(a,b) && !_less(b,a)) 1090 (thisRange, thatRange); 1091 } 1092 1093 static if (doUnittest) @system unittest 1094 { 1095 auto t1 = new RedBlackTree(1,2,3,4); 1096 auto t2 = new RedBlackTree(1,2,3,4); 1097 auto t3 = new RedBlackTree(1,2,3,5); 1098 auto t4 = new RedBlackTree(1,2,3,4,5); 1099 auto o = new Object(); 1100 1101 assert(t1 == t1); 1102 assert(t1 == t2); 1103 assert(t1 != t3); 1104 assert(t1 != t4); 1105 assert(t1 != o); // pathological case, must not crash 1106 } 1107 1108 /** 1109 * Generates a hash for the tree. Note that with a custom comparison function 1110 * it may not hold that if two rbtrees are equal, the hashes of the trees 1111 * will be equal. 1112 */ 1113 override size_t toHash() nothrow @safe 1114 { 1115 size_t hash = cast(size_t) 0x6b63_616c_4264_6552UL; 1116 foreach (ref e; this[]) 1117 // As in boost::hash_combine 1118 // https://www.boost.org/doc/libs/1_55_0/doc/html/hash/reference.html#boost.hash_combine 1119 hash += .hashOf(e) + 0x9e3779b9 + (hash << 6) + (hash >>> 2); 1120 return hash; 1121 } 1122 1123 static if (doUnittest) @system unittest 1124 { 1125 auto t1 = new RedBlackTree(1,2,3,4); 1126 auto t2 = new RedBlackTree(1,2,3,4); 1127 auto t3 = new RedBlackTree(1,2,3,5); 1128 auto t4 = new RedBlackTree(1,2,3,4,5); 1129 1130 assert(t1.toHash() == t2.toHash); 1131 1132 assert(t1.toHash() != t3.toHash); 1133 assert(t2.toHash() != t3.toHash); 1134 1135 assert(t3.toHash() != t4.toHash); 1136 assert(t1.toHash() != t4.toHash); 1137 1138 // empty tree 1139 auto t5 = new RedBlackTree(); 1140 auto t6 = new RedBlackTree(); 1141 1142 assert(t5.toHash() == t6.toHash()); 1143 1144 auto t7 = new RedBlackTree!string("red", "black"); 1145 auto t8 = new RedBlackTree!string("white", "black"); 1146 auto t9 = new RedBlackTree!string("red", "black"); 1147 1148 assert(t7.toHash() == t9.toHash()); 1149 assert(t7.toHash() != t8.toHash()); 1150 1151 static struct MyInt 1152 { 1153 int x; 1154 1155 @safe: 1156 1157 this(int init_x) 1158 { 1159 x = init_x; 1160 } 1161 1162 size_t toHash() const nothrow 1163 { 1164 return typeid(x).getHash(&x) ^ 0xF0F0_F0F0; 1165 } 1166 1167 int opCmp(const MyInt that) const 1168 { 1169 return (x > that.x) - (x < that.x); 1170 } 1171 1172 bool opEquals(const MyInt that) const 1173 { 1174 return (this.x == that.x); 1175 } 1176 } 1177 1178 auto rbt1 = new RedBlackTree!MyInt(MyInt(1), MyInt(2), MyInt(3), MyInt(4)); 1179 auto rbt2 = new RedBlackTree!MyInt(MyInt(1), MyInt(2), MyInt(3), MyInt(4)); 1180 1181 assert(rbt1.toHash() == rbt2.toHash()); 1182 assert(rbt1.toHash() != t1.toHash()); 1183 1184 auto rbt3 = new RedBlackTree!MyInt(MyInt(4), MyInt(2), MyInt(3), MyInt(4)); 1185 1186 assert(rbt1.toHash() != rbt3.toHash()); 1187 1188 class MyInt2 1189 { 1190 int x; 1191 1192 this(int init_x) 1193 { 1194 x = init_x; 1195 } 1196 1197 override size_t toHash() const @safe nothrow 1198 { 1199 return typeid(x).getHash(&x) ^ 0xF0F0_F0F0; 1200 } 1201 1202 int opCmp(const MyInt2 that) const 1203 { 1204 return (x > that.x) - (x < that.x); 1205 } 1206 1207 bool opEquals(const MyInt2 that) const 1208 { 1209 return (this.x == that.x); 1210 } 1211 } 1212 1213 static bool nullSafeLess(scope const MyInt2 a, scope const MyInt2 b) 1214 { 1215 return a is null ? b !is null : (b !is null && a < b); 1216 } 1217 1218 auto rbt4 = new RedBlackTree!MyInt2(new MyInt2(1), new MyInt2(9), new MyInt2(3), new MyInt2(42)); 1219 auto rbt5 = new RedBlackTree!MyInt2(new MyInt2(1), new MyInt2(9), new MyInt2(3), new MyInt2(42)); 1220 auto rbt6 = new RedBlackTree!(MyInt2, nullSafeLess)(new MyInt2(9), new MyInt2(3), new MyInt2(42)); 1221 auto rbt7 = new RedBlackTree!(MyInt2, nullSafeLess)(null); 1222 1223 assert(rbt6.toHash() != rbt5.toHash()); 1224 assert(rbt6.toHash() != rbt4.toHash()); 1225 assert(rbt6.toHash() != rbt7.toHash()); 1226 assert(rbt4.toHash() == rbt5.toHash()); 1227 1228 auto rbt8 = new RedBlackTree!(MyInt2, nullSafeLess)(null, new MyInt2(9), null, new MyInt2(42)); 1229 auto rbt9 = new RedBlackTree!(MyInt2, nullSafeLess)(null, new MyInt2(9), null, new MyInt2(42)); 1230 auto rbt10 = new RedBlackTree!(MyInt2, nullSafeLess)(new MyInt2(94), null, new MyInt2(147)); 1231 1232 assert(rbt8.toHash() == rbt9.toHash()); 1233 assert(rbt8.toHash() != rbt10.toHash()); 1234 } 1235 1236 /** 1237 * Removes all elements from the container. 1238 * 1239 * Complexity: $(BIGOH 1) 1240 */ 1241 void clear() 1242 { 1243 _end.left = null; 1244 _begin = _end; 1245 _length = 0; 1246 } 1247 1248 static if (doUnittest) @safe pure unittest 1249 { 1250 auto ts = new RedBlackTree(1,2,3,4,5); 1251 assert(ts.length == 5); 1252 ts.clear(); 1253 assert(ts.empty && ts.length == 0); 1254 } 1255 1256 /** 1257 * Insert a single element in the container. Note that this does not 1258 * invalidate any ranges currently iterating the container. 1259 * 1260 * Returns: The number of elements inserted. 1261 * 1262 * Complexity: $(BIGOH log(n)) 1263 */ 1264 size_t stableInsert(Stuff)(Stuff stuff) if (isImplicitlyConvertible!(Stuff, Elem)) 1265 { 1266 static if (allowDuplicates) 1267 { 1268 _add(stuff); 1269 return 1; 1270 } 1271 else 1272 { 1273 return _add(stuff); 1274 } 1275 } 1276 1277 /** 1278 * Insert a range of elements in the container. Note that this does not 1279 * invalidate any ranges currently iterating the container. 1280 * 1281 * Returns: The number of elements inserted. 1282 * 1283 * Complexity: $(BIGOH m * log(n)) 1284 */ 1285 size_t stableInsert(Stuff)(scope Stuff stuff) 1286 if (isInputRange!Stuff && 1287 isImplicitlyConvertible!(ElementType!Stuff, Elem)) 1288 { 1289 size_t result = 0; 1290 static if (allowDuplicates) 1291 { 1292 foreach (e; stuff) 1293 { 1294 ++result; 1295 _add(e); 1296 } 1297 } 1298 else 1299 { 1300 foreach (e; stuff) 1301 { 1302 result += _add(e); 1303 } 1304 } 1305 return result; 1306 } 1307 1308 /// ditto 1309 alias insert = stableInsert; 1310 1311 static if (doUnittest) @safe pure unittest 1312 { 1313 auto ts = new RedBlackTree(2,1,3,4,5,2,5); 1314 static if (allowDuplicates) 1315 { 1316 assert(ts.length == 7); 1317 assert(ts.stableInsert(cast(Elem[])[7, 8, 6, 9, 10, 8]) == 6); 1318 assert(ts.length == 13); 1319 assert(ts.stableInsert(cast(Elem) 11) == 1 && ts.length == 14); 1320 assert(ts.stableInsert(cast(Elem) 7) == 1 && ts.length == 15); 1321 1322 static if (less == "a < b") 1323 assert(ts.arrayEqual([1,2,2,3,4,5,5,6,7,7,8,8,9,10,11])); 1324 else 1325 assert(ts.arrayEqual([11,10,9,8,8,7,7,6,5,5,4,3,2,2,1])); 1326 } 1327 else 1328 { 1329 assert(ts.length == 5); 1330 Elem[] elems = [7, 8, 6, 9, 10, 8]; 1331 assert(ts.stableInsert(elems) == 5); 1332 assert(ts.length == 10); 1333 assert(ts.stableInsert(cast(Elem) 11) == 1 && ts.length == 11); 1334 assert(ts.stableInsert(cast(Elem) 7) == 0 && ts.length == 11); 1335 1336 static if (less == "a < b") 1337 assert(ts.arrayEqual([1,2,3,4,5,6,7,8,9,10,11])); 1338 else 1339 assert(ts.arrayEqual([11,10,9,8,7,6,5,4,3,2,1])); 1340 } 1341 } 1342 1343 /** 1344 * Remove an element from the container and return its value. 1345 * 1346 * Complexity: $(BIGOH log(n)) 1347 */ 1348 Elem removeAny() 1349 { 1350 scope(success) 1351 --_length; 1352 auto n = _begin; 1353 auto result = n.value; 1354 _begin = n.remove(_end); 1355 debug(RBDoChecks) 1356 check(); 1357 return result; 1358 } 1359 1360 static if (doUnittest) @safe pure unittest 1361 { 1362 auto ts = new RedBlackTree(1,2,3,4,5); 1363 assert(ts.length == 5); 1364 auto x = ts.removeAny(); 1365 assert(ts.length == 4); 1366 Elem[] arr; 1367 foreach (Elem i; 1 .. 6) 1368 if (i != x) arr ~= i; 1369 assert(ts.arrayEqual(arr)); 1370 } 1371 1372 /** 1373 * Remove the front element from the container. 1374 * 1375 * Complexity: $(BIGOH log(n)) 1376 */ 1377 void removeFront() 1378 { 1379 scope(success) 1380 --_length; 1381 _begin = _begin.remove(_end); 1382 debug(RBDoChecks) 1383 check(); 1384 } 1385 1386 /** 1387 * Remove the back element from the container. 1388 * 1389 * Complexity: $(BIGOH log(n)) 1390 */ 1391 void removeBack() 1392 { 1393 scope(success) 1394 --_length; 1395 auto lastnode = _end.prev; 1396 if (lastnode is _begin) 1397 _begin = _begin.remove(_end); 1398 else 1399 lastnode.remove(_end); 1400 debug(RBDoChecks) 1401 check(); 1402 } 1403 1404 static if (doUnittest) @safe pure unittest 1405 { 1406 auto ts = new RedBlackTree(1,2,3,4,5); 1407 assert(ts.length == 5); 1408 ts.removeBack(); 1409 assert(ts.length == 4); 1410 1411 static if (less == "a < b") 1412 assert(ts.arrayEqual([1,2,3,4])); 1413 else 1414 assert(ts.arrayEqual([2,3,4,5])); 1415 1416 ts.removeFront(); 1417 assert(ts.arrayEqual([2,3,4]) && ts.length == 3); 1418 } 1419 1420 /++ 1421 Removes the given range from the container. 1422 1423 Returns: A range containing all of the elements that were after the 1424 given range. 1425 1426 Complexity: $(BIGOH m * log(n)) (where m is the number of elements in 1427 the range) 1428 +/ 1429 Range remove(Range r) 1430 { 1431 auto b = r._begin; 1432 auto e = r._end; 1433 if (_begin is b) 1434 _begin = e; 1435 while (b !is e) 1436 { 1437 b = b.remove(_end); 1438 --_length; 1439 } 1440 debug(RBDoChecks) 1441 check(); 1442 return Range(e, _end); 1443 } 1444 1445 static if (doUnittest) @safe pure unittest 1446 { 1447 import std.algorithm.comparison : equal; 1448 auto ts = new RedBlackTree(1,2,3,4,5); 1449 assert(ts.length == 5); 1450 auto r = ts[]; 1451 r.popFront(); 1452 r.popBack(); 1453 assert(ts.length == 5); 1454 auto r2 = ts.remove(r); 1455 assert(ts.length == 2); 1456 assert(ts.arrayEqual([1,5])); 1457 1458 static if (less == "a < b") 1459 assert(equal(r2, [5])); 1460 else 1461 assert(equal(r2, [1])); 1462 } 1463 1464 /++ 1465 Removes the given `Take!Range` from the container 1466 1467 Returns: A range containing all of the elements that were after the 1468 given range. 1469 1470 Complexity: $(BIGOH m * log(n)) (where m is the number of elements in 1471 the range) 1472 +/ 1473 Range remove(Take!Range r) 1474 { 1475 immutable isBegin = (r.source._begin is _begin); 1476 auto b = r.source._begin; 1477 1478 while (!r.empty) 1479 { 1480 r.popFront(); 1481 b = b.remove(_end); 1482 --_length; 1483 } 1484 1485 if (isBegin) 1486 _begin = b; 1487 1488 return Range(b, _end); 1489 } 1490 1491 static if (doUnittest) @safe pure unittest 1492 { 1493 import std.algorithm.comparison : equal; 1494 import std.range : take; 1495 auto ts = new RedBlackTree(1,2,3,4,5); 1496 auto r = ts[]; 1497 r.popFront(); 1498 assert(ts.length == 5); 1499 auto r2 = ts.remove(take(r, 0)); 1500 1501 static if (less == "a < b") 1502 { 1503 assert(equal(r2, [2,3,4,5])); 1504 auto r3 = ts.remove(take(r, 2)); 1505 assert(ts.arrayEqual([1,4,5]) && ts.length == 3); 1506 assert(equal(r3, [4,5])); 1507 } 1508 else 1509 { 1510 assert(equal(r2, [4,3,2,1])); 1511 auto r3 = ts.remove(take(r, 2)); 1512 assert(ts.arrayEqual([5,2,1]) && ts.length == 3); 1513 assert(equal(r3, [2,1])); 1514 } 1515 } 1516 1517 /++ 1518 Removes elements from the container that are equal to the given values 1519 according to the less comparator. One element is removed for each value 1520 given which is in the container. If `allowDuplicates` is true, 1521 duplicates are removed only if duplicate values are given. 1522 1523 Returns: The number of elements removed. 1524 1525 Complexity: $(BIGOH m log(n)) (where m is the number of elements to remove) 1526 1527 Example: 1528 -------------------- 1529 auto rbt = redBlackTree!true(0, 1, 1, 1, 4, 5, 7); 1530 rbt.removeKey(1, 4, 7); 1531 assert(equal(rbt[], [0, 1, 1, 5])); 1532 rbt.removeKey(1, 1, 0); 1533 assert(equal(rbt[], [5])); 1534 -------------------- 1535 +/ 1536 size_t removeKey(U...)(U elems) 1537 if (allSatisfy!(isImplicitlyConvertibleToElem, U)) 1538 { 1539 Elem[U.length] toRemove = [elems]; 1540 return removeKey(toRemove[]); 1541 } 1542 1543 /++ Ditto +/ 1544 size_t removeKey(U)(scope U[] elems) 1545 if (isImplicitlyConvertible!(U, Elem)) 1546 { 1547 immutable lenBefore = length; 1548 1549 foreach (e; elems) 1550 { 1551 auto beg = _firstGreaterEqual(e); 1552 if (beg is _end || _less(e, beg.value)) 1553 // no values are equal 1554 continue; 1555 immutable isBegin = (beg is _begin); 1556 beg = beg.remove(_end); 1557 if (isBegin) 1558 _begin = beg; 1559 --_length; 1560 } 1561 1562 return lenBefore - length; 1563 } 1564 1565 /++ Ditto +/ 1566 size_t removeKey(Stuff)(Stuff stuff) 1567 if (isInputRange!Stuff && 1568 isImplicitlyConvertible!(ElementType!Stuff, Elem) && 1569 !isDynamicArray!Stuff) 1570 { 1571 import std.array : array; 1572 //We use array in case stuff is a Range from this RedBlackTree - either 1573 //directly or indirectly. 1574 return removeKey(array(stuff)); 1575 } 1576 1577 //Helper for removeKey. 1578 private template isImplicitlyConvertibleToElem(U) 1579 { 1580 enum isImplicitlyConvertibleToElem = isImplicitlyConvertible!(U, Elem); 1581 } 1582 1583 static if (doUnittest) @safe pure unittest 1584 { 1585 import std.algorithm.comparison : equal; 1586 import std.range : take; 1587 auto rbt = new RedBlackTree(5, 4, 3, 7, 2, 1, 7, 6, 2, 19, 45); 1588 1589 //The cast(Elem) is because these tests are instantiated with a variety 1590 //of numeric types, and the literals are all int, which is not always 1591 //implicitly convertible to Elem (e.g. short). 1592 static if (allowDuplicates) 1593 { 1594 assert(rbt.length == 11); 1595 assert(rbt.removeKey(cast(Elem) 4) == 1 && rbt.length == 10); 1596 assert(rbt.arrayEqual([1,2,2,3,5,6,7,7,19,45]) && rbt.length == 10); 1597 1598 assert(rbt.removeKey(cast(Elem) 6, cast(Elem) 2, cast(Elem) 1) == 3); 1599 assert(rbt.arrayEqual([2,3,5,7,7,19,45]) && rbt.length == 7); 1600 1601 assert(rbt.removeKey(cast(Elem)(42)) == 0 && rbt.length == 7); 1602 assert(rbt.removeKey(take(rbt[], 3)) == 3 && rbt.length == 4); 1603 1604 static if (less == "a < b") 1605 assert(equal(rbt[], [7,7,19,45])); 1606 else 1607 assert(equal(rbt[], [7,5,3,2])); 1608 } 1609 else 1610 { 1611 assert(rbt.length == 9); 1612 assert(rbt.removeKey(cast(Elem) 4) == 1 && rbt.length == 8); 1613 assert(rbt.arrayEqual([1,2,3,5,6,7,19,45])); 1614 1615 assert(rbt.removeKey(cast(Elem) 6, cast(Elem) 2, cast(Elem) 1) == 3); 1616 assert(rbt.arrayEqual([3,5,7,19,45]) && rbt.length == 5); 1617 1618 assert(rbt.removeKey(cast(Elem)(42)) == 0 && rbt.length == 5); 1619 assert(rbt.removeKey(take(rbt[], 3)) == 3 && rbt.length == 2); 1620 1621 static if (less == "a < b") 1622 assert(equal(rbt[], [19,45])); 1623 else 1624 assert(equal(rbt[], [5,3])); 1625 } 1626 } 1627 1628 // find the first node where the value is > e 1629 private inout(RBNode)* _firstGreater(Elem e) inout 1630 { 1631 // can't use _find, because we cannot return null 1632 auto cur = _end.left; 1633 inout(RBNode)* result = _end; 1634 while (cur) 1635 { 1636 if (_less(e, cur.value)) 1637 { 1638 result = cur; 1639 cur = cur.left; 1640 } 1641 else 1642 cur = cur.right; 1643 } 1644 return result; 1645 } 1646 1647 // find the first node where the value is >= e 1648 private inout(RBNode)* _firstGreaterEqual(Elem e) inout 1649 { 1650 // can't use _find, because we cannot return null. 1651 auto cur = _end.left; 1652 inout(RBNode)* result = _end; 1653 while (cur) 1654 { 1655 if (_less(cur.value, e)) 1656 cur = cur.right; 1657 else 1658 { 1659 result = cur; 1660 cur = cur.left; 1661 } 1662 1663 } 1664 return result; 1665 } 1666 1667 /** 1668 * Get a range from the container with all elements that are > e according 1669 * to the less comparator 1670 * 1671 * Complexity: $(BIGOH log(n)) 1672 */ 1673 Range upperBound(Elem e) 1674 { 1675 return Range(_firstGreater(e), _end); 1676 } 1677 1678 /// Ditto 1679 ConstRange upperBound(Elem e) const 1680 { 1681 return ConstRange(_firstGreater(e), _end); 1682 } 1683 1684 /// Ditto 1685 ImmutableRange upperBound(Elem e) immutable 1686 { 1687 return ImmutableRange(_firstGreater(e), _end); 1688 } 1689 1690 /** 1691 * Get a range from the container with all elements that are < e according 1692 * to the less comparator 1693 * 1694 * Complexity: $(BIGOH log(n)) 1695 */ 1696 Range lowerBound(Elem e) 1697 { 1698 return Range(_begin, _firstGreaterEqual(e)); 1699 } 1700 1701 /// Ditto 1702 ConstRange lowerBound(Elem e) const 1703 { 1704 return ConstRange(_begin, _firstGreaterEqual(e)); 1705 } 1706 1707 /// Ditto 1708 ImmutableRange lowerBound(Elem e) immutable 1709 { 1710 return ImmutableRange(_begin, _firstGreaterEqual(e)); 1711 } 1712 1713 /** 1714 * Get a range from the container with all elements that are == e according 1715 * to the less comparator 1716 * 1717 * Complexity: $(BIGOH log(n)) 1718 */ 1719 auto equalRange(this This)(Elem e) 1720 { 1721 auto beg = _firstGreaterEqual(e); 1722 alias RangeType = RBRange!(typeof(beg)); 1723 if (beg is _end || _less(e, beg.value)) 1724 // no values are equal 1725 return RangeType(beg, beg); 1726 static if (allowDuplicates) 1727 { 1728 return RangeType(beg, _firstGreater(e)); 1729 } 1730 else 1731 { 1732 // no sense in doing a full search, no duplicates are allowed, 1733 // so we just get the next node. 1734 return RangeType(beg, beg.next); 1735 } 1736 } 1737 1738 static if (doUnittest) @safe pure unittest 1739 { 1740 import std.algorithm.comparison : equal; 1741 auto ts = new RedBlackTree(1, 2, 3, 4, 5); 1742 auto rl = ts.lowerBound(3); 1743 auto ru = ts.upperBound(3); 1744 auto re = ts.equalRange(3); 1745 1746 static if (less == "a < b") 1747 { 1748 assert(equal(rl, [1,2])); 1749 assert(equal(ru, [4,5])); 1750 } 1751 else 1752 { 1753 assert(equal(rl, [5,4])); 1754 assert(equal(ru, [2,1])); 1755 } 1756 1757 assert(equal(re, [3])); 1758 } 1759 1760 debug(RBDoChecks) 1761 { 1762 /* 1763 * Print the tree. This prints a sideways view of the tree in ASCII form, 1764 * with the number of indentations representing the level of the nodes. 1765 * It does not print values, only the tree structure and color of nodes. 1766 */ 1767 void printTree(Node n, int indent = 0) 1768 { 1769 import std.stdio : write, writeln; 1770 if (n !is null) 1771 { 1772 printTree(n.right, indent + 2); 1773 for (int i = 0; i < indent; i++) 1774 write("."); 1775 writeln(n.color == n.color.Black ? "B" : "R"); 1776 printTree(n.left, indent + 2); 1777 } 1778 else 1779 { 1780 for (int i = 0; i < indent; i++) 1781 write("."); 1782 writeln("N"); 1783 } 1784 if (indent is 0) 1785 writeln(); 1786 } 1787 1788 /* 1789 * Check the tree for validity. This is called after every add or remove. 1790 * This should only be enabled to debug the implementation of the RB Tree. 1791 */ 1792 void check() @trusted 1793 { 1794 // 1795 // check implementation of the tree 1796 // 1797 int recurse(Node n, string path) 1798 { 1799 import std.stdio : writeln; 1800 if (n is null) 1801 return 1; 1802 if (n.parent.left !is n && n.parent.right !is n) 1803 throw new Exception("Node at path " ~ path ~ " has inconsistent pointers"); 1804 Node next = n.next; 1805 static if (allowDuplicates) 1806 { 1807 if (next !is _end && _less(next.value, n.value)) 1808 throw new Exception("ordering invalid at path " ~ path); 1809 } 1810 else 1811 { 1812 if (next !is _end && !_less(n.value, next.value)) 1813 throw new Exception("ordering invalid at path " ~ path); 1814 } 1815 if (n.color == n.color.Red) 1816 { 1817 if ((n.left !is null && n.left.color == n.color.Red) || 1818 (n.right !is null && n.right.color == n.color.Red)) 1819 throw new Exception("Node at path " ~ path ~ " is red with a red child"); 1820 } 1821 1822 int l = recurse(n.left, path ~ "L"); 1823 int r = recurse(n.right, path ~ "R"); 1824 if (l != r) 1825 { 1826 writeln("bad tree at:"); 1827 debug printTree(n); 1828 throw new Exception( 1829 "Node at path " ~ path ~ " has different number of black nodes on left and right paths" 1830 ); 1831 } 1832 return l + (n.color == n.color.Black ? 1 : 0); 1833 } 1834 1835 try 1836 { 1837 recurse(_end.left, ""); 1838 } 1839 catch (Exception e) 1840 { 1841 debug printTree(_end.left, 0); 1842 throw e; 1843 } 1844 } 1845 } 1846 1847 /** 1848 Formats the RedBlackTree into a sink function. For more info see $(D 1849 std.format.formatValue). Note that this only is available when the 1850 element type can be formatted. Otherwise, the default toString from 1851 Object is used. 1852 */ 1853 static if (is(typeof((){FormatSpec!(char) fmt; formatValue((const(char)[]) {}, ConstRange.init, fmt);}))) 1854 { 1855 void toString(scope void delegate(const(char)[]) sink, scope const ref FormatSpec!char fmt) const 1856 { 1857 sink("RedBlackTree("); 1858 sink.formatValue(this[], fmt); 1859 sink(")"); 1860 } 1861 } 1862 1863 /** 1864 * Constructor. Pass in an array of elements, or individual elements to 1865 * initialize the tree with. 1866 */ 1867 this(Elem[] elems...) 1868 { 1869 _setup(); 1870 stableInsert(elems); 1871 } 1872 1873 /** 1874 * Constructor. Pass in a range of elements to initialize the tree with. 1875 */ 1876 this(Stuff)(Stuff stuff) if (isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, Elem)) 1877 { 1878 _setup(); 1879 stableInsert(stuff); 1880 } 1881 1882 /// 1883 this() 1884 { 1885 _setup(); 1886 } 1887 1888 private this(Node end, size_t length) 1889 { 1890 _end = end; 1891 _begin = end.leftmost; 1892 _length = length; 1893 } 1894 } 1895 1896 //Verify Example for removeKey. 1897 @safe pure unittest 1898 { 1899 import std.algorithm.comparison : equal; 1900 auto rbt = redBlackTree!true(0, 1, 1, 1, 4, 5, 7); 1901 rbt.removeKey(1, 4, 7); 1902 assert(equal(rbt[], [0, 1, 1, 5])); 1903 rbt.removeKey(1, 1, 0); 1904 assert(equal(rbt[], [5])); 1905 } 1906 1907 //Tests for removeKey 1908 @safe pure unittest 1909 { 1910 import std.algorithm.comparison : equal; 1911 { 1912 auto rbt = redBlackTree(["hello", "world", "foo", "bar"]); 1913 assert(equal(rbt[], ["bar", "foo", "hello", "world"])); 1914 assert(rbt.removeKey("hello") == 1); 1915 assert(equal(rbt[], ["bar", "foo", "world"])); 1916 assert(rbt.removeKey("hello") == 0); 1917 assert(equal(rbt[], ["bar", "foo", "world"])); 1918 assert(rbt.removeKey("hello", "foo", "bar") == 2); 1919 assert(equal(rbt[], ["world"])); 1920 assert(rbt.removeKey(["", "world", "hello"]) == 1); 1921 assert(rbt.empty); 1922 } 1923 1924 { 1925 auto rbt = redBlackTree([1, 2, 12, 27, 4, 500]); 1926 assert(equal(rbt[], [1, 2, 4, 12, 27, 500])); 1927 assert(rbt.removeKey(1u) == 1); 1928 assert(equal(rbt[], [2, 4, 12, 27, 500])); 1929 assert(rbt.removeKey(cast(byte) 1) == 0); 1930 assert(equal(rbt[], [2, 4, 12, 27, 500])); 1931 assert(rbt.removeKey(1, 12u, cast(byte) 27) == 2); 1932 assert(equal(rbt[], [2, 4, 500])); 1933 assert(rbt.removeKey([cast(short) 0, cast(short) 500, cast(short) 1]) == 1); 1934 assert(equal(rbt[], [2, 4])); 1935 } 1936 } 1937 1938 @safe pure unittest 1939 { 1940 void test(T)() 1941 { 1942 auto rt1 = new RedBlackTree!(T, "a < b", false)(); 1943 auto rt2 = new RedBlackTree!(T, "a < b", true)(); 1944 auto rt3 = new RedBlackTree!(T, "a > b", false)(); 1945 auto rt4 = new RedBlackTree!(T, "a > b", true)(); 1946 } 1947 1948 test!long(); 1949 test!ulong(); 1950 test!int(); 1951 test!uint(); 1952 test!short(); 1953 test!ushort(); 1954 test!byte(); 1955 test!byte(); 1956 } 1957 1958 // https://issues.dlang.org/show_bug.cgi?id=19626 1959 @safe pure unittest 1960 { 1961 enum T { a, b } 1962 alias t = RedBlackTree!T; 1963 } 1964 1965 import std.range.primitives : isInputRange, ElementType; 1966 import std.traits : isArray, isSomeString; 1967 1968 /++ 1969 Convenience function for creating a `RedBlackTree!E` from a list of 1970 values. 1971 1972 Params: 1973 allowDuplicates = Whether duplicates should be allowed (optional, default: false) 1974 less = predicate to sort by (optional) 1975 elems = elements to insert into the rbtree (variadic arguments) 1976 range = range elements to insert into the rbtree (alternative to elems) 1977 +/ 1978 auto redBlackTree(E)(E[] elems...) 1979 { 1980 return new RedBlackTree!E(elems); 1981 } 1982 1983 /++ Ditto +/ 1984 auto redBlackTree(bool allowDuplicates, E)(E[] elems...) 1985 { 1986 return new RedBlackTree!(E, "a < b", allowDuplicates)(elems); 1987 } 1988 1989 /++ Ditto +/ 1990 auto redBlackTree(alias less, E)(E[] elems...) 1991 if (is(typeof(binaryFun!less(E.init, E.init)))) 1992 { 1993 return new RedBlackTree!(E, less)(elems); 1994 } 1995 1996 /++ Ditto +/ 1997 auto redBlackTree(alias less, bool allowDuplicates, E)(E[] elems...) 1998 if (is(typeof(binaryFun!less(E.init, E.init)))) 1999 { 2000 //We shouldn't need to instantiate less here, but for some reason, 2001 //dmd can't handle it if we don't (even though the template which 2002 //takes less but not allowDuplicates works just fine). 2003 return new RedBlackTree!(E, binaryFun!less, allowDuplicates)(elems); 2004 } 2005 2006 /++ Ditto +/ 2007 auto redBlackTree(Stuff)(Stuff range) 2008 if (isInputRange!Stuff && !isArray!(Stuff)) 2009 { 2010 return new RedBlackTree!(ElementType!Stuff)(range); 2011 } 2012 2013 /++ Ditto +/ 2014 auto redBlackTree(bool allowDuplicates, Stuff)(Stuff range) 2015 if (isInputRange!Stuff && !isArray!(Stuff)) 2016 { 2017 return new RedBlackTree!(ElementType!Stuff, "a < b", allowDuplicates)(range); 2018 } 2019 2020 /++ Ditto +/ 2021 auto redBlackTree(alias less, Stuff)(Stuff range) 2022 if ( is(typeof(binaryFun!less((ElementType!Stuff).init, (ElementType!Stuff).init))) 2023 && isInputRange!Stuff && !isArray!(Stuff)) 2024 { 2025 return new RedBlackTree!(ElementType!Stuff, less)(range); 2026 } 2027 2028 /++ Ditto +/ 2029 auto redBlackTree(alias less, bool allowDuplicates, Stuff)(Stuff range) 2030 if ( is(typeof(binaryFun!less((ElementType!Stuff).init, (ElementType!Stuff).init))) 2031 && isInputRange!Stuff && !isArray!(Stuff)) 2032 { 2033 //We shouldn't need to instantiate less here, but for some reason, 2034 //dmd can't handle it if we don't (even though the template which 2035 //takes less but not allowDuplicates works just fine). 2036 return new RedBlackTree!(ElementType!Stuff, binaryFun!less, allowDuplicates)(range); 2037 } 2038 2039 /// 2040 @safe pure unittest 2041 { 2042 import std.range : iota; 2043 2044 auto rbt1 = redBlackTree(0, 1, 5, 7); 2045 auto rbt2 = redBlackTree!string("hello", "world"); 2046 auto rbt3 = redBlackTree!true(0, 1, 5, 7, 5); 2047 auto rbt4 = redBlackTree!"a > b"(0, 1, 5, 7); 2048 auto rbt5 = redBlackTree!("a > b", true)(0.1, 1.3, 5.9, 7.2, 5.9); 2049 2050 // also works with ranges 2051 auto rbt6 = redBlackTree(iota(3)); 2052 auto rbt7 = redBlackTree!true(iota(3)); 2053 auto rbt8 = redBlackTree!"a > b"(iota(3)); 2054 auto rbt9 = redBlackTree!("a > b", true)(iota(3)); 2055 } 2056 2057 //Combinations not in examples. 2058 @system pure unittest 2059 { 2060 auto rbt1 = redBlackTree!(true, string)("hello", "hello"); 2061 auto rbt2 = redBlackTree!((a, b){return a < b;}, double)(5.1, 2.3); 2062 auto rbt3 = redBlackTree!("a > b", true, string)("hello", "world"); 2063 } 2064 2065 //Range construction. 2066 @safe pure unittest 2067 { 2068 import std.algorithm.comparison : equal; 2069 import std.range : iota; 2070 auto rbt = new RedBlackTree!(int, "a > b")(iota(5)); 2071 assert(equal(rbt[], [4, 3, 2, 1, 0])); 2072 } 2073 2074 2075 // construction with arrays 2076 @safe pure unittest 2077 { 2078 import std.algorithm.comparison : equal; 2079 2080 auto rbt = redBlackTree!"a > b"([0, 1, 2, 3, 4]); 2081 assert(equal(rbt[], [4, 3, 2, 1, 0])); 2082 2083 auto rbt2 = redBlackTree!"a > b"(["a", "b"]); 2084 assert(equal(rbt2[], ["b", "a"])); 2085 2086 auto rbt3 = redBlackTree!"a > b"([1, 2]); 2087 assert(equal(rbt3[], [2, 1])); 2088 2089 auto rbt4 = redBlackTree([0, 1, 7, 5]); 2090 assert(equal(rbt4[], [0, 1, 5, 7])); 2091 2092 auto rbt5 = redBlackTree(["hello", "world"]); 2093 assert(equal(rbt5[], ["hello", "world"])); 2094 2095 auto rbt6 = redBlackTree!true([0, 1, 5, 7, 5]); 2096 assert(equal(rbt6[], [0, 1, 5, 5, 7])); 2097 2098 auto rbt7 = redBlackTree!"a > b"([0, 1, 5, 7]); 2099 assert(equal(rbt7[], [7, 5, 1, 0])); 2100 2101 auto rbt8 = redBlackTree!("a > b", true)([0.1, 1.3, 5.9, 7.2, 5.9]); 2102 assert(equal(rbt8[], [7.2, 5.9, 5.9, 1.3, 0.1])); 2103 } 2104 2105 // convenience wrapper range construction 2106 @safe pure unittest 2107 { 2108 import std.algorithm.comparison : equal; 2109 import std.range : chain, iota; 2110 2111 auto rbt = redBlackTree(iota(3)); 2112 assert(equal(rbt[], [0, 1, 2])); 2113 2114 auto rbt2 = redBlackTree!"a > b"(iota(2)); 2115 assert(equal(rbt2[], [1, 0])); 2116 2117 auto rbt3 = redBlackTree(chain([0, 1], [7, 5])); 2118 assert(equal(rbt3[], [0, 1, 5, 7])); 2119 2120 auto rbt4 = redBlackTree(chain(["hello"], ["world"])); 2121 assert(equal(rbt4[], ["hello", "world"])); 2122 2123 auto rbt5 = redBlackTree!true(chain([0, 1], [5, 7, 5])); 2124 assert(equal(rbt5[], [0, 1, 5, 5, 7])); 2125 2126 auto rbt6 = redBlackTree!("a > b", true)(chain([0.1, 1.3], [5.9, 7.2, 5.9])); 2127 assert(equal(rbt6[], [7.2, 5.9, 5.9, 1.3, 0.1])); 2128 } 2129 2130 @safe pure unittest 2131 { 2132 import std.array : array; 2133 2134 auto rt1 = redBlackTree(5, 4, 3, 2, 1); 2135 assert(rt1.length == 5); 2136 assert(array(rt1[]) == [1, 2, 3, 4, 5]); 2137 2138 auto rt2 = redBlackTree!"a > b"(1.1, 2.1); 2139 assert(rt2.length == 2); 2140 assert(array(rt2[]) == [2.1, 1.1]); 2141 2142 auto rt3 = redBlackTree!true(5, 5, 4); 2143 assert(rt3.length == 3); 2144 assert(array(rt3[]) == [4, 5, 5]); 2145 2146 auto rt4 = redBlackTree!string("hello", "hello"); 2147 assert(rt4.length == 1); 2148 assert(array(rt4[]) == ["hello"]); 2149 } 2150 2151 @system unittest 2152 { 2153 import std.conv : to; 2154 2155 auto rt1 = redBlackTree!string(); 2156 assert(rt1.to!string == "RedBlackTree([])"); 2157 2158 auto rt2 = redBlackTree!string("hello"); 2159 assert(rt2.to!string == "RedBlackTree([\"hello\"])"); 2160 2161 auto rt3 = redBlackTree!string("hello", "world", "!"); 2162 assert(rt3.to!string == "RedBlackTree([\"!\", \"hello\", \"world\"])"); 2163 2164 // type deduction can be done automatically 2165 auto rt4 = redBlackTree(["hello"]); 2166 assert(rt4.to!string == "RedBlackTree([\"hello\"])"); 2167 } 2168 2169 //constness checks 2170 @safe pure unittest 2171 { 2172 const rt1 = redBlackTree(5,4,3,2,1); 2173 void allQualifiers() pure nothrow @safe @nogc { 2174 assert(!rt1.empty); 2175 assert(rt1.length == 5); 2176 assert(5 in rt1); 2177 } 2178 allQualifiers(); 2179 2180 static assert(is(typeof(rt1.upperBound(3).front) == const(int))); 2181 import std.algorithm.comparison : equal; 2182 assert(rt1.upperBound(3).equal([4, 5])); 2183 assert(rt1.lowerBound(3).equal([1, 2])); 2184 assert(rt1.equalRange(3).equal([3])); 2185 assert(rt1[].equal([1, 2, 3, 4, 5])); 2186 } 2187 2188 //immutable checks 2189 @safe pure unittest 2190 { 2191 immutable rt1 = redBlackTree(5,4,3,2,1); 2192 static assert(is(typeof(rt1.empty))); 2193 static assert(is(typeof(rt1.length))); 2194 static assert(is(typeof(5 in rt1))); 2195 2196 static assert(is(typeof(rt1.upperBound(3).front) == immutable(int))); 2197 import std.algorithm.comparison : equal; 2198 assert(rt1.upperBound(2).equal([3, 4, 5])); 2199 } 2200 2201 // https://issues.dlang.org/show_bug.cgi?id=15941 2202 @safe pure unittest 2203 { 2204 class C {} 2205 RedBlackTree!(C, "cast(void*)a < cast(void*) b") tree; 2206 } 2207 2208 // const/immutable elements (https://issues.dlang.org/show_bug.cgi?id=17519) 2209 @safe pure unittest 2210 { 2211 RedBlackTree!(immutable int) t1; 2212 RedBlackTree!(const int) t2; 2213 2214 import std.algorithm.iteration : map; 2215 static struct S { int* p; } 2216 auto t3 = new RedBlackTree!(immutable S, (a, b) => *a.p < *b.p); 2217 t3.insert([1, 2, 3].map!(x => immutable S(new int(x)))); 2218 static assert(!__traits(compiles, *t3.front.p = 4)); 2219 assert(*t3.front.p == 1); 2220 } 2221 2222 // make sure the comparator can be a delegate 2223 @safe pure unittest 2224 { 2225 import std.algorithm.comparison : equal; 2226 2227 auto t = new RedBlackTree!(int, delegate(a, b) => a > b); 2228 t.insert([1, 3, 5, 4, 2]); 2229 assert(t[].equal([5, 4, 3, 2, 1])); 2230 }