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