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