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 }