1 /******************************************************************************* 2 3 Based upon Doug Lea's Java collection package 4 5 Copyright: 6 Copyright (c) 2008 Kris Bell. 7 Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH. 8 All rights reserved. 9 10 License: 11 Tango Dual License: 3-Clause BSD License / Academic Free License v3.0. 12 See LICENSE_TANGO.txt for details. 13 14 Version: Apr 2008: Initial release 15 16 Authors: Kris, tsalm 17 18 *******************************************************************************/ 19 20 module ocean.util.container.RedBlack; 21 22 import ocean.meta.types.Qualifiers; 23 import ocean.meta.types.Typedef; 24 25 import ocean.util.container.model.IContainer; 26 27 private 28 { 29 mixin(Typedef!(int, "AttributeDummy")); 30 } 31 32 /******************************************************************************* 33 34 RedBlack implements basic capabilities of Red-Black trees, 35 an efficient kind of balanced binary tree. The particular 36 algorithms used are adaptations of those in Corman, 37 Lieserson, and Rivest's <EM>Introduction to Algorithms</EM>. 38 This class was inspired by (and code cross-checked with) a 39 similar class by Chuck McManis. The implementations of 40 rebalancings during insertion and deletion are 41 a little trickier than those versions since they 42 don't swap Cell contents or use special dummy nilnodes. 43 44 Doug Lea 45 46 *******************************************************************************/ 47 48 struct RedBlack (V, A = AttributeDummy) 49 { 50 import ocean.core.Verify; 51 52 alias RedBlack!(V, A) Type; 53 alias Type *Ref; 54 55 enum : bool {RED = false, BLACK = true} 56 57 /** 58 * Pointer to left child 59 **/ 60 61 package Ref left; 62 63 /** 64 * Pointer to right child 65 **/ 66 67 package Ref right; 68 69 /** 70 * Pointer to parent (null if root) 71 **/ 72 73 package Ref parent; 74 75 package V value; 76 77 static if (!is(typeof(A) == AttributeDummy)) 78 { 79 A attribute; 80 } 81 82 /** 83 * The node color (RED, BLACK) 84 **/ 85 86 package bool color; 87 88 static if (!is(typeof(A) == AttributeDummy)) 89 { 90 final Ref set (V v, A a) 91 { 92 attribute = a; 93 return set (v); 94 } 95 } 96 97 /** 98 * Make a new Cell with given value, null links, and BLACK color. 99 * Normally only called to establish a new root. 100 **/ 101 102 final Ref set (V v) 103 { 104 value = v; 105 left = null; 106 right = null; 107 parent = null; 108 color = BLACK; 109 return &this; 110 } 111 112 /** 113 * Return a new Ref with same value and color as self, 114 * but with null links. (Since it is never OK to have 115 * multiple identical links in a RB tree.) 116 **/ 117 118 protected Ref dup (scope Ref delegate() alloc) 119 { 120 static if (is(typeof(A) == AttributeDummy)) 121 auto t = alloc().set (value); 122 else 123 auto t = alloc().set (value, attribute); 124 125 t.color = color; 126 return t; 127 } 128 129 130 /** 131 * See_Also: ocean.util.collection.model.View.View.checkImplementation. 132 **/ 133 public void checkImplementation () 134 { 135 136 // It's too hard to check the property that every simple 137 // path from node to leaf has same number of black nodes. 138 // So restrict to the following 139 140 verify(parent is null || 141 &this is parent.left || 142 &this is parent.right); 143 144 verify(left is null || 145 &this is left.parent); 146 147 verify(right is null || 148 &this is right.parent); 149 150 verify(color is BLACK || 151 (colorOf(left) is BLACK) && (colorOf(right) is BLACK)); 152 153 if (left !is null) 154 left.checkImplementation(); 155 if (right !is null) 156 right.checkImplementation(); 157 } 158 159 /** 160 * Return the minimum value of the current (sub)tree 161 **/ 162 163 Ref leftmost () 164 { 165 auto p = &this; 166 for ( ; p.left; p = p.left) {} 167 return p; 168 } 169 170 /** 171 * Return the maximum value of the current (sub)tree 172 **/ 173 Ref rightmost () 174 { 175 auto p = &this; 176 for ( ; p.right; p = p.right) {} 177 return p; 178 } 179 180 /** 181 * Return the root (parentless node) of the tree 182 **/ 183 Ref root () 184 { 185 auto p = &this; 186 for ( ; p.parent; p = p.parent) {} 187 return p; 188 } 189 190 /** 191 * Return true if node is a root (i.e., has a null parent) 192 **/ 193 194 bool isRoot () 195 { 196 return parent is null; 197 } 198 199 200 /** 201 * Return the inorder successor, or null if no such 202 **/ 203 204 Ref successor () 205 { 206 if (right) 207 return right.leftmost; 208 209 auto p = parent; 210 auto ch = &this; 211 while (p && ch is p.right) 212 { 213 ch = p; 214 p = p.parent; 215 } 216 return p; 217 } 218 219 /** 220 * Return the inorder predecessor, or null if no such 221 **/ 222 223 Ref predecessor () 224 { 225 if (left) 226 return left.rightmost; 227 228 auto p = parent; 229 auto ch = &this; 230 while (p && ch is p.left) 231 { 232 ch = p; 233 p = p.parent; 234 } 235 return p; 236 } 237 238 /** 239 * Return the number of nodes in the subtree 240 **/ 241 int size () 242 { 243 auto c = 1; 244 if (left) 245 c += left.size; 246 if (right) 247 c += right.size; 248 return c; 249 } 250 251 252 /** 253 * Return node of current subtree containing value as value(), 254 * if it exists, else null. 255 * Uses Comparator cmp to find and to check equality. 256 **/ 257 258 Ref find (V value, Compare!(V) cmp) 259 { 260 auto t = &this; 261 for (;;) 262 { 263 auto diff = cmp (value, t.value); 264 if (diff is 0) 265 return t; 266 else 267 if (diff < 0) 268 t = t.left; 269 else 270 t = t.right; 271 if (t is null) 272 break; 273 } 274 return null; 275 } 276 277 278 /** 279 * Return node of subtree matching "value" 280 * or, if none found, the one just after or before 281 * if it doesn't exist, return null 282 * Uses Comparator cmp to find and to check equality. 283 **/ 284 Ref findFirst (V value, Compare!(V) cmp, bool after = true) 285 { 286 auto t = &this; 287 auto tLower = &this; 288 auto tGreater = &this; 289 290 for (;;) 291 { 292 auto diff = cmp (value, t.value); 293 if (diff is 0) 294 return t; 295 else 296 if (diff < 0) 297 { 298 tGreater = t; 299 t = t.left; 300 } 301 else 302 { 303 tLower = t; 304 t = t.right; 305 } 306 if (t is null) 307 break; 308 } 309 310 if (after) 311 { 312 if (cmp (value, tGreater.value) <= 0) 313 if (cmp (value, tGreater.value) < 0) 314 return tGreater; 315 } 316 else 317 { 318 if (cmp (value, tLower.value) >= 0) 319 if (cmp (value, tLower.value) > 0) 320 return tLower; 321 } 322 323 return null; 324 } 325 326 /** 327 * Return number of nodes of current subtree containing value. 328 * Uses Comparator cmp to find and to check equality. 329 **/ 330 int count (V value, Compare!(V) cmp) 331 { 332 auto c = 0; 333 auto t = &this; 334 while (t) 335 { 336 int diff = cmp (value, t.value); 337 if (diff is 0) 338 { 339 ++c; 340 if (t.left is null) 341 t = t.right; 342 else 343 if (t.right is null) 344 t = t.left; 345 else 346 { 347 c += t.right.count (value, cmp); 348 t = t.left; 349 } 350 } 351 else 352 if (diff < 0) 353 t = t.left; 354 else 355 t = t.right; 356 } 357 return c; 358 } 359 360 static if (!is(typeof(A) == AttributeDummy)) 361 { 362 Ref findAttribute (A attribute, Compare!(A) cmp) 363 { 364 auto t = &this; 365 366 while (t) 367 { 368 if (t.attribute == attribute) 369 return t; 370 else 371 if (t.right is null) 372 t = t.left; 373 else 374 if (t.left is null) 375 t = t.right; 376 else 377 { 378 auto p = t.left.findAttribute (attribute, cmp); 379 380 if (p !is null) 381 return p; 382 else 383 t = t.right; 384 } 385 } 386 return null; // not reached 387 } 388 389 int countAttribute (A attrib, Compare!(A) cmp) 390 { 391 int c = 0; 392 auto t = &this; 393 394 while (t) 395 { 396 if (t.attribute == attribute) 397 ++c; 398 399 if (t.right is null) 400 t = t.left; 401 else 402 if (t.left is null) 403 t = t.right; 404 else 405 { 406 c += t.left.countAttribute (attribute, cmp); 407 t = t.right; 408 } 409 } 410 return c; 411 } 412 413 /** 414 * find and return a cell holding (key, element), or null if no such 415 **/ 416 Ref find (V value, A attribute, Compare!(V) cmp) 417 { 418 auto t = &this; 419 420 for (;;) 421 { 422 int diff = cmp (value, t.value); 423 if (diff is 0 && t.attribute == attribute) 424 return t; 425 else 426 if (diff <= 0) 427 t = t.left; 428 else 429 t = t.right; 430 431 if (t is null) 432 break; 433 } 434 return null; 435 } 436 437 } 438 439 440 441 /** 442 * Return a new subtree containing each value of current subtree 443 **/ 444 445 Ref copyTree (scope Ref delegate() alloc) 446 { 447 auto t = dup (alloc); 448 449 if (left) 450 { 451 t.left = left.copyTree (alloc); 452 t.left.parent = t; 453 } 454 455 if (right) 456 { 457 t.right = right.copyTree (alloc); 458 t.right.parent = t; 459 } 460 461 return t; 462 } 463 464 465 /** 466 * There's no generic value insertion. Instead find the 467 * place you want to add a node and then invoke insertLeft 468 * or insertRight. 469 * <P> 470 * Insert Cell as the left child of current node, and then 471 * rebalance the tree it is in. 472 * @param Cell the Cell to add 473 * @param root, the root of the current tree 474 * Returns: the new root of the current tree. (Rebalancing 475 * can change the root!) 476 **/ 477 478 479 Ref insertLeft (Ref cell, Ref root) 480 { 481 left = cell; 482 cell.parent = &this; 483 return cell.fixAfterInsertion (root); 484 } 485 486 /** 487 * Insert Cell as the right child of current node, and then 488 * rebalance the tree it is in. 489 * @param Cell the Cell to add 490 * @param root, the root of the current tree 491 * Returns: the new root of the current tree. (Rebalancing 492 * can change the root!) 493 **/ 494 495 Ref insertRight (Ref cell, Ref root) 496 { 497 right = cell; 498 cell.parent = &this; 499 return cell.fixAfterInsertion (root); 500 } 501 502 503 /** 504 * Delete the current node, and then rebalance the tree it is in 505 * @param root the root of the current tree 506 * Returns: the new root of the current tree. (Rebalancing 507 * can change the root!) 508 **/ 509 510 511 Ref remove (Ref root) 512 { 513 // handle case where we are only node 514 if (left is null && right is null && parent is null) 515 return null; 516 517 // if strictly internal, swap places with a successor 518 if (left && right) 519 { 520 auto s = successor; 521 522 // To work nicely with arbitrary subclasses of Ref, we don't want to 523 // just copy successor's fields. since we don't know what 524 // they are. Instead we swap positions _in the tree. 525 root = swapPosition(&this, s, root); 526 } 527 528 // Start fixup at replacement node (normally a child). 529 // But if no children, fake it by using self 530 531 if (left is null && right is null) 532 { 533 if (color is BLACK) 534 root = this.fixAfterDeletion (root); 535 536 // Unlink (Couldn't before since fixAfterDeletion needs parent ptr) 537 if (parent) 538 { 539 if (&this is parent.left) 540 parent.left = null; 541 else 542 if (&this is parent.right) 543 parent.right = null; 544 parent = null; 545 } 546 } 547 else 548 { 549 auto replacement = left; 550 if (replacement is null) 551 replacement = right; 552 553 // link replacement to parent 554 replacement.parent = parent; 555 556 if (parent is null) 557 root = replacement; 558 else 559 if (&this is parent.left) 560 parent.left = replacement; 561 else 562 parent.right = replacement; 563 564 left = null; 565 right = null; 566 parent = null; 567 568 // fix replacement 569 if (color is BLACK) 570 root = replacement.fixAfterDeletion (root); 571 } 572 return root; 573 } 574 575 /** 576 * Swap the linkages of two nodes in a tree. 577 * Return new root, in case it changed. 578 **/ 579 580 static Ref swapPosition (Ref x, Ref y, Ref root) 581 { 582 /* Too messy. TODO: find sequence of assigments that are always OK */ 583 584 auto px = x.parent; 585 bool xpl = px !is null && x is px.left; 586 auto lx = x.left; 587 auto rx = x.right; 588 589 auto py = y.parent; 590 bool ypl = py !is null && y is py.left; 591 auto ly = y.left; 592 auto ry = y.right; 593 594 if (x is py) 595 { 596 y.parent = px; 597 if (px !is null) 598 { 599 if (xpl) 600 px.left = y; 601 else 602 px.right = y; 603 } 604 605 x.parent = y; 606 if (ypl) 607 { 608 y.left = x; 609 y.right = rx; 610 if (rx !is null) 611 rx.parent = y; 612 } 613 else 614 { 615 y.right = x; 616 y.left = lx; 617 if (lx !is null) 618 lx.parent = y; 619 } 620 621 x.left = ly; 622 if (ly !is null) 623 ly.parent = x; 624 625 x.right = ry; 626 if (ry !is null) 627 ry.parent = x; 628 } 629 else 630 if (y is px) 631 { 632 x.parent = py; 633 if (py !is null) 634 { 635 if (ypl) 636 py.left = x; 637 else 638 py.right = x; 639 } 640 641 y.parent = x; 642 if (xpl) 643 { 644 x.left = y; 645 x.right = ry; 646 if (ry !is null) 647 ry.parent = x; 648 } 649 else 650 { 651 x.right = y; 652 x.left = ly; 653 if (ly !is null) 654 ly.parent = x; 655 } 656 657 y.left = lx; 658 if (lx !is null) 659 lx.parent = y; 660 661 y.right = rx; 662 if (rx !is null) 663 rx.parent = y; 664 } 665 else 666 { 667 x.parent = py; 668 if (py !is null) 669 { 670 if (ypl) 671 py.left = x; 672 else 673 py.right = x; 674 } 675 676 x.left = ly; 677 if (ly !is null) 678 ly.parent = x; 679 680 x.right = ry; 681 if (ry !is null) 682 ry.parent = x; 683 684 y.parent = px; 685 if (px !is null) 686 { 687 if (xpl) 688 px.left = y; 689 else 690 px.right = y; 691 } 692 693 y.left = lx; 694 if (lx !is null) 695 lx.parent = y; 696 697 y.right = rx; 698 if (rx !is null) 699 rx.parent = y; 700 } 701 702 bool c = x.color; 703 x.color = y.color; 704 y.color = c; 705 706 if (root is x) 707 root = y; 708 else 709 if (root is y) 710 root = x; 711 return root; 712 } 713 714 715 716 /** 717 * Return color of node p, or BLACK if p is null 718 * (In the CLR version, they use 719 * a special dummy `nil' node for such purposes, but that doesn't 720 * work well here, since it could lead to creating one such special 721 * node per real node.) 722 * 723 **/ 724 725 static bool colorOf (Ref p) 726 { 727 return (p is null) ? BLACK : p.color; 728 } 729 730 /** 731 * return parent of node p, or null if p is null 732 **/ 733 static Ref parentOf (Ref p) 734 { 735 return (p is null) ? null : p.parent; 736 } 737 738 /** 739 * Set the color of node p, or do nothing if p is null 740 **/ 741 742 static void setColor (Ref p, bool c) 743 { 744 if (p !is null) 745 p.color = c; 746 } 747 748 /** 749 * return left child of node p, or null if p is null 750 **/ 751 752 static Ref leftOf (Ref p) 753 { 754 return (p is null) ? null : p.left; 755 } 756 757 /** 758 * return right child of node p, or null if p is null 759 **/ 760 761 static Ref rightOf (Ref p) 762 { 763 return (p is null) ? null : p.right; 764 } 765 766 767 /** From CLR **/ 768 package Ref rotateLeft (Ref root) 769 { 770 auto r = right; 771 right = r.left; 772 773 if (r.left) 774 r.left.parent = &this; 775 776 r.parent = parent; 777 if (parent is null) 778 root = r; 779 else 780 if (parent.left is &this) 781 parent.left = r; 782 else 783 parent.right = r; 784 785 r.left = &this; 786 parent = r; 787 return root; 788 } 789 790 /** From CLR **/ 791 package Ref rotateRight (Ref root) 792 { 793 auto l = left; 794 left = l.right; 795 796 if (l.right !is null) 797 l.right.parent = &this; 798 799 l.parent = parent; 800 if (parent is null) 801 root = l; 802 else 803 if (parent.right is &this) 804 parent.right = l; 805 else 806 parent.left = l; 807 808 l.right = &this; 809 parent = l; 810 return root; 811 } 812 813 814 /** From CLR **/ 815 package Ref fixAfterInsertion (Ref root) 816 { 817 color = RED; 818 auto x = &this; 819 820 while (x && x !is root && x.parent.color is RED) 821 { 822 if (parentOf(x) is leftOf(parentOf(parentOf(x)))) 823 { 824 auto y = rightOf(parentOf(parentOf(x))); 825 if (colorOf(y) is RED) 826 { 827 setColor(parentOf(x), BLACK); 828 setColor(y, BLACK); 829 setColor(parentOf(parentOf(x)), RED); 830 x = parentOf(parentOf(x)); 831 } 832 else 833 { 834 if (x is rightOf(parentOf(x))) 835 { 836 x = parentOf(x); 837 root = x.rotateLeft(root); 838 } 839 840 setColor(parentOf(x), BLACK); 841 setColor(parentOf(parentOf(x)), RED); 842 if (parentOf(parentOf(x)) !is null) 843 root = parentOf(parentOf(x)).rotateRight(root); 844 } 845 } 846 else 847 { 848 auto y = leftOf(parentOf(parentOf(x))); 849 if (colorOf(y) is RED) 850 { 851 setColor(parentOf(x), BLACK); 852 setColor(y, BLACK); 853 setColor(parentOf(parentOf(x)), RED); 854 x = parentOf(parentOf(x)); 855 } 856 else 857 { 858 if (x is leftOf(parentOf(x))) 859 { 860 x = parentOf(x); 861 root = x.rotateRight(root); 862 } 863 864 setColor(parentOf(x), BLACK); 865 setColor(parentOf(parentOf(x)), RED); 866 if (parentOf(parentOf(x)) !is null) 867 root = parentOf(parentOf(x)).rotateLeft(root); 868 } 869 } 870 } 871 root.color = BLACK; 872 return root; 873 } 874 875 876 877 /** From CLR **/ 878 package Ref fixAfterDeletion(Ref root) 879 { 880 auto x = &this; 881 while (x !is root && colorOf(x) is BLACK) 882 { 883 if (x is leftOf(parentOf(x))) 884 { 885 auto sib = rightOf(parentOf(x)); 886 if (colorOf(sib) is RED) 887 { 888 setColor(sib, BLACK); 889 setColor(parentOf(x), RED); 890 root = parentOf(x).rotateLeft(root); 891 sib = rightOf(parentOf(x)); 892 } 893 if (colorOf(leftOf(sib)) is BLACK && colorOf(rightOf(sib)) is BLACK) 894 { 895 setColor(sib, RED); 896 x = parentOf(x); 897 } 898 else 899 { 900 if (colorOf(rightOf(sib)) is BLACK) 901 { 902 setColor(leftOf(sib), BLACK); 903 setColor(sib, RED); 904 root = sib.rotateRight(root); 905 sib = rightOf(parentOf(x)); 906 } 907 908 setColor(sib, colorOf(parentOf(x))); 909 setColor(parentOf(x), BLACK); 910 setColor(rightOf(sib), BLACK); 911 root = parentOf(x).rotateLeft(root); 912 x = root; 913 } 914 } 915 else 916 { 917 auto sib = leftOf(parentOf(x)); 918 if (colorOf(sib) is RED) 919 { 920 setColor(sib, BLACK); 921 setColor(parentOf(x), RED); 922 root = parentOf(x).rotateRight(root); 923 sib = leftOf(parentOf(x)); 924 } 925 926 if (colorOf(rightOf(sib)) is BLACK && colorOf(leftOf(sib)) is BLACK) 927 { 928 setColor(sib, RED); 929 x = parentOf(x); 930 } 931 else 932 { 933 if (colorOf(leftOf(sib)) is BLACK) 934 { 935 setColor(rightOf(sib), BLACK); 936 setColor(sib, RED); 937 root = sib.rotateLeft(root); 938 sib = leftOf(parentOf(x)); 939 } 940 941 setColor(sib, colorOf(parentOf(x))); 942 setColor(parentOf(x), BLACK); 943 setColor(leftOf(sib), BLACK); 944 root = parentOf(x).rotateRight(root); 945 x = root; 946 } 947 } 948 } 949 950 setColor(x, BLACK); 951 return root; 952 } 953 }