1 /** 2 * Implementation of a custom allocator red-black tree container. 3 * 4 * Copyright: Red-black tree code copyright (C) 2008- by Steven Schveighoffer. Other code 5 * copyright 2010- Andrei Alexandrescu. All rights reserved by the respective holders. 6 * License: Distributed under the Boost Software License, Version 1.0. 7 * (See at $(WEB boost.org/LICENSE_1_0.txt)). 8 * Authors: Steven Schveighoffer, $(WEB erdani.com, Andrei Alexandrescu) 9 */ 10 module memutils.rbtree; 11 12 import std.functional; // : binaryFun; 13 import std.traits; 14 import std.range; 15 import std.algorithm : countUntil; 16 import memutils.allocators; 17 import memutils.refcounted; 18 import memutils.vector; 19 import memutils.constants; 20 import memutils.utils; 21 22 alias RBTreeRef(T, alias less = "a < b", bool allowDuplicates = true, ALLOC = ThreadMem, bool NOGC_ = false) = RefCounted!(RBTree!(T, less, allowDuplicates, ALLOC, NOGC_)); 23 24 template isImplicitlyConvertibleLegacy(From, To) 25 { 26 enum bool isImplicitlyConvertibleLegacy = is(typeof({ 27 void fun(ref From v) 28 { 29 void gun(To) {} 30 gun(v); 31 } 32 })); 33 } 34 35 /** 36 * All inserts, removes, searches, and any function in general has complexity 37 * of $(BIGOH lg(n)). 38 * 39 * To use a different comparison than $(D "a < b"), pass a different operator string 40 * that can be used by $(XREF functional, binaryFun), or pass in a 41 * function, delegate, functor, or any type where $(D less(a, b)) results in a $(D bool) 42 * value. 43 * 44 * Note that less should produce a strict ordering. That is, for two unequal 45 * elements $(D a) and $(D b), $(D less(a, b) == !less(b, a)). $(D less(a, a)) should 46 * always equal $(D false). 47 * 48 * If $(D allowDuplicates) is set to $(D true), then inserting the same element more than 49 * once continues to add more elements. If it is $(D false), duplicate elements are 50 * ignored on insertion. If duplicates are allowed, then new elements are 51 * inserted after all existing duplicate elements. 52 */ 53 struct RBTree(T, alias less = "a < b", bool allowDuplicates = true, ALLOC = ThreadMem, bool NOGC_ = false) 54 if(is(typeof(binaryFun!less(T.init, T.init)))) 55 { 56 @disable this(this); 57 58 import std.range : Take; 59 import std.typetuple : allSatisfy; 60 import std.traits; 61 62 alias _less = binaryFun!less; 63 64 // BUG: this must come first in the struct due to issue 2810 65 66 // add an element to the tree, returns the node added, or the existing node 67 // if it has already been added and allowDuplicates is false 68 69 private auto _add(Elem n) 70 { 71 Node result; 72 static if(!allowDuplicates) 73 bool added = true; 74 75 if(!_end.left) 76 { 77 _end.left = _begin = result = allocate(n); 78 } 79 else 80 { 81 Node newParent = _end.left; 82 Node nxt = void; 83 while(true) 84 { 85 if(_less(n, newParent.value)) 86 { 87 nxt = newParent.left; 88 if(nxt is null) 89 { 90 // 91 // add to right of new parent 92 // 93 newParent.left = result = allocate(n); 94 break; 95 } 96 } 97 else 98 { 99 static if(!allowDuplicates) 100 { 101 if(!_less(newParent.value, n)) 102 { 103 result = newParent; 104 added = false; 105 break; 106 } 107 } 108 nxt = newParent.right; 109 if(nxt is null) 110 { 111 // 112 // add to right of new parent 113 // 114 newParent.right = result = allocate(n); 115 break; 116 } 117 } 118 newParent = nxt; 119 } 120 if(_begin.left) 121 _begin = _begin.left; 122 } 123 124 static if(allowDuplicates) 125 { 126 result.setColor(_end); 127 ++_length; 128 return result; 129 } 130 else 131 { 132 import std.typecons : Tuple; 133 134 if(added) 135 { 136 ++_length; 137 result.setColor(_end); 138 } 139 return Tuple!(bool, "added", Node, "n")(added, result); 140 } 141 } 142 143 144 private enum doUnittest = false; 145 146 /** 147 * Element type for the tree 148 */ 149 alias Elem = T; 150 151 // used for convenience 152 private alias Node = RBNode!(Elem, ALLOC, NOGC_).Node; 153 154 private Node _root; 155 private Node _end; 156 private Node _begin; 157 private size_t _length; 158 159 package void _defaultInitialize() 160 { 161 if (!_end) { 162 _begin = _end = _root = allocate(); 163 } 164 } 165 166 static private Node allocate() 167 { 168 return ObjectAllocator!(RBNode!(Elem, ALLOC, NOGC_), ALLOC).alloc(); 169 } 170 171 static private Node allocate(Elem v) 172 { 173 auto result = allocate(); 174 logTrace("Allocating node ", cast(void*)result); 175 result.value = v; 176 return result; 177 } 178 179 // find a node based on an element value 180 private Node _find(Elem e) const 181 { 182 static if(allowDuplicates) 183 { 184 Node cur = _end.left; 185 Node result = null; 186 while(cur) 187 { 188 if(_less(cur.value, e)) 189 cur = cur.right; 190 else if(_less(e, cur.value)) 191 cur = cur.left; 192 else 193 { 194 // want to find the left-most element 195 result = cur; 196 cur = cur.left; 197 } 198 } 199 return result; 200 } 201 else 202 { 203 Node cur = _end.left; 204 while(cur) 205 { 206 if(_less(cur.value, e)) 207 cur = cur.right; 208 else if(_less(e, cur.value)) 209 cur = cur.left; 210 else 211 return cur; 212 } 213 return null; 214 } 215 } 216 217 218 219 /** 220 * Check if any elements exist in the container. Returns $(D false) if at least 221 * one element exists. 222 */ 223 @property bool empty() const 224 { 225 return _end.left is null; 226 } 227 228 /++ 229 Returns the number of elements in the container. 230 231 Complexity: $(BIGOH 1). 232 +/ 233 @property size_t length() const 234 { 235 return _length; 236 } 237 238 /** 239 * Fetch a range that spans all the elements in the container. 240 * 241 * Complexity: $(BIGOH 1) 242 */ 243 RBRange!(Elem, ALLOC, NOGC_) opSlice() 244 { 245 _defaultInitialize(); 246 return range!(T, ALLOC, NOGC_)(_begin, _end); 247 } 248 249 /** 250 * The front element in the container 251 * 252 * Complexity: $(BIGOH 1) 253 */ 254 ref Elem front() 255 { 256 _defaultInitialize(); 257 return _begin.value; 258 } 259 260 /** 261 * The last element in the container 262 * 263 * Complexity: $(BIGOH log(n)) 264 */ 265 ref Elem back() 266 { 267 _defaultInitialize(); 268 return _end.prev.value; 269 } 270 271 /++ 272 $(D in) operator. Check to see if the given element exists in the 273 container. 274 275 Complexity: $(BIGOH log(n)) 276 +/ 277 pragma(inline, true) 278 bool opBinaryRight(string op)(Elem e) const if (op == "in") 279 { 280 return _find(e) !is null; 281 } 282 283 /** 284 * Removes all elements from the container. 285 * 286 * Complexity: $(BIGOH 1) 287 */ 288 void clear() 289 { 290 _defaultInitialize(); 291 logTrace("Clearing rbtree"); 292 while (length > 0) 293 removeAny(); 294 logTrace(length, " items left"); 295 return; 296 } 297 298 /** 299 * Insert a single element in the container. Note that this does not 300 * invalidate any ranges currently iterating the container. 301 * 302 * Complexity: $(BIGOH log(n)) 303 */ 304 pragma(inline, true) 305 size_t insert(Stuff)(Stuff stuff) if (isImplicitlyConvertibleLegacy!(Stuff, Elem)) 306 { 307 _defaultInitialize(); 308 static if(allowDuplicates) 309 { 310 _add(stuff); 311 return 1; 312 } 313 else 314 { 315 return(_add(stuff).added ? 1 : 0); 316 } 317 } 318 319 /** 320 * Insert a range of elements in the container. Note that this does not 321 * invalidate any ranges currently iterating the container. 322 * 323 * Complexity: $(BIGOH m * log(n)) 324 */ 325 pragma(inline, true) 326 size_t insert(Stuff)(Stuff stuff) if(isInputRange!Stuff && isImplicitlyConvertibleLegacy!(ElementType!Stuff, Elem)) 327 { 328 _defaultInitialize(); 329 size_t result = 0; 330 static if(allowDuplicates) 331 { 332 foreach(e; stuff) 333 { 334 ++result; 335 _add(e); 336 } 337 } 338 else 339 { 340 foreach(e; stuff) 341 { 342 if(_add(e).added) 343 ++result; 344 } 345 } 346 return result; 347 } 348 349 350 /** 351 * Remove an element from the container and return its value. 352 * 353 * Complexity: $(BIGOH log(n)) 354 */ 355 Elem removeAny() 356 { 357 _defaultInitialize(); 358 scope(success) 359 --_length; 360 auto n = _begin; 361 auto result = n.value; 362 _begin = n.remove(_end); 363 return result; 364 } 365 366 /** 367 * Remove the front element from the container. 368 * 369 * Complexity: $(BIGOH log(n)) 370 */ 371 void removeFront() 372 { 373 _defaultInitialize(); 374 scope(success) 375 --_length; 376 _begin = _begin.remove(_end); 377 } 378 379 /** 380 * Remove the back element from the container. 381 * 382 * Complexity: $(BIGOH log(n)) 383 */ 384 void removeBack() 385 { 386 _defaultInitialize(); 387 scope(success) 388 --_length; 389 auto lastnode = _end.prev; 390 if(lastnode is _begin) 391 _begin = _begin.remove(_end); 392 else 393 lastnode.remove(_end); 394 } 395 396 /++ 397 Removes elements from the container that are equal to the given values 398 according to the less comparator. One element is removed for each value 399 given which is in the container. If $(D allowDuplicates) is true, 400 duplicates are removed only if duplicate values are given. 401 402 Returns: The number of elements removed. 403 404 Complexity: $(BIGOH m log(n)) (where m is the number of elements to remove) 405 406 Examples: 407 -------------------- 408 auto rbt = redBlackTree!true(0, 1, 1, 1, 4, 5, 7); 409 rbt.removeKey(1, 4, 7); 410 assert(equal(rbt[], [0, 1, 1, 5])); 411 rbt.removeKey(1, 1, 0); 412 assert(equal(rbt[], [5])); 413 -------------------- 414 +/ 415 size_t remove(U...)(U elems) 416 if(allSatisfy!(isImplicitlyConvertibleToElem, U)) 417 { 418 _defaultInitialize(); 419 Elem[U.length] toRemove; 420 421 foreach(i, e; elems) 422 toRemove[i] = e; 423 424 return remove(toRemove[]); 425 } 426 427 /++ Ditto +/ 428 size_t remove(U)(U[] elems) 429 if(isImplicitlyConvertibleLegacy!(U, Elem)) 430 { 431 _defaultInitialize(); 432 immutable lenBefore = length; 433 434 foreach(e; elems) 435 { 436 auto beg = _firstGreaterEqual(e); 437 if(beg is _end || _less(e, beg.value)) 438 // no values are equal 439 continue; 440 immutable isBegin = (beg is _begin); 441 beg = beg.remove(_end); 442 if(isBegin) 443 _begin = beg; 444 --_length; 445 } 446 447 return lenBefore - length; 448 } 449 450 /++ Ditto +/ 451 size_t remove(Stuff)(Stuff stuff) 452 if(isInputRange!Stuff && 453 isImplicitlyConvertibleLegacy!(ElementType!Stuff, Elem) && 454 !isDynamicArray!Stuff) 455 { 456 _defaultInitialize(); 457 import std.array : array; 458 //We use array in case stuff is a Range from this RedBlackTree - either 459 //directly or indirectly. 460 return remove(array(stuff)); 461 } 462 463 //Helper for removeKey. 464 private template isImplicitlyConvertibleToElem(U) 465 { 466 enum isImplicitlyConvertibleToElem = isImplicitlyConvertibleLegacy!(U, Elem); 467 } 468 469 /** 470 * Compares two trees for equality. 471 * 472 * Complexity: $(BIGOH n*log(n)) 473 */ 474 bool opEquals(ref RBTree rhs) 475 { 476 _defaultInitialize(); 477 import std.algorithm : equal; 478 if (rhs.empty) return false; 479 480 // If there aren't the same number of nodes, we can't be equal. 481 if (this._length != rhs._length) return false; 482 483 auto thisRange = this[]; 484 auto thatRange = rhs[]; 485 return equal!(function(Elem a, Elem b) => !_less(a,b) && !_less(b,a))(thisRange, thatRange); 486 } 487 488 // find the first node where the value is > e 489 private Node _firstGreater(Elem e) 490 { 491 // can't use _find, because we cannot return null 492 auto cur = _end.left; 493 auto result = _end; 494 while(cur) 495 { 496 if(_less(e, cur.value)) 497 { 498 result = cur; 499 cur = cur.left; 500 } 501 else 502 cur = cur.right; 503 } 504 return result; 505 } 506 507 // find the first node where the value is >= e 508 private Node _firstGreaterEqual(Elem e) 509 { 510 // can't use _find, because we cannot return null. 511 auto cur = _end.left; 512 auto result = _end; 513 while(cur) 514 { 515 if(_less(cur.value, e)) 516 cur = cur.right; 517 else 518 { 519 result = cur; 520 cur = cur.left; 521 } 522 523 } 524 return result; 525 } 526 527 /** 528 * Get a range from the container with all elements that are > e according 529 * to the less comparator 530 * 531 * Complexity: $(BIGOH log(n)) 532 */ 533 auto upperBoundRange(Elem e) 534 { 535 _defaultInitialize(); 536 return range!(T, ALLOC, NOGC_)(_firstGreater(e), _end); 537 } 538 539 /** 540 * Get a range from the container with all elements that are < e according 541 * to the less comparator 542 * 543 * Complexity: $(BIGOH log(n)) 544 */ 545 auto lowerBoundRange(Elem e) 546 { 547 _defaultInitialize(); 548 return range!(T, ALLOC, NOGC_)(_begin, _firstGreaterEqual(e)); 549 } 550 551 /** 552 * Get a range from the container with all elements that are == e according 553 * to the less comparator 554 * 555 * Complexity: $(BIGOH log(n)) 556 */ 557 auto getValuesAt(Elem e) 558 { 559 _defaultInitialize(); 560 auto beg = _firstGreaterEqual(e); 561 if(beg is _end || _less(e, beg.value)) 562 // no values are equal 563 return range!(T, ALLOC, NOGC_)(beg, beg); 564 static if(allowDuplicates) 565 { 566 return range!(T, ALLOC, NOGC_)(beg, _firstGreater(e)); 567 } 568 else 569 { 570 // no sense in doing a full search, no duplicates are allowed, 571 // so we just get the next node. 572 return range!(T, ALLOC, NOGC_)(beg, beg.next); 573 } 574 } 575 576 this(size_t elems) { 577 _defaultInitialize(); 578 } 579 580 /** 581 * Constructor. Pass in an array of elements, or individual elements to 582 * initialize the tree with. 583 */ 584 this(Elem[] elems...) 585 { 586 _defaultInitialize(); 587 static if (is(Elem == void[])) { 588 foreach(elem;elems) insert(elem); 589 } 590 else 591 insert(elems); 592 } 593 594 /** 595 * Constructor. Pass in a range of elements to initialize the tree with. 596 */ 597 this(Stuff)(Stuff stuff) if (isInputRange!Stuff && isImplicitlyConvertibleLegacy!(ElementType!Stuff, Elem)) 598 { 599 _defaultInitialize(); 600 insert(stuff); 601 } 602 603 ~this() { 604 if (!_end) return; 605 clear(); 606 ObjectAllocator!(RBNode!(Elem, ALLOC, NOGC_), ALLOC).free(_root); 607 } 608 609 private this(Node end, size_t length) 610 { 611 _end = end; 612 _begin = end.leftmost; 613 _length = length; 614 } 615 } 616 617 /* 618 * Implementation for a Red Black node for use in a Red Black Tree (see below) 619 * 620 * this implementation assumes we have a marker Node that is the parent of the 621 * root Node. This marker Node is not a valid Node, but marks the end of the 622 * collection. The root is the left child of the marker Node, so it is always 623 * last in the collection. The marker Node is passed in to the setColor 624 * function, and the Node which has this Node as its parent is assumed to be 625 * the root Node. 626 * 627 * A Red Black tree should have O(lg(n)) insertion, removal, and search time. 628 */ 629 struct RBNode(V, ALLOC, bool NOGC_ = false) 630 { 631 enum NOGC = NOGC_; 632 /* 633 * Convenience alias 634 */ 635 alias Node = RBNode!(V, ALLOC, NOGC_)*; 636 637 private Node _left; 638 private Node _right; 639 private Node _parent; 640 641 /** 642 * The value held by this node 643 */ 644 V value; 645 646 /** 647 * Enumeration determining what color the node is. Null nodes are assumed 648 * to be black. 649 */ 650 enum Color : byte 651 { 652 Red, 653 Black 654 } 655 656 /** 657 * The color of the node. 658 */ 659 Color color; 660 661 /** 662 * Get the left child 663 */ 664 @property Node left() const 665 { 666 return cast(Node)_left; 667 } 668 669 /** 670 * Get the right child 671 */ 672 @property inout(Node) right() inout 673 { 674 return _right; 675 } 676 677 /** 678 * Get the parent 679 */ 680 @property Node parent() 681 { 682 return _parent; 683 } 684 685 /** 686 * Set the left child. Also updates the new child's parent node. This 687 * does not update the previous child. 688 * 689 * Returns newNode 690 */ 691 @property Node left(Node newNode) 692 { 693 _left = newNode; 694 if(newNode !is null) 695 newNode._parent = &this; 696 return newNode; 697 } 698 699 /** 700 * Set the right child. Also updates the new child's parent node. This 701 * does not update the previous child. 702 * 703 * Returns newNode 704 */ 705 @property Node right(Node newNode) 706 { 707 _right = newNode; 708 if(newNode !is null) 709 newNode._parent = &this; 710 return newNode; 711 } 712 713 // assume _left is not null 714 // 715 // performs rotate-right operation, where this is T, _right is R, _left is 716 // L, _parent is P: 717 // 718 // P P 719 // | -> | 720 // T L 721 // / \ / \ 722 // L R a T 723 // / \ / \ 724 // a b b R 725 // 726 /** 727 * Rotate right. This performs the following operations: 728 * - The left child becomes the parent of this node. 729 * - This node becomes the new parent's right child. 730 * - The old right child of the new parent becomes the left child of this 731 * node. 732 */ 733 Node rotateR() 734 in 735 { 736 assert(_left !is null); 737 } 738 do 739 { 740 // sets _left._parent also 741 if(isLeftNode) 742 parent.left = _left; 743 else 744 parent.right = _left; 745 Node tmp = _left._right; 746 747 // sets _parent also 748 _left.right = &this; 749 750 // sets tmp._parent also 751 left = tmp; 752 753 return &this; 754 } 755 756 // assumes _right is non null 757 // 758 // performs rotate-left operation, where this is T, _right is R, _left is 759 // L, _parent is P: 760 // 761 // P P 762 // | -> | 763 // T R 764 // / \ / \ 765 // L R T b 766 // / \ / \ 767 // a b L a 768 // 769 /** 770 * Rotate left. This performs the following operations: 771 * - The right child becomes the parent of this node. 772 * - This node becomes the new parent's left child. 773 * - The old left child of the new parent becomes the right child of this 774 * node. 775 */ 776 Node rotateL() 777 in 778 { 779 assert(_right !is null); 780 } 781 do 782 { 783 // sets _right._parent also 784 if(isLeftNode) 785 parent.left = _right; 786 else 787 parent.right = _right; 788 Node tmp = _right._left; 789 790 // sets _parent also 791 _right.left = &this; 792 793 // sets tmp._parent also 794 right = tmp; 795 return &this; 796 } 797 798 799 /** 800 * Returns true if this node is a left child. 801 * 802 * Note that this should always return a value because the root has a 803 * parent which is the marker node. 804 */ 805 @property bool isLeftNode() const 806 in 807 { 808 assert(_parent !is null); 809 } 810 do 811 { 812 return _parent._left is &this; 813 } 814 815 /** 816 * Set the color of the node after it is inserted. This performs an 817 * update to the whole tree, possibly rotating nodes to keep the Red-Black 818 * properties correct. This is an O(lg(n)) operation, where n is the 819 * number of nodes in the tree. 820 * 821 * end is the marker node, which is the parent of the topmost valid node. 822 */ 823 void setColor(Node end) 824 { 825 // test against the marker node 826 if(_parent !is end) 827 { 828 if(_parent.color == Color.Red) 829 { 830 Node cur = &this; 831 while(true) 832 { 833 // because root is always black, _parent._parent always exists 834 if(cur._parent.isLeftNode) 835 { 836 // parent is left node, y is 'uncle', could be null 837 Node y = cur._parent._parent._right; 838 if(y !is null && y.color == Color.Red) 839 { 840 cur._parent.color = Color.Black; 841 y.color = Color.Black; 842 cur = cur._parent._parent; 843 if(cur._parent is end) 844 { 845 // root node 846 cur.color = Color.Black; 847 break; 848 } 849 else 850 { 851 // not root node 852 cur.color = Color.Red; 853 if(cur._parent.color == Color.Black) 854 // satisfied, exit the loop 855 break; 856 } 857 } 858 else 859 { 860 if(!cur.isLeftNode) 861 cur = cur._parent.rotateL(); 862 cur._parent.color = Color.Black; 863 cur = cur._parent._parent.rotateR(); 864 cur.color = Color.Red; 865 // tree should be satisfied now 866 break; 867 } 868 } 869 else 870 { 871 // parent is right node, y is 'uncle' 872 Node y = cur._parent._parent._left; 873 if(y !is null && y.color == Color.Red) 874 { 875 cur._parent.color = Color.Black; 876 y.color = Color.Black; 877 cur = cur._parent._parent; 878 if(cur._parent is end) 879 { 880 // root node 881 cur.color = Color.Black; 882 break; 883 } 884 else 885 { 886 // not root node 887 cur.color = Color.Red; 888 if(cur._parent.color == Color.Black) 889 // satisfied, exit the loop 890 break; 891 } 892 } 893 else 894 { 895 if(cur.isLeftNode) 896 cur = cur._parent.rotateR(); 897 cur._parent.color = Color.Black; 898 cur = cur._parent._parent.rotateL(); 899 cur.color = Color.Red; 900 // tree should be satisfied now 901 break; 902 } 903 } 904 } 905 906 } 907 } 908 else 909 { 910 // 911 // this is the root node, color it black 912 // 913 color = Color.Black; 914 } 915 } 916 917 /** 918 * Remove this node from the tree. The 'end' node is used as the marker 919 * which is root's parent. Note that this cannot be null! 920 * 921 * Returns the next highest valued node in the tree after this one, or end 922 * if this was the highest-valued node. 923 */ 924 Node remove(Node end) 925 { 926 // 927 // remove this node from the tree, fixing the color if necessary. 928 // 929 Node x; 930 Node ret = next; 931 932 // if this node has 2 children 933 if (_left !is null && _right !is null) 934 { 935 // 936 // normally, we can just swap this node's and y's value, but 937 // because an iterator could be pointing to y and we don't want to 938 // disturb it, we swap this node and y's structure instead. This 939 // can also be a benefit if the value of the tree is a large 940 // struct, which takes a long time to copy. 941 // 942 Node yp, yl, yr; 943 Node y = ret; // y = next 944 yp = y._parent; 945 yl = y._left; 946 yr = y._right; 947 auto yc = y.color; 948 auto isyleft = y.isLeftNode; 949 950 // 951 // replace y's structure with structure of this node. 952 // 953 if(isLeftNode) 954 _parent.left = y; 955 else 956 _parent.right = y; 957 // 958 // need special case so y doesn't point back to itself 959 // 960 y.left = _left; 961 if(_right is y) 962 y.right = &this; 963 else 964 y.right = _right; 965 y.color = color; 966 967 // 968 // replace this node's structure with structure of y. 969 // 970 left = yl; 971 right = yr; 972 if(_parent !is y) 973 { 974 if(isyleft) 975 yp.left = &this; 976 else 977 yp.right = &this; 978 } 979 color = yc; 980 } 981 982 // if this has less than 2 children, remove it 983 if(_left !is null) 984 x = _left; 985 else 986 x = _right; 987 988 bool deferedUnlink = false; 989 if(x is null) 990 { 991 // pretend this is a null node, defer unlinking the node 992 x = &this; 993 deferedUnlink = true; 994 } 995 else if(isLeftNode) 996 _parent.left = x; 997 else 998 _parent.right = x; 999 1000 // if the color of this is black, then it needs to be fixed 1001 if(color == color.Black) 1002 { 1003 // need to recolor the tree. 1004 while(x._parent !is end && x.color == Node.Color.Black) 1005 { 1006 if(x.isLeftNode) 1007 { 1008 // left node 1009 Node w = x._parent._right; 1010 if(w.color == Node.Color.Red) 1011 { 1012 w.color = Node.Color.Black; 1013 x._parent.color = Node.Color.Red; 1014 x._parent.rotateL(); 1015 w = x._parent._right; 1016 } 1017 Node wl = w.left; 1018 Node wr = w.right; 1019 if((wl is null || wl.color == Node.Color.Black) && 1020 (wr is null || wr.color == Node.Color.Black)) 1021 { 1022 w.color = Node.Color.Red; 1023 x = x._parent; 1024 } 1025 else 1026 { 1027 if(wr is null || wr.color == Node.Color.Black) 1028 { 1029 // wl cannot be null here 1030 wl.color = Node.Color.Black; 1031 w.color = Node.Color.Red; 1032 w.rotateR(); 1033 w = x._parent._right; 1034 } 1035 1036 w.color = x._parent.color; 1037 x._parent.color = Node.Color.Black; 1038 w._right.color = Node.Color.Black; 1039 x._parent.rotateL(); 1040 x = end.left; // x = root 1041 } 1042 } 1043 else 1044 { 1045 // right node 1046 Node w = x._parent._left; 1047 if(w.color == Node.Color.Red) 1048 { 1049 w.color = Node.Color.Black; 1050 x._parent.color = Node.Color.Red; 1051 x._parent.rotateR(); 1052 w = x._parent._left; 1053 } 1054 Node wl = w.left; 1055 Node wr = w.right; 1056 if((wl is null || wl.color == Node.Color.Black) && 1057 (wr is null || wr.color == Node.Color.Black)) 1058 { 1059 w.color = Node.Color.Red; 1060 x = x._parent; 1061 } 1062 else 1063 { 1064 if(wl is null || wl.color == Node.Color.Black) 1065 { 1066 // wr cannot be null here 1067 wr.color = Node.Color.Black; 1068 w.color = Node.Color.Red; 1069 w.rotateL(); 1070 w = x._parent._left; 1071 } 1072 1073 w.color = x._parent.color; 1074 x._parent.color = Node.Color.Black; 1075 w._left.color = Node.Color.Black; 1076 x._parent.rotateR(); 1077 x = end.left; // x = root 1078 } 1079 } 1080 } 1081 x.color = Node.Color.Black; 1082 } 1083 1084 if(deferedUnlink) 1085 { 1086 // 1087 // unlink this node from the tree 1088 // 1089 if(isLeftNode) 1090 _parent.left = null; 1091 else 1092 _parent.right = null; 1093 1094 } 1095 1096 // clean references to help GC - Bugzilla 12915 1097 _left = _right = _parent = null; 1098 1099 /// this node object can now be safely deleted 1100 logTrace("Freeing node ", cast(void*)&this); 1101 ObjectAllocator!(RBNode!(V, ALLOC, NOGC_), ALLOC).free(cast(RBNode!(V, ALLOC, NOGC_)*)&this); 1102 1103 return ret; 1104 } 1105 1106 /** 1107 * Return the leftmost descendant of this node. 1108 */ 1109 @property Node leftmost() 1110 { 1111 Node result = &this; 1112 while(result._left !is null) 1113 result = result._left; 1114 return result; 1115 } 1116 1117 /** 1118 * Return the rightmost descendant of this node 1119 */ 1120 @property Node rightmost() 1121 { 1122 Node result = &this; 1123 while(result._right !is null) 1124 result = result._right; 1125 return result; 1126 } 1127 1128 /** 1129 * Returns the next valued node in the tree. 1130 * 1131 * You should never call this on the marker node, as it is assumed that 1132 * there is a valid next node. 1133 */ 1134 @property Node next() 1135 { 1136 Node n = &this; 1137 if(n.right is null) 1138 { 1139 while(n._parent && !n.isLeftNode) 1140 n = n._parent; 1141 return n._parent; 1142 } 1143 else if (n.right !is null) { 1144 if (!n._parent) return null; 1145 return n.right.leftmost; 1146 } 1147 else return null; 1148 } 1149 1150 /** 1151 * Returns the previous valued node in the tree. 1152 * 1153 * You should never call this on the leftmost node of the tree as it is 1154 * assumed that there is a valid previous node. 1155 */ 1156 @property Node prev() 1157 { 1158 Node n = &this; 1159 if(n.left is null) 1160 { 1161 while(n.isLeftNode) 1162 n = n._parent; 1163 return n._parent; 1164 } 1165 else 1166 return n.left.rightmost; 1167 } 1168 1169 @property Node clone() const 1170 { 1171 Node copy = ObjectAllocator!(RBNode!(V, ALLOC, NOGC_), ALLOC).alloc(); 1172 logTrace("Allocating node ", cast(void*)copy); 1173 copy.value = cast(V)value; 1174 copy.color = color; 1175 if(_left !is null) 1176 copy.left = _left.clone(); 1177 if(_right !is null) 1178 copy.right = _right.clone(); 1179 return copy; 1180 } 1181 1182 @disable @property Node dup() const; 1183 } 1184 1185 /** 1186 * The range type for $(D RedBlackTree) 1187 */ 1188 struct RBRange(Elem, ALLOC, bool NOGC_ = false) 1189 { 1190 alias Node = RBNode!(Elem, ALLOC, NOGC_).Node; 1191 private Node _begin; 1192 private Node _end; 1193 1194 private this(Node b, Node e) 1195 { 1196 _begin = b; 1197 _end = e; 1198 } 1199 1200 /** 1201 * Returns $(D true) if the range is _empty 1202 */ 1203 @property bool empty() const 1204 { 1205 return _begin is _end || !_begin; 1206 } 1207 1208 /** 1209 * Returns the first element in the range 1210 */ 1211 @property ref Elem front() 1212 { 1213 return _begin.value; 1214 } 1215 1216 /** 1217 * Returns the last element in the range 1218 */ 1219 @property ref Elem back() 1220 { 1221 return _end.prev.value; 1222 } 1223 1224 /** 1225 * pop the front element from the range 1226 * 1227 * complexity: amortized $(BIGOH 1) 1228 */ 1229 void popFront() 1230 { 1231 _begin = _begin.next; 1232 } 1233 1234 /** 1235 * pop the back element from the range 1236 * 1237 * complexity: amortized $(BIGOH 1) 1238 */ 1239 void popBack() 1240 { 1241 _end = _end.prev; 1242 } 1243 1244 /** 1245 * Trivial _save implementation, needed for $(D isForwardRBRange). 1246 */ 1247 @property RBRange save() 1248 { 1249 return *cast(RBRange*)&this; 1250 } 1251 } 1252 1253 private auto range(Elem, ALLOC, bool NOGC_ = false)(RBNode!(Elem, ALLOC, NOGC_)* start, RBNode!(Elem, ALLOC, NOGC_)* end) { 1254 return RBRange!(Elem, ALLOC, NOGC_)(start, end); 1255 } 1256 1257 auto vector(Elem, ALLOC, bool NOGC_ = false)(RBRange!(Elem, ALLOC, NOGC_) r) { 1258 return Vector!(Unqual!Elem, ALLOC)(r); 1259 }