1 /** 2 * This module implements an associative array. 3 * @nogc associative array, replacement for std::map and std::set. 4 * Implementation of Red Black Tree from Phobos. 5 * 6 * Copyright: Copyright Auburn Sounds 2015-2016 7 * Copyright: Copyright (C) 2008- by Steven Schveighoffer. Other code 8 * Copyright: 2010- Andrei Alexandrescu. All rights reserved by the respective holders. 9 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 10 * Authors: Authors: Steven Schveighoffer, $(HTTP erdani.com, Andrei Alexandrescu), Guillaume Piolat 11 */ 12 module dplug.core.map; 13 14 import std.functional: binaryFun; 15 16 import dplug.core.nogc; 17 18 nothrow: 19 @nogc: 20 21 /// Creates a new empty `Map`. 22 Map!(K, V, less, allowDuplicates) makeMap(K, V, alias less = "a < b", bool allowDuplicates = false)() 23 { 24 return Map!(K, V, less, allowDuplicates)(42); 25 } 26 27 /// Tree-map, designed to replace std::map usage. 28 /// The API should looks closely like the builtin associative arrays. 29 /// O(lg(n)) insertion, removal, and search time. 30 /// `Map` is designed to operate even without initialization through `makeMap`. 31 struct Map(K, V, alias less = "a < b", bool allowDuplicates = false) 32 { 33 public: 34 nothrow: 35 @nogc: 36 37 this(int dummy) 38 { 39 lazyInitialize(); 40 } 41 42 @disable this(this); 43 44 ~this() 45 { 46 if (_rbt !is null) 47 { 48 destroyFree(_rbt); 49 _rbt = null; 50 } 51 } 52 53 /// Insert an element in the container, if the container doesn't already contain 54 /// an element with equivalent key. 55 /// Returns: `true` if the insertion took place. 56 bool insert(K key, V value) 57 { 58 lazyInitialize(); 59 60 auto kv = KeyValue(key, value); 61 assert(_rbt); 62 return _rbt.insert(kv) != 0; 63 } 64 65 /// Removes an element from the container. 66 /// Returns: `true` if the removal took place. 67 bool remove(K key) 68 { 69 if (!isInitialized) 70 return false; 71 72 auto kv = KeyValue(key, V.init); 73 return _rbt.removeKey(kv) != 0; 74 } 75 76 /// Removes all elements from the map. 77 void clearContents() 78 { 79 if (!isInitialized) 80 return; 81 82 while(_rbt.length > 0) 83 _rbt.removeBack(); 84 } 85 86 /// Returns: A pointer to the value corresponding to this key, or null if not available. 87 /// Live builtin associative arrays. 88 inout(V)* opBinaryRight(string op)(K key) inout if (op == "in") 89 { 90 if (!isInitialized) 91 return null; 92 93 auto kv = KeyValue(key, V.init); 94 auto node = _rbt._find(kv); 95 if (node is null) 96 return null; 97 else 98 return &node.value.value; 99 } 100 101 /// Returns: A reference to the value corresponding to this key. 102 ref inout(V) opIndex(K key) inout 103 { 104 inout(V)* p = key in this; 105 return *p; 106 } 107 108 /// Updates a value associated with a key, creates it if necessary. 109 void opIndexAssign(V value, K key) 110 { 111 // PERF: this could be faster 112 V* p = key in this; 113 if (p is null) 114 insert(key, value); 115 else 116 *p = value; 117 } 118 119 /// Returns: `true` if this key is contained. 120 bool contains(K key) const 121 { 122 if (!isInitialized) 123 return false; 124 auto kv = KeyValue(key, V.init); 125 return (kv in _rbt); 126 } 127 128 /// Returns: Number of elements in the map. 129 size_t length() const 130 { 131 if (!isInitialized) 132 return 0; 133 134 return _rbt.length(); 135 } 136 137 /// Returns: `ttue` is the map has no element. 138 bool empty() const 139 { 140 if (!isInitialized) 141 return true; 142 return _rbt.length() == 0; 143 } 144 145 // Iterate by value only 146 147 /// Fetch a forward range on all values. 148 Range!(MapRangeType.value) byValue() 149 { 150 if (!isInitialized) 151 return Range!(MapRangeType.value).init; 152 153 return Range!(MapRangeType.value)(_rbt[]); 154 } 155 156 /// ditto 157 ConstRange!(MapRangeType.value) byValue() const 158 { 159 if (!isInitialized) 160 return ConstRange!(MapRangeType.value).init; 161 162 return ConstRange!(MapRangeType.value)(_rbt[]); 163 } 164 165 /// ditto 166 ImmutableRange!(MapRangeType.value) byValue() immutable 167 { 168 if (!isInitialized) 169 return ImmutableRange!(MapRangeType.value).init; 170 171 return ImmutableRange!(MapRangeType.value)(_rbt[]); 172 } 173 174 // default opSlice is like byValue for builtin associative arrays 175 alias opSlice = byValue; 176 177 // Iterate by key only 178 179 /// Fetch a forward range on all keys. 180 Range!(MapRangeType.key) byKey() 181 { 182 if (!isInitialized) 183 return Range!(MapRangeType.key).init; 184 185 return Range!(MapRangeType.key)(_rbt[]); 186 } 187 188 /// ditto 189 ConstRange!(MapRangeType.key) byKey() const 190 { 191 if (!isInitialized) 192 return ConstRange!(MapRangeType.key).init; 193 194 return ConstRange!(MapRangeType.key)(_rbt[]); 195 } 196 197 /// ditto 198 ImmutableRange!(MapRangeType.key) byKey() immutable 199 { 200 if (!isInitialized) 201 return ImmutableRange!(MapRangeType.key).init; 202 203 return ImmutableRange!(MapRangeType.key)(_rbt[]); 204 } 205 206 // Iterate by key-value 207 208 /// Fetch a forward range on all keys. 209 Range!(MapRangeType.keyValue) byKeyValue() 210 { 211 if (!isInitialized) 212 return Range!(MapRangeType.keyValue).init; 213 214 return Range!(MapRangeType.keyValue)(_rbt[]); 215 } 216 217 /// ditto 218 ConstRange!(MapRangeType.keyValue) byKeyValue() const 219 { 220 if (!isInitialized) 221 return ConstRange!(MapRangeType.keyValue).init; 222 223 return ConstRange!(MapRangeType.keyValue)(_rbt[]); 224 } 225 226 /// ditto 227 ImmutableRange!(MapRangeType.keyValue) byKeyValue() immutable 228 { 229 if (!isInitialized) 230 return ImmutableRange!(MapRangeType.keyValue).init; 231 232 return ImmutableRange!(MapRangeType.keyValue)(_rbt[]); 233 } 234 235 // Iterate by single value (return a range where all elements have equal key) 236 237 /// Fetch a forward range on all elements with given key. 238 Range!(MapRangeType.value) byGivenKey(K key) 239 { 240 if (!isInitialized) 241 return Range!(MapRangeType.value).init; 242 243 auto kv = KeyValue(key, V.init); 244 return Range!(MapRangeType.value)(_rbt.range(kv)); 245 } 246 247 /// ditto 248 ConstRange!(MapRangeType.value) byGivenKey(K key) const 249 { 250 if (!isInitialized) 251 return ConstRange!(MapRangeType.value).init; 252 253 auto kv = KeyValue(key, V.init); 254 return ConstRange!(MapRangeType.value)(_rbt.range(kv)); 255 } 256 257 /// ditto 258 ImmutableRange!(MapRangeType.value) byGivenKey(K key) immutable 259 { 260 if (!isInitialized) 261 return ImmutableRange!(MapRangeType.value).init; 262 263 auto kv = KeyValue(key, V.init); 264 return ImmutableRange!(MapRangeType.value)(_rbt.range(kv)); 265 } 266 267 268 private: 269 270 alias Range(MapRangeType type) = MapRange!(RBNode!KeyValue*, type); 271 alias ConstRange(MapRangeType type) = MapRange!(const(RBNode!KeyValue)*, type); /// Ditto 272 alias ImmutableRange(MapRangeType type) = MapRange!(immutable(RBNode!KeyValue)*, type); /// Ditto 273 274 alias _less = binaryFun!less; 275 static bool lessForAggregate(const(KeyValue) a, const(KeyValue) b) 276 { 277 return _less(a.key, b.key); 278 } 279 280 alias InternalTree = RedBlackTree!(KeyValue, lessForAggregate, allowDuplicates); 281 282 // we need a composite value to reuse Phobos RedBlackTree 283 static struct KeyValue 284 { 285 nothrow: 286 @nogc: 287 K key; 288 V value; 289 } 290 291 InternalTree _rbt; 292 293 bool isInitialized() const 294 { 295 return _rbt !is null; 296 } 297 298 void lazyInitialize() 299 { 300 if (_rbt is null) 301 { 302 _rbt = mallocNew!InternalTree(); 303 } 304 } 305 } 306 307 unittest 308 { 309 // It should be possible to use most function of an uninitialized Map 310 // All except functions returning a range will work. 311 Map!(int, string) m; 312 313 assert(m.length == 0); 314 assert(m.empty); 315 assert(!m.contains(7)); 316 317 auto range = m.byKey(); 318 assert(range.empty); 319 foreach(e; range) 320 { 321 } 322 323 m[1] = "fun"; 324 } 325 326 unittest 327 { 328 void test(bool removeKeys) nothrow @nogc 329 { 330 { 331 auto test = makeMap!(int, string); 332 int N = 100; 333 foreach(i; 0..N) 334 { 335 int key = (i * 69069) % 65536; 336 test.insert(key, "this is a test"); 337 } 338 foreach(i; 0..N) 339 { 340 int key = (i * 69069) % 65536; 341 assert(test.contains(key)); 342 } 343 344 if (removeKeys) 345 { 346 foreach(i; 0..N) 347 { 348 int key = (i * 69069) % 65536; 349 test.remove(key); 350 } 351 } 352 foreach(i; 0..N) 353 { 354 int key = (i * 69069) % 65536; 355 assert(removeKeys ^ test.contains(key)); // either keys are here or removed 356 } 357 } 358 } 359 test(true); 360 test(false); 361 } 362 363 unittest 364 { 365 Map!(string, int) aa = makeMap!(string, int); // Associative array of ints that are 366 // indexed by string keys. 367 // The KeyType is string. 368 aa["hello"] = 3; // set value associated with key "hello" to 3 369 int value = aa["hello"]; // lookup value from a key 370 assert(value == 3); 371 372 int* p; 373 374 p = ("hello" in aa); 375 if (p !is null) 376 { 377 *p = 4; // update value associated with key 378 assert(aa["hello"] == 4); 379 } 380 381 aa.remove("hello"); 382 } 383 384 /// Creates a new empty `Set`. 385 Set!(K, less) makeSet(K, alias less = "a < b", bool allowDuplicates = false)() 386 { 387 return Set!(K, less, allowDuplicates)(42); 388 } 389 390 391 /// Set, designed to replace std::set usage. 392 /// O(lg(n)) insertion, removal, and search time. 393 /// `Set` is designed to operate even without initialization through `makeSet`. 394 struct Set(K, alias less = "a < b", bool allowDuplicates = false) 395 { 396 public: 397 nothrow: 398 @nogc: 399 400 this(int dummy) 401 { 402 lazyInitialize(); 403 } 404 405 @disable this(this); 406 407 ~this() 408 { 409 if (isInitialized) 410 { 411 destroyFree(_rbt); 412 _rbt = null; 413 } 414 } 415 416 /// Insert an element in the container. 417 /// If allowDuplicates is false, this can fail and return `false` 418 /// if the already contains an element with equivalent key. 419 /// Returns: `true` if the insertion took place. 420 bool insert(K key) 421 { 422 lazyInitialize(); 423 return _rbt.insert(key) != 0; 424 } 425 426 /// Removes an element from the container. 427 /// Returns: `true` if the removal took place. 428 bool remove(K key) 429 { 430 if (!isInitialized) 431 return false; 432 return _rbt.removeKey(key) != 0; 433 } 434 435 /// Removes all elements from the set. 436 void clearContents() 437 { 438 if (!isInitialized) 439 return; 440 while(_rbt.length > 0) 441 _rbt.removeBack(); 442 } 443 444 /// Returns: `true` if the element is present. 445 bool opBinaryRight(string op)(K key) inout if (op == "in") 446 { 447 if (!isInitialized) 448 return false; 449 return key in _rbt; 450 } 451 452 /// Returns: `true` if the element is present. 453 bool opIndex(K key) const 454 { 455 if (!isInitialized) 456 return false; 457 return key in _rbt; 458 } 459 460 /// Returns: `true` if the element is present. 461 bool contains(K key) const 462 { 463 if (!isInitialized) 464 return false; 465 return key in _rbt; 466 } 467 468 /// Fetch a range that spans all the elements in the container. 469 auto opSlice() inout 470 { 471 if (!isInitialized) 472 return nullRange(); 473 return _rbt[]; 474 } 475 476 /// Returns: Number of elements in the set. 477 size_t length() const 478 { 479 if (!isInitialized) 480 return 0; 481 return _rbt.length(); 482 } 483 484 /// Returns: `ttue` is the set has no element. 485 bool empty() const 486 { 487 if (!isInitialized) 488 return true; 489 return _rbt.length() == 0; 490 } 491 492 private: 493 alias InternalTree = RedBlackTree!(K, less, allowDuplicates); 494 InternalTree _rbt; 495 496 bool isInitialized() const 497 { 498 return _rbt !is null; 499 } 500 501 void lazyInitialize() 502 { 503 if (_rbt is null) 504 { 505 _rbt = mallocNew!InternalTree(); 506 } 507 } 508 509 /** 510 * Return a range without any items. 511 */ 512 auto nullRange() 513 { 514 return InternalTree.Range.init; 515 } 516 517 /// Ditto 518 auto nullRange() const 519 { 520 return InternalTree.ConstRange.init; 521 } 522 523 /// Ditto 524 auto nullRange() immutable 525 { 526 return InternalTree.ImmutableRange.init; 527 } 528 } 529 530 unittest 531 { 532 // It should be possible to use most function of an uninitialized Set 533 // All except functions returning a range will work. 534 Set!(string) set; 535 536 assert(set.length == 0); 537 assert(set.empty); 538 set.clearContents(); 539 assert(!set.contains("toto")); 540 541 auto range = set[]; 542 assert(range.empty); 543 foreach(e; range) 544 { 545 } 546 547 // Finally create the internal state 548 set.insert("titi"); 549 assert(set.contains("titi")); 550 } 551 552 553 unittest 554 { 555 { 556 Set!(string) keywords = makeSet!string; 557 558 assert(keywords.insert("public")); 559 assert(keywords.insert("private")); 560 assert(!keywords.insert("private")); 561 562 assert(keywords.remove("public")); 563 assert(!keywords.remove("non-existent")); 564 565 assert(keywords.contains("private")); 566 assert(!keywords.contains("public")); 567 } 568 569 } 570 571 private: 572 573 574 /* 575 * Implementation for a Red Black node for use in a Red Black Tree (see below) 576 * 577 * this implementation assumes we have a marker Node that is the parent of the 578 * root Node. This marker Node is not a valid Node, but marks the end of the 579 * collection. The root is the left child of the marker Node, so it is always 580 * last in the collection. The marker Node is passed in to the setColor 581 * function, and the Node which has this Node as its parent is assumed to be 582 * the root Node. 583 * 584 * A Red Black tree should have O(lg(n)) insertion, removal, and search time. 585 */ 586 struct RBNode(V) 587 { 588 nothrow: 589 @nogc: 590 /* 591 * Convenience alias 592 */ 593 alias Node = RBNode*; 594 595 private Node _left; 596 private Node _right; 597 private Node _parent; 598 599 /** 600 * The value held by this node 601 */ 602 V value; 603 604 /** 605 * Enumeration determining what color the node is. Null nodes are assumed 606 * to be black. 607 */ 608 enum Color : byte 609 { 610 Red, 611 Black 612 } 613 614 /** 615 * The color of the node. 616 */ 617 Color color; 618 619 /** 620 * Get the left child 621 */ 622 @property inout(RBNode)* left() inout 623 { 624 return _left; 625 } 626 627 /** 628 * Get the right child 629 */ 630 @property inout(RBNode)* right() inout 631 { 632 return _right; 633 } 634 635 /** 636 * Get the parent 637 */ 638 @property inout(RBNode)* parent() inout 639 { 640 return _parent; 641 } 642 643 void deallocate() 644 { 645 //import core.stdc.stdio; 646 //printf("deallocate %p\n", &this); 647 destroyFree(&this); 648 } 649 650 /** 651 * Set the left child. Also updates the new child's parent node. This 652 * does not update the previous child. 653 * 654 * Returns newNode 655 */ 656 @property Node left(Node newNode) 657 { 658 _left = newNode; 659 if (newNode !is null) 660 newNode._parent = &this; 661 return newNode; 662 } 663 664 /** 665 * Set the right child. Also updates the new child's parent node. This 666 * does not update the previous child. 667 * 668 * Returns newNode 669 */ 670 @property Node right(Node newNode) 671 { 672 _right = newNode; 673 if (newNode !is null) 674 newNode._parent = &this; 675 return newNode; 676 } 677 678 // assume _left is not null 679 // 680 // performs rotate-right operation, where this is T, _right is R, _left is 681 // L, _parent is P: 682 // 683 // P P 684 // | -> | 685 // T L 686 // / \ / \ 687 // L R a T 688 // / \ / \ 689 // a b b R 690 // 691 /** 692 * Rotate right. This performs the following operations: 693 * - The left child becomes the parent of this node. 694 * - This node becomes the new parent's right child. 695 * - The old right child of the new parent becomes the left child of this 696 * node. 697 */ 698 Node rotateR() 699 in 700 { 701 assert(_left !is null); 702 } 703 body 704 { 705 // sets _left._parent also 706 if (isLeftNode) 707 parent.left = _left; 708 else 709 parent.right = _left; 710 Node tmp = _left._right; 711 712 // sets _parent also 713 _left.right = &this; 714 715 // sets tmp._parent also 716 left = tmp; 717 718 return &this; 719 } 720 721 // assumes _right is non null 722 // 723 // performs rotate-left operation, where this is T, _right is R, _left is 724 // L, _parent is P: 725 // 726 // P P 727 // | -> | 728 // T R 729 // / \ / \ 730 // L R T b 731 // / \ / \ 732 // a b L a 733 // 734 /** 735 * Rotate left. This performs the following operations: 736 * - The right child becomes the parent of this node. 737 * - This node becomes the new parent's left child. 738 * - The old left child of the new parent becomes the right child of this 739 * node. 740 */ 741 Node rotateL() 742 in 743 { 744 assert(_right !is null); 745 } 746 body 747 { 748 // sets _right._parent also 749 if (isLeftNode) 750 parent.left = _right; 751 else 752 parent.right = _right; 753 Node tmp = _right._left; 754 755 // sets _parent also 756 _right.left = &this; 757 758 // sets tmp._parent also 759 right = tmp; 760 return &this; 761 } 762 763 764 /** 765 * Returns true if this node is a left child. 766 * 767 * Note that this should always return a value because the root has a 768 * parent which is the marker node. 769 */ 770 @property bool isLeftNode() const 771 in 772 { 773 assert(_parent !is null); 774 } 775 body 776 { 777 return _parent._left is &this; 778 } 779 780 /** 781 * Set the color of the node after it is inserted. This performs an 782 * update to the whole tree, possibly rotating nodes to keep the Red-Black 783 * properties correct. This is an O(lg(n)) operation, where n is the 784 * number of nodes in the tree. 785 * 786 * end is the marker node, which is the parent of the topmost valid node. 787 */ 788 void setColor(Node end) 789 { 790 // test against the marker node 791 if (_parent !is end) 792 { 793 if (_parent.color == Color.Red) 794 { 795 Node cur = &this; 796 while (true) 797 { 798 // because root is always black, _parent._parent always exists 799 if (cur._parent.isLeftNode) 800 { 801 // parent is left node, y is 'uncle', could be null 802 Node y = cur._parent._parent._right; 803 if (y !is null && y.color == Color.Red) 804 { 805 cur._parent.color = Color.Black; 806 y.color = Color.Black; 807 cur = cur._parent._parent; 808 if (cur._parent is end) 809 { 810 // root node 811 cur.color = Color.Black; 812 break; 813 } 814 else 815 { 816 // not root node 817 cur.color = Color.Red; 818 if (cur._parent.color == Color.Black) 819 // satisfied, exit the loop 820 break; 821 } 822 } 823 else 824 { 825 if (!cur.isLeftNode) 826 cur = cur._parent.rotateL(); 827 cur._parent.color = Color.Black; 828 cur = cur._parent._parent.rotateR(); 829 cur.color = Color.Red; 830 // tree should be satisfied now 831 break; 832 } 833 } 834 else 835 { 836 // parent is right node, y is 'uncle' 837 Node y = cur._parent._parent._left; 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.rotateR(); 862 cur._parent.color = Color.Black; 863 cur = cur._parent._parent.rotateL(); 864 cur.color = Color.Red; 865 // tree should be satisfied now 866 break; 867 } 868 } 869 } 870 871 } 872 } 873 else 874 { 875 // 876 // this is the root node, color it black 877 // 878 color = Color.Black; 879 } 880 } 881 882 /** 883 * Remove this node from the tree. The 'end' node is used as the marker 884 * which is root's parent. Note that this cannot be null! 885 * 886 * Returns the next highest valued node in the tree after this one, or end 887 * if this was the highest-valued node. 888 */ 889 Node remove(Node end) 890 { 891 // 892 // remove this node from the tree, fixing the color if necessary. 893 // 894 Node x; 895 Node ret = next; 896 897 // if this node has 2 children 898 if (_left !is null && _right !is null) 899 { 900 // 901 // normally, we can just swap this node's and y's value, but 902 // because an iterator could be pointing to y and we don't want to 903 // disturb it, we swap this node and y's structure instead. This 904 // can also be a benefit if the value of the tree is a large 905 // struct, which takes a long time to copy. 906 // 907 Node yp, yl, yr; 908 Node y = ret; // y = next 909 yp = y._parent; 910 yl = y._left; 911 yr = y._right; 912 auto yc = y.color; 913 auto isyleft = y.isLeftNode; 914 915 // 916 // replace y's structure with structure of this node. 917 // 918 if (isLeftNode) 919 _parent.left = y; 920 else 921 _parent.right = y; 922 // 923 // need special case so y doesn't point back to itself 924 // 925 y.left = _left; 926 if (_right is y) 927 y.right = &this; 928 else 929 y.right = _right; 930 y.color = color; 931 932 // 933 // replace this node's structure with structure of y. 934 // 935 left = yl; 936 right = yr; 937 if (_parent !is y) 938 { 939 if (isyleft) 940 yp.left = &this; 941 else 942 yp.right = &this; 943 } 944 color = yc; 945 } 946 947 // if this has less than 2 children, remove it 948 if (_left !is null) 949 x = _left; 950 else 951 x = _right; 952 953 bool deferedUnlink = false; 954 if (x is null) 955 { 956 // pretend this is a null node, defer unlinking the node 957 x = &this; 958 deferedUnlink = true; 959 } 960 else if (isLeftNode) 961 _parent.left = x; 962 else 963 _parent.right = x; 964 965 // if the color of this is black, then it needs to be fixed 966 if (color == color.Black) 967 { 968 // need to recolor the tree. 969 while (x._parent !is end && x.color == Node.Color.Black) 970 { 971 if (x.isLeftNode) 972 { 973 // left node 974 Node w = x._parent._right; 975 if (w.color == Node.Color.Red) 976 { 977 w.color = Node.Color.Black; 978 x._parent.color = Node.Color.Red; 979 x._parent.rotateL(); 980 w = x._parent._right; 981 } 982 Node wl = w.left; 983 Node wr = w.right; 984 if ((wl is null || wl.color == Node.Color.Black) && 985 (wr is null || wr.color == Node.Color.Black)) 986 { 987 w.color = Node.Color.Red; 988 x = x._parent; 989 } 990 else 991 { 992 if (wr is null || wr.color == Node.Color.Black) 993 { 994 // wl cannot be null here 995 wl.color = Node.Color.Black; 996 w.color = Node.Color.Red; 997 w.rotateR(); 998 w = x._parent._right; 999 } 1000 1001 w.color = x._parent.color; 1002 x._parent.color = Node.Color.Black; 1003 w._right.color = Node.Color.Black; 1004 x._parent.rotateL(); 1005 x = end.left; // x = root 1006 } 1007 } 1008 else 1009 { 1010 // right node 1011 Node w = x._parent._left; 1012 if (w.color == Node.Color.Red) 1013 { 1014 w.color = Node.Color.Black; 1015 x._parent.color = Node.Color.Red; 1016 x._parent.rotateR(); 1017 w = x._parent._left; 1018 } 1019 Node wl = w.left; 1020 Node wr = w.right; 1021 if ((wl is null || wl.color == Node.Color.Black) && 1022 (wr is null || wr.color == Node.Color.Black)) 1023 { 1024 w.color = Node.Color.Red; 1025 x = x._parent; 1026 } 1027 else 1028 { 1029 if (wl is null || wl.color == Node.Color.Black) 1030 { 1031 // wr cannot be null here 1032 wr.color = Node.Color.Black; 1033 w.color = Node.Color.Red; 1034 w.rotateL(); 1035 w = x._parent._left; 1036 } 1037 1038 w.color = x._parent.color; 1039 x._parent.color = Node.Color.Black; 1040 w._left.color = Node.Color.Black; 1041 x._parent.rotateR(); 1042 x = end.left; // x = root 1043 } 1044 } 1045 } 1046 x.color = Node.Color.Black; 1047 } 1048 1049 if (deferedUnlink) 1050 { 1051 // 1052 // unlink this node from the tree 1053 // 1054 if (isLeftNode) 1055 _parent.left = null; 1056 else 1057 _parent.right = null; 1058 } 1059 1060 // clean references to help GC - Bugzilla 12915 1061 _left = _right = _parent = null; 1062 1063 return ret; 1064 } 1065 1066 /** 1067 * Return the leftmost descendant of this node. 1068 */ 1069 @property inout(RBNode)* leftmost() inout 1070 { 1071 inout(RBNode)* result = &this; 1072 while (result._left !is null) 1073 result = result._left; 1074 return result; 1075 } 1076 1077 /** 1078 * Return the rightmost descendant of this node 1079 */ 1080 @property inout(RBNode)* rightmost() inout 1081 { 1082 inout(RBNode)* result = &this; 1083 while (result._right !is null) 1084 result = result._right; 1085 return result; 1086 } 1087 1088 /** 1089 * Returns the next valued node in the tree. 1090 * 1091 * You should never call this on the marker node, as it is assumed that 1092 * there is a valid next node. 1093 */ 1094 @property inout(RBNode)* next() inout 1095 { 1096 inout(RBNode)* n = &this; 1097 if (n.right is null) 1098 { 1099 while (!n.isLeftNode) 1100 n = n._parent; 1101 return n._parent; 1102 } 1103 else 1104 return n.right.leftmost; 1105 } 1106 1107 /** 1108 * Returns the previous valued node in the tree. 1109 * 1110 * You should never call this on the leftmost node of the tree as it is 1111 * assumed that there is a valid previous node. 1112 */ 1113 @property inout(RBNode)* prev() inout 1114 { 1115 inout(RBNode)* n = &this; 1116 if (n.left is null) 1117 { 1118 while (n.isLeftNode) 1119 n = n._parent; 1120 return n._parent; 1121 } 1122 else 1123 return n.left.rightmost; 1124 } 1125 } 1126 1127 // Range type for RedBlackTree 1128 private struct RBRange(N) 1129 { 1130 nothrow: 1131 @nogc: 1132 alias Node = N; 1133 alias Elem = typeof(Node.value); 1134 1135 private Node _begin = null; 1136 private Node _end = null; 1137 1138 private this(Node b, Node e) 1139 { 1140 _begin = b; 1141 _end = e; 1142 } 1143 1144 /** 1145 * Returns $(D true) if the range is _empty 1146 */ 1147 @property bool empty() const 1148 { 1149 return _begin is _end; 1150 } 1151 1152 /** 1153 * Returns the first element in the range 1154 */ 1155 @property Elem front() 1156 { 1157 return _begin.value; 1158 } 1159 1160 /** 1161 * Returns the last element in the range 1162 */ 1163 @property Elem back() 1164 { 1165 return _end.prev.value; 1166 } 1167 1168 /** 1169 * pop the front element from the range 1170 * 1171 * complexity: amortized $(BIGOH 1) 1172 */ 1173 void popFront() 1174 { 1175 _begin = _begin.next; 1176 } 1177 1178 /** 1179 * pop the back element from the range 1180 * 1181 * complexity: amortized $(BIGOH 1) 1182 */ 1183 void popBack() 1184 { 1185 _end = _end.prev; 1186 } 1187 1188 /** 1189 * Trivial _save implementation, needed for $(D isForwardRange). 1190 */ 1191 @property RBRange save() 1192 { 1193 return this; 1194 } 1195 } 1196 1197 unittest 1198 { 1199 // RBRange.init is supposed to be an empty valid range 1200 RBRange!(RBNode!int*) range; 1201 assert(range.empty); 1202 foreach(e; range) 1203 { 1204 } 1205 } 1206 1207 private enum MapRangeType 1208 { 1209 key, 1210 value, 1211 keyValue 1212 } 1213 1214 // Range type for Dplug's Map, can iterate on keys or values 1215 private struct MapRange(N, MapRangeType type) 1216 { 1217 nothrow: 1218 @nogc: 1219 1220 alias Node = N; 1221 alias InnerRange = RBRange!N; 1222 1223 static if (type == MapRangeType.key) 1224 alias Elem = typeof(Node.value.key); 1225 1226 else static if (type == MapRangeType.value) 1227 alias Elem = typeof(Node.value.value); 1228 1229 else static if (type == MapRangeType.keyValue) 1230 alias Elem = typeof(Node.value); 1231 1232 static Elem get(InnerRange.Elem pair) 1233 { 1234 static if (type == MapRangeType.key) 1235 return pair.key; 1236 1237 else static if (type == MapRangeType.value) 1238 return pair.value; 1239 1240 else static if (type == MapRangeType.keyValue) 1241 return pair; 1242 } 1243 1244 // A Map range is just a wrapper around a RBRange 1245 private InnerRange _inner; 1246 1247 private this(InnerRange inner) 1248 { 1249 _inner = inner; 1250 } 1251 1252 /** 1253 * Returns $(D true) if the range is _empty 1254 */ 1255 @property bool empty() const 1256 { 1257 return _inner.empty; 1258 } 1259 1260 /** 1261 * Returns the first element in the range 1262 */ 1263 @property Elem front() 1264 { 1265 return get(_inner.front); 1266 } 1267 1268 /** 1269 * Returns the last element in the range 1270 */ 1271 @property Elem back() 1272 { 1273 return get(_inner.back()); 1274 } 1275 1276 /** 1277 * pop the front element from the range 1278 * 1279 * complexity: amortized $(BIGOH 1) 1280 */ 1281 void popFront() 1282 { 1283 _inner.popFront(); 1284 } 1285 1286 /** 1287 * pop the back element from the range 1288 * 1289 * complexity: amortized $(BIGOH 1) 1290 */ 1291 void popBack() 1292 { 1293 _inner.popBack(); 1294 } 1295 1296 /** 1297 * Trivial _save implementation, needed for $(D isForwardRange). 1298 */ 1299 @property MapRange save() 1300 { 1301 return this; 1302 } 1303 } 1304 1305 /** 1306 * Implementation of a $(LINK2 https://en.wikipedia.org/wiki/Red%E2%80%93black_tree, 1307 * red-black tree) container. 1308 * 1309 * All inserts, removes, searches, and any function in general has complexity 1310 * of $(BIGOH lg(n)). 1311 * 1312 * To use a different comparison than $(D "a < b"), pass a different operator string 1313 * that can be used by $(REF binaryFun, std,functional), or pass in a 1314 * function, delegate, functor, or any type where $(D less(a, b)) results in a $(D bool) 1315 * value. 1316 * 1317 * Note that less should produce a strict ordering. That is, for two unequal 1318 * elements $(D a) and $(D b), $(D less(a, b) == !less(b, a)). $(D less(a, a)) should 1319 * always equal $(D false). 1320 * 1321 * If $(D allowDuplicates) is set to $(D true), then inserting the same element more than 1322 * once continues to add more elements. If it is $(D false), duplicate elements are 1323 * ignored on insertion. If duplicates are allowed, then new elements are 1324 * inserted after all existing duplicate elements. 1325 */ 1326 1327 final class RedBlackTree(T, alias less = "a < b", bool allowDuplicates = false) 1328 { 1329 nothrow: 1330 @nogc: 1331 /** 1332 * Element type for the tree 1333 */ 1334 alias Elem = T; 1335 1336 alias _less = binaryFun!less; 1337 1338 // used for convenience 1339 private alias RBNode = .RBNode!Elem; 1340 private alias Node = RBNode.Node; 1341 1342 private Node _end; 1343 private Node _begin; 1344 private size_t _length; 1345 1346 private void _setup() 1347 { 1348 assert(!_end); //Make sure that _setup isn't run more than once. 1349 _begin = _end = allocate(); 1350 } 1351 1352 static private Node allocate() 1353 { 1354 Node p = mallocNew!RBNode; 1355 //import core.stdc.stdio; 1356 //printf("allocate %p\n", p); 1357 return p; 1358 } 1359 1360 static private Node allocate(Elem v) 1361 { 1362 auto result = allocate(); 1363 result.value = v; 1364 return result; 1365 } 1366 1367 /** 1368 * The range types for $(D RedBlackTree) 1369 */ 1370 alias Range = RBRange!(RBNode*); 1371 alias ConstRange = RBRange!(const(RBNode)*); /// Ditto 1372 alias ImmutableRange = RBRange!(immutable(RBNode)*); /// Ditto 1373 1374 // find a node based on an element value 1375 private inout(RBNode)* _find(Elem e) inout 1376 { 1377 static if (allowDuplicates) 1378 { 1379 inout(RBNode)* cur = _end.left; 1380 inout(RBNode)* result = null; 1381 while (cur) 1382 { 1383 if (_less(cur.value, e)) 1384 cur = cur.right; 1385 else if (_less(e, cur.value)) 1386 cur = cur.left; 1387 else 1388 { 1389 // want to find the left-most element 1390 result = cur; 1391 cur = cur.left; 1392 } 1393 } 1394 return result; 1395 } 1396 else 1397 { 1398 inout(RBNode)* cur = _end.left; 1399 while (cur) 1400 { 1401 if (_less(cur.value, e)) 1402 cur = cur.right; 1403 else if (_less(e, cur.value)) 1404 cur = cur.left; 1405 else 1406 return cur; 1407 } 1408 return null; 1409 } 1410 } 1411 1412 // add an element to the tree, returns the node added, or the existing node 1413 // if it has already been added and allowDuplicates is false 1414 private auto _add(Elem n) 1415 { 1416 Node result; 1417 static if (!allowDuplicates) 1418 bool added = true; 1419 1420 if (!_end.left) 1421 { 1422 _end.left = _begin = result = allocate(n); 1423 } 1424 else 1425 { 1426 Node newParent = _end.left; 1427 Node nxt; 1428 while (true) 1429 { 1430 if (_less(n, newParent.value)) 1431 { 1432 nxt = newParent.left; 1433 if (nxt is null) 1434 { 1435 // 1436 // add to right of new parent 1437 // 1438 newParent.left = result = allocate(n); 1439 break; 1440 } 1441 } 1442 else 1443 { 1444 static if (!allowDuplicates) 1445 { 1446 if (!(_less(newParent.value, n))) 1447 { 1448 result = newParent; 1449 added = false; 1450 break; 1451 } 1452 } 1453 nxt = newParent.right; 1454 if (nxt is null) 1455 { 1456 // 1457 // add to right of new parent 1458 // 1459 newParent.right = result = allocate(n); 1460 break; 1461 } 1462 } 1463 newParent = nxt; 1464 } 1465 if (_begin.left) 1466 _begin = _begin.left; 1467 } 1468 1469 static if (allowDuplicates) 1470 { 1471 result.setColor(_end); 1472 ++_length; 1473 return result; 1474 } 1475 else 1476 { 1477 import std.typecons : Tuple; 1478 1479 if (added) 1480 { 1481 ++_length; 1482 result.setColor(_end); 1483 } 1484 return Tuple!(bool, "added", Node, "n")(added, result); 1485 } 1486 } 1487 1488 1489 /** 1490 * Check if any elements exist in the container. Returns $(D false) if at least 1491 * one element exists. 1492 */ 1493 @property bool empty() 1494 { 1495 return _end.left is null; 1496 } 1497 1498 /++ 1499 Returns the number of elements in the container. 1500 1501 Complexity: $(BIGOH 1). 1502 +/ 1503 @property size_t length() const 1504 { 1505 return _length; 1506 } 1507 1508 // Find the range for which every element is equal. 1509 private void findEnclosingRange(Elem e, inout(RBNode)** begin, inout(RBNode)** end) inout 1510 { 1511 *begin = _firstGreaterEqual(e); 1512 *end = _firstGreater(e); 1513 } 1514 1515 /** 1516 * Fetch a range that spans all the elements in the container. 1517 * 1518 * Complexity: $(BIGOH 1) 1519 */ 1520 Range opSlice() 1521 { 1522 return Range(_begin, _end); 1523 } 1524 1525 /// Ditto 1526 ConstRange opSlice() const 1527 { 1528 return ConstRange(_begin, _end); 1529 } 1530 1531 /// Ditto 1532 ImmutableRange opSlice() immutable 1533 { 1534 return ImmutableRange(_begin, _end); 1535 } 1536 1537 /** 1538 * Fetch a range that spans all equal elements of a particular value. 1539 * 1540 * Complexity: $(BIGOH 1) 1541 */ 1542 Range range(Elem e) 1543 { 1544 RBNode* begin, end; 1545 findEnclosingRange(e, &begin, &end); 1546 return Range(begin, end); 1547 } 1548 1549 /// Ditto 1550 ConstRange range(Elem e) const 1551 { 1552 const(RBNode)* begin, end; 1553 findEnclosingRange(e, &begin, &end); 1554 return ConstRange(begin, end); 1555 } 1556 1557 /// Ditto 1558 ImmutableRange range(Elem e) immutable 1559 { 1560 immutable(RBNode)* begin, end; 1561 findEnclosingRange(e, &begin, &end); 1562 return ImmutableRange(begin, end); 1563 } 1564 1565 /** 1566 * The front element in the container 1567 * 1568 * Complexity: $(BIGOH 1) 1569 */ 1570 Elem front() 1571 { 1572 return _begin.value; 1573 } 1574 1575 /** 1576 * The last element in the container 1577 * 1578 * Complexity: $(BIGOH log(n)) 1579 */ 1580 Elem back() 1581 { 1582 return _end.prev.value; 1583 } 1584 1585 /++ 1586 $(D in) operator. Check to see if the given element exists in the 1587 container. 1588 1589 Complexity: $(BIGOH log(n)) 1590 +/ 1591 bool opBinaryRight(string op)(Elem e) const if (op == "in") 1592 { 1593 return _find(e) !is null; 1594 } 1595 1596 /** 1597 * Insert a single element in the container. Note that this does not 1598 * invalidate any ranges currently iterating the container. 1599 * 1600 * Returns: The number of elements inserted. 1601 * 1602 * Complexity: $(BIGOH log(n)) 1603 */ 1604 size_t stableInsert(Elem elem) 1605 { 1606 static if (allowDuplicates) 1607 { 1608 _add(elem); 1609 return 1; 1610 } 1611 else 1612 { 1613 return(_add(elem).added ? 1 : 0); 1614 } 1615 } 1616 1617 /// ditto 1618 alias insert = stableInsert; 1619 1620 /** 1621 * Remove an element from the container and return its value. 1622 * 1623 * Complexity: $(BIGOH log(n)) 1624 */ 1625 Elem removeAny() 1626 { 1627 scope(success) 1628 --_length; 1629 auto n = _begin; 1630 auto result = n.value; 1631 _begin = n.remove(_end); 1632 n.deallocate(); 1633 return result; 1634 } 1635 1636 /** 1637 * Remove the front element from the container. 1638 * 1639 * Complexity: $(BIGOH log(n)) 1640 */ 1641 void removeFront() 1642 { 1643 scope(success) 1644 --_length; 1645 auto oldBegin = _begin; 1646 _begin = _begin.remove(_end); 1647 oldBegin.deallocate(); 1648 } 1649 1650 /** 1651 * Remove the back element from the container. 1652 * 1653 * Complexity: $(BIGOH log(n)) 1654 */ 1655 void removeBack() 1656 { 1657 scope(success) 1658 --_length; 1659 auto lastnode = _end.prev; 1660 if (lastnode is _begin) 1661 { 1662 auto oldBegin = _begin; 1663 _begin = _begin.remove(_end); 1664 oldBegin.deallocate(); 1665 } 1666 else 1667 { 1668 lastnode.remove(_end); 1669 lastnode.deallocate(); 1670 } 1671 } 1672 1673 /++ Ditto +/ 1674 size_t removeKey(Elem e) 1675 { 1676 immutable lenBefore = length; 1677 1678 auto beg = _firstGreaterEqual(e); 1679 if (beg is _end || _less(e, beg.value)) 1680 // no values are equal 1681 return 0; 1682 auto oldBeg = beg; 1683 immutable isBegin = (beg is _begin); 1684 beg = beg.remove(_end); 1685 if (isBegin) 1686 _begin = beg; 1687 --_length; 1688 1689 oldBeg.deallocate(); 1690 1691 return lenBefore - length; 1692 } 1693 1694 // find the first node where the value is > e 1695 private inout(RBNode)* _firstGreater(Elem e) inout 1696 { 1697 // can't use _find, because we cannot return null 1698 auto cur = _end.left; 1699 inout(RBNode)* result = _end; 1700 while (cur) 1701 { 1702 if (_less(e, cur.value)) 1703 { 1704 result = cur; 1705 cur = cur.left; 1706 } 1707 else 1708 cur = cur.right; 1709 } 1710 return result; 1711 } 1712 1713 1714 // find the first node where the value is >= e 1715 private inout(RBNode)* _firstGreaterEqual(Elem e) inout 1716 { 1717 // can't use _find, because we cannot return null. 1718 auto cur = _end.left; 1719 inout(RBNode)* result = _end; 1720 while (cur) 1721 { 1722 if (_less(cur.value, e)) 1723 cur = cur.right; 1724 else 1725 { 1726 result = cur; 1727 cur = cur.left; 1728 } 1729 1730 } 1731 return result; 1732 } 1733 1734 /// 1735 this() 1736 { 1737 _setup(); 1738 } 1739 1740 ~this() 1741 { 1742 while(length > 0) 1743 removeBack(); 1744 1745 // deallocate sentinel 1746 _end.deallocate(); 1747 } 1748 }