1 11 package org.eclipse.jface.viewers.deferred; 12 13 import java.util.Collection ; 14 import java.util.Comparator ; 15 import java.util.Iterator ; 16 17 import org.eclipse.core.runtime.Assert; 18 19 41 public class LazySortedCollection { 42 private final int MIN_CAPACITY = 8; 43 private Object [] contents = new Object [MIN_CAPACITY]; 44 private int[] leftSubTree = new int[MIN_CAPACITY]; 45 private int[] rightSubTree = new int[MIN_CAPACITY]; 46 private int[] nextUnsorted = new int[MIN_CAPACITY]; 47 private int[] treeSize = new int[MIN_CAPACITY]; 48 private int[] parentTree = new int[MIN_CAPACITY]; 49 private int root = -1; 50 private int lastNode = 0; 51 private int firstUnusedNode = -1; 52 53 private static final float loadFactor = 0.75f; 54 55 private IntHashMap objectIndices; 56 private Comparator comparator; 57 private static int counter = 0; 58 59 64 public boolean enableDebug = false; 65 66 private Object lazyRemovalFlag = new Object () { 68 public String toString() { 69 return "Lazy removal flag"; } 71 }; 72 73 private final static int DIR_LEFT = 0; 74 private final static int DIR_RIGHT = 1; 75 private final static int DIR_UNSORTED = 2; 76 77 private final static int DIR_ROOT = 3; 79 private final static int DIR_UNUSED = 4; 80 81 private final class Edge { 82 private int startNode; 83 private int direction; 84 85 private Edge() { 86 startNode = -1; 87 direction = -1; 88 } 89 90 private Edge(int node, int dir) { 91 startNode = node; 92 direction = dir; 93 } 94 95 private int getStart() { 96 return startNode; 97 } 98 99 private int getTarget() { 100 if (startNode == -1) { 101 if (direction == DIR_UNSORTED) { 102 return firstUnusedNode; 103 } else if (direction == DIR_ROOT) { 104 return root; 105 } 106 return -1; 107 } 108 109 if (direction == DIR_LEFT) { 110 return leftSubTree[startNode]; 111 } 112 if (direction == DIR_RIGHT) { 113 return rightSubTree[startNode]; 114 } 115 return nextUnsorted[startNode]; 116 } 117 118 private boolean isNull() { 119 return getTarget() == -1; 120 } 121 122 127 private void setTarget(int newNode) { 128 if (direction == DIR_LEFT) { 129 leftSubTree[startNode] = newNode; 130 } else if (direction == DIR_RIGHT) { 131 rightSubTree[startNode] = newNode; 132 } else if (direction == DIR_UNSORTED) { 133 nextUnsorted[startNode] = newNode; 134 } else if (direction == DIR_ROOT) { 135 root = newNode; 136 } else if (direction == DIR_UNUSED) { 137 firstUnusedNode = newNode; 138 } 139 140 if (newNode != -1) { 141 parentTree[newNode] = startNode; 142 } 143 } 144 145 private void advance(int direction) { 146 startNode = getTarget(); 147 this.direction = direction; 148 } 149 } 150 151 private void setRootNode(int node) { 152 root = node; 153 if (node != -1) { 154 parentTree[node] = -1; 155 } 156 } 157 158 164 public LazySortedCollection(Comparator c) { 165 this.comparator = c; 166 } 167 168 174 public void testInvariants() { 175 if (!enableDebug) { 176 return; 177 } 178 179 testInvariants(root); 180 } 181 182 private void testInvariants(int node) { 183 if (node == -1) { 184 return; 185 } 186 187 int treeSize = getSubtreeSize(node); 191 192 int left = leftSubTree[node]; 193 int right = rightSubTree[node]; 194 int unsorted = nextUnsorted[node]; 195 196 if (isUnsorted(node)) { 197 Assert.isTrue(left == -1, "unsorted nodes shouldn't have a left subtree"); Assert.isTrue(right == -1, "unsorted nodes shouldn't have a right subtree"); } 200 201 if (left != -1) { 202 testInvariants(left); 203 Assert.isTrue(parentTree[left] == node, "left node has invalid parent pointer"); } 205 if (right != -1) { 206 testInvariants(right); 207 Assert.isTrue(parentTree[right] == node, "right node has invalid parent pointer"); } 209 210 int previous = node; 211 while (unsorted != -1) { 212 int oldTreeSize = this.treeSize[unsorted]; 213 recomputeTreeSize(unsorted); 214 215 Assert.isTrue(this.treeSize[unsorted] == oldTreeSize, 216 "Invalid node size for unsorted node"); Assert.isTrue(leftSubTree[unsorted] == -1, "unsorted nodes shouldn't have left subtrees"); Assert.isTrue(rightSubTree[unsorted] == -1, "unsorted nodes shouldn't have right subtrees"); Assert.isTrue(parentTree[unsorted] == previous, "unsorted node has invalid parent pointer"); Assert.isTrue(contents[unsorted] != lazyRemovalFlag, "unsorted nodes should not be lazily removed"); previous = unsorted; 222 unsorted = nextUnsorted[unsorted]; 223 } 224 225 recomputeTreeSize(node); 228 229 Assert.isTrue(treeSize == getSubtreeSize(node), "invalid tree size"); } 231 232 private boolean isUnsorted(int node) { 233 int parent = parentTree[node]; 234 235 if (parent != -1) { 236 return nextUnsorted[parent] == node; 237 } 238 239 return false; 240 } 241 242 private final boolean isLess(int element1, int element2) { 243 return comparator.compare(contents[element1], contents[element2]) < 0; 244 } 245 246 256 private final int addUnsorted(int subTree, int elementToAdd) { 257 if (elementToAdd == -1) { 258 return subTree; 259 } 260 261 if (subTree == -1) { 262 nextUnsorted[elementToAdd] = -1; 263 treeSize[elementToAdd] = 1; 264 return elementToAdd; 265 } 266 267 if (treeSize[subTree] == 0) { 270 removeSubTree(subTree); 271 nextUnsorted[elementToAdd] = -1; 272 treeSize[elementToAdd] = 1; 273 return elementToAdd; 274 } 275 276 if (!enableDebug && leftSubTree[subTree] == -1 && rightSubTree[subTree] == -1 280 && leftSubTree[elementToAdd] == -1 && rightSubTree[elementToAdd] == -1) { 281 counter--; 282 283 if (counter % treeSize[subTree] == 0) { 284 nextUnsorted[elementToAdd] = subTree; 286 parentTree[elementToAdd] = parentTree[subTree]; 287 parentTree[subTree] = elementToAdd; 288 treeSize[elementToAdd] = treeSize[subTree] + 1; 289 return elementToAdd; 290 } 291 } 292 293 int oldNextUnsorted = nextUnsorted[subTree]; 294 nextUnsorted[elementToAdd] = oldNextUnsorted; 295 296 if (oldNextUnsorted == -1) { 297 treeSize[elementToAdd] = 1; 298 } else { 299 treeSize[elementToAdd] = treeSize[oldNextUnsorted] + 1; 300 parentTree[oldNextUnsorted] = elementToAdd; 301 } 302 303 parentTree[elementToAdd] = subTree; 304 305 nextUnsorted[subTree] = elementToAdd; 306 treeSize[subTree]++; 307 return subTree; 308 } 309 310 315 public int size() { 316 int result = getSubtreeSize(root); 317 318 testInvariants(); 319 320 return result; 321 } 322 323 331 private final int partition(int subTree, int toMove) { 332 int result = nextUnsorted[toMove]; 333 334 if (isLess(toMove, subTree)) { 335 int nextLeft = addUnsorted(leftSubTree[subTree], toMove); 336 leftSubTree[subTree] = nextLeft; 337 parentTree[nextLeft] = subTree; 338 } else { 339 int nextRight = addUnsorted(rightSubTree[subTree], toMove); 340 rightSubTree[subTree] = nextRight; 341 parentTree[nextRight] = subTree; 342 } 343 344 return result; 345 } 346 347 358 private final int partition(int subTree, FastProgressReporter mon) throws InterruptedException { 359 if (subTree == -1) { 360 return -1; 361 } 362 363 if (contents[subTree] == lazyRemovalFlag) { 364 subTree = removeNode(subTree); 365 if (subTree == -1) { 366 return -1; 367 } 368 } 369 370 for (int idx = nextUnsorted[subTree]; idx != -1;) { 371 idx = partition(subTree, idx); 372 nextUnsorted[subTree] = idx; 373 if (idx != -1) { 374 parentTree[idx] = subTree; 375 } 376 377 if (mon.isCanceled()) { 378 throw new InterruptedException (); 379 } 380 } 381 382 nextUnsorted[subTree] = -1; 384 385 return subTree; 386 } 387 388 private final int getSubtreeSize(int subTree) { 389 if (subTree == -1) { 390 return 0; 391 } 392 return treeSize[subTree]; 393 } 394 395 403 public final void setCapacity(int newSize) { 404 if (newSize > contents.length) { 405 setArraySize(newSize); 406 } 407 } 408 409 414 private final void setArraySize(int newCapacity) { 415 Object [] newContents = new Object [newCapacity]; 416 System.arraycopy(contents, 0, newContents, 0, lastNode); 417 contents = newContents; 418 419 int[] newLeftSubTree = new int[newCapacity]; 420 System.arraycopy(leftSubTree, 0, newLeftSubTree, 0, lastNode); 421 leftSubTree = newLeftSubTree; 422 423 int[] newRightSubTree = new int[newCapacity]; 424 System.arraycopy(rightSubTree, 0, newRightSubTree, 0, lastNode); 425 rightSubTree = newRightSubTree; 426 427 int[] newNextUnsorted = new int[newCapacity]; 428 System.arraycopy(nextUnsorted, 0, newNextUnsorted, 0, lastNode); 429 nextUnsorted = newNextUnsorted; 430 431 int[] newTreeSize = new int[newCapacity]; 432 System.arraycopy(treeSize, 0, newTreeSize, 0, lastNode); 433 treeSize = newTreeSize; 434 435 int[] newParentTree = new int[newCapacity]; 436 System.arraycopy(parentTree, 0, newParentTree, 0, lastNode); 437 parentTree = newParentTree; 438 } 439 440 448 private final int createNode(Object value) { 449 int result = -1; 450 451 if (firstUnusedNode == -1) { 452 result = lastNode; 455 456 if (contents.length <= lastNode) { 458 setCapacity(lastNode * 2); 459 } 460 461 lastNode++; 462 } else { 463 result = firstUnusedNode; 465 firstUnusedNode = nextUnsorted[result]; 466 } 467 468 contents[result] = value; 469 treeSize[result] = 1; 470 471 leftSubTree[result] = -1; 473 rightSubTree[result] = -1; 474 nextUnsorted[result] = -1; 475 476 if (objectIndices != null) { 480 objectIndices.put(value, result); 481 } 482 483 return result; 484 } 485 486 493 private int getObjectIndex(Object value) { 494 if (objectIndices == null) { 496 int result = -1; 497 498 objectIndices = new IntHashMap((int)(contents.length / loadFactor) + 1, loadFactor); 499 500 for (int i = 0; i < lastNode; i++) { 501 Object element = contents[i]; 502 503 if (element != null && element != lazyRemovalFlag) { 504 objectIndices.put(element, i); 505 506 if (value == element) { 507 result = i; 508 } 509 } 510 } 511 512 return result; 513 } 514 515 return objectIndices.get(value, -1); 518 } 519 520 529 private void replaceNode(int nodeToReplace, int replacementNode) { 530 int parent = parentTree[nodeToReplace]; 531 532 if (parent == -1) { 533 if (root == nodeToReplace) { 534 setRootNode(replacementNode); 535 } 536 } else { 537 if (leftSubTree[parent] == nodeToReplace) { 538 leftSubTree[parent] = replacementNode; 539 } else if (rightSubTree[parent] == nodeToReplace) { 540 rightSubTree[parent] = replacementNode; 541 } else if (nextUnsorted[parent] == nodeToReplace) { 542 nextUnsorted[parent] = replacementNode; 543 } 544 if (replacementNode != -1) { 545 parentTree[replacementNode] = parent; 546 } 547 } 548 } 549 550 private void recomputeAncestorTreeSizes(int node) { 551 while (node != -1) { 552 int oldSize = treeSize[node]; 553 554 recomputeTreeSize(node); 555 556 if (treeSize[node] == oldSize) { 557 break; 558 } 559 560 node = parentTree[node]; 561 } 562 } 563 564 570 private void recomputeTreeSize(int node) { 571 if (node == -1) { 572 return; 573 } 574 treeSize[node] = getSubtreeSize(leftSubTree[node]) 575 + getSubtreeSize(rightSubTree[node]) 576 + getSubtreeSize(nextUnsorted[node]) 577 + (contents[node] == lazyRemovalFlag ? 0 : 1); 578 } 579 580 586 private void forceRecomputeTreeSize(int toRecompute, int whereToStop) { 587 while (toRecompute != -1 && toRecompute != whereToStop) { 588 recomputeTreeSize(toRecompute); 589 590 toRecompute = parentTree[toRecompute]; 591 } 592 } 593 594 599 private void destroyNode(int nodeToDestroy) { 600 if (objectIndices != null) { 603 Object oldContents = contents[nodeToDestroy]; 604 if (oldContents != lazyRemovalFlag) { 605 objectIndices.remove(oldContents); 606 } 607 } 608 609 contents[nodeToDestroy] = null; 610 leftSubTree[nodeToDestroy] = -1; 611 rightSubTree[nodeToDestroy] = -1; 612 613 if (firstUnusedNode == -1) { 614 treeSize[nodeToDestroy] = 1; 615 } else { 616 treeSize[nodeToDestroy] = treeSize[firstUnusedNode] + 1; 617 parentTree[firstUnusedNode] = nodeToDestroy; 618 } 619 620 nextUnsorted[nodeToDestroy] = firstUnusedNode; 621 622 firstUnusedNode = nodeToDestroy; 623 } 624 625 630 private final void pack() { 631 632 if (firstUnusedNode == -1) { 634 return; 635 } 636 637 int reusableNodes = getSubtreeSize(firstUnusedNode); 638 int nonPackableNodes = lastNode - reusableNodes; 639 640 if (contents.length < MIN_CAPACITY || nonPackableNodes > contents.length / 4) { 643 return; 644 } 645 646 objectIndices = null; 651 652 int[] mapNewIdxOntoOld = new int[contents.length]; 654 int[] mapOldIdxOntoNew = new int[contents.length]; 655 656 int nextNewIdx = 0; 657 for (int oldIdx = 0; oldIdx < lastNode; oldIdx++) { 659 if (contents[oldIdx] != null) { 660 mapOldIdxOntoNew[oldIdx] = nextNewIdx; 661 mapNewIdxOntoOld[nextNewIdx] = oldIdx; 662 nextNewIdx++; 663 } else { 664 mapOldIdxOntoNew[oldIdx] = -1; 665 } 666 } 667 668 int newNodes = nextNewIdx; 671 int newCapacity = Math.max(newNodes * 2, MIN_CAPACITY); 672 673 Object [] newContents = new Object [newCapacity]; 675 int[] newTreeSize = new int[newCapacity]; 676 int[] newNextUnsorted = new int[newCapacity]; 677 int[] newLeftSubTree = new int[newCapacity]; 678 int[] newRightSubTree = new int[newCapacity]; 679 int[] newParentTree = new int[newCapacity]; 680 681 for (int newIdx = 0; newIdx < newNodes; newIdx++) { 682 int oldIdx = mapNewIdxOntoOld[newIdx]; 683 newContents[newIdx] = contents[oldIdx]; 684 newTreeSize[newIdx] = treeSize[oldIdx]; 685 686 int left = leftSubTree[oldIdx]; 687 if (left == -1) { 688 newLeftSubTree[newIdx] = -1; 689 } else { 690 newLeftSubTree[newIdx] = mapOldIdxOntoNew[left]; 691 } 692 693 int right = rightSubTree[oldIdx]; 694 if (right == -1) { 695 newRightSubTree[newIdx] = -1; 696 } else { 697 newRightSubTree[newIdx] = mapOldIdxOntoNew[right]; 698 } 699 700 int unsorted = nextUnsorted[oldIdx]; 701 if (unsorted == -1) { 702 newNextUnsorted[newIdx] = -1; 703 } else { 704 newNextUnsorted[newIdx] = mapOldIdxOntoNew[unsorted]; 705 } 706 707 int parent = parentTree[oldIdx]; 708 if (parent == -1) { 709 newParentTree[newIdx] = -1; 710 } else { 711 newParentTree[newIdx] = mapOldIdxOntoNew[parent]; 712 } 713 } 714 715 contents = newContents; 716 nextUnsorted = newNextUnsorted; 717 treeSize = newTreeSize; 718 leftSubTree = newLeftSubTree; 719 rightSubTree = newRightSubTree; 720 parentTree = newParentTree; 721 722 if (root != -1) { 723 root = mapOldIdxOntoNew[root]; 724 } 725 726 firstUnusedNode = -1; 728 lastNode = newNodes; 729 } 730 731 736 public final void add(Object toAdd) { 737 Assert.isNotNull(toAdd); 738 int newIdx = createNode(toAdd); 740 741 setRootNode(addUnsorted(root, newIdx)); 743 744 testInvariants(); 745 } 746 747 752 public final void addAll(Collection toAdd) { 753 Assert.isNotNull(toAdd); 754 Iterator iter = toAdd.iterator(); 755 while (iter.hasNext()) { 756 add(iter.next()); 757 } 758 759 testInvariants(); 760 } 761 762 767 public final void addAll(Object [] toAdd) { 768 Assert.isNotNull(toAdd); 769 for (int i = 0; i < toAdd.length; i++) { 770 Object object = toAdd[i]; 771 772 add(object); 773 } 774 775 testInvariants(); 776 } 777 778 783 public final boolean isEmpty() { 784 boolean result = (root == -1); 785 786 testInvariants(); 787 788 return result; 789 } 790 791 797 public final void remove(Object toRemove) { 798 internalRemove(toRemove); 799 800 pack(); 801 802 testInvariants(); 803 } 804 805 811 private void internalRemove(Object toRemove) { 812 int objectIndex = getObjectIndex(toRemove); 813 814 if (objectIndex != -1) { 815 int parent = parentTree[objectIndex]; 816 lazyRemoveNode(objectIndex); 817 recomputeAncestorTreeSizes(parent); 820 } 821 822 } 824 825 830 public final void removeAll(Object [] toRemove) { 831 Assert.isNotNull(toRemove); 832 833 for (int i = 0; i < toRemove.length; i++) { 834 Object object = toRemove[i]; 835 836 internalRemove(object); 837 } 838 pack(); 839 } 840 841 853 final void retainFirst(int n, FastProgressReporter mon) throws InterruptedException { 854 int sz = size(); 855 856 if (n >= sz) { 857 return; 858 } 859 860 removeRange(n, sz - n, mon); 861 862 testInvariants(); 863 } 864 865 872 public final void retainFirst(int n) { 873 try { 874 retainFirst(n, new FastProgressReporter()); 875 } catch (InterruptedException e) { 876 } 877 878 testInvariants(); 879 } 880 881 889 public final void removeRange(int first, int length) { 890 try { 891 removeRange(first, length, new FastProgressReporter()); 892 } catch (InterruptedException e) { 893 } 894 895 testInvariants(); 896 } 897 898 911 final void removeRange(int first, int length, FastProgressReporter mon) throws InterruptedException { 912 removeRange(root, first, length, mon); 913 914 pack(); 915 916 testInvariants(); 917 } 918 919 private final void removeRange(int node, int rangeStart, int rangeLength, FastProgressReporter mon) throws InterruptedException { 920 if (rangeLength == 0) { 921 return; 922 } 923 924 int size = getSubtreeSize(node); 925 926 if (size <= rangeStart) { 927 return; 928 } 929 930 if (rangeStart == 0 && rangeLength >= size) { 932 removeSubTree(node); 933 return; 934 } 935 try { 936 node = partition(node, mon); 938 939 int left = leftSubTree[node]; 940 int leftSize = getSubtreeSize(left); 941 942 int toRemoveFromLeft = Math.min(leftSize - rangeStart, rangeLength); 943 944 if (toRemoveFromLeft >= 0) { 946 removeRange(leftSubTree[node], rangeStart, toRemoveFromLeft, mon); 947 948 int toRemoveFromRight = rangeStart + rangeLength - leftSize - 1; 950 951 if (toRemoveFromRight >= 0) { 952 removeRange(rightSubTree[node], 0, toRemoveFromRight, mon); 954 955 removeNode(node); 957 return; 958 } 959 } else { 960 removeRange(rightSubTree[node], rangeStart - leftSize - 1, rangeLength, mon); 962 } 963 } finally { 964 recomputeTreeSize(node); 965 } 966 } 967 968 974 private final void removeSubTree(int subTree) { 975 if (subTree == -1) { 976 return; 977 } 978 979 for (int next = nextUnsorted[subTree]; next != -1;) { 981 int current = next; 982 next = nextUnsorted[next]; 983 984 destroyNode(current); 986 } 987 988 removeSubTree(leftSubTree[subTree]); 990 991 removeSubTree(rightSubTree[subTree]); 993 994 replaceNode(subTree, -1); 995 destroyNode(subTree); 997 } 998 999 1007 private final int lazyRemoveNode(int subTree) { 1008 int left = leftSubTree[subTree]; 1009 int right = rightSubTree[subTree]; 1010 1011 if (left == -1 && right == -1) { 1013 int result = nextUnsorted[subTree]; 1014 replaceNode(subTree, result); 1015 destroyNode(subTree); 1016 return result; 1017 } 1018 1019 Object value = contents[subTree]; 1021 contents[subTree] = lazyRemovalFlag; 1022 treeSize[subTree]--; 1023 if (objectIndices != null) { 1024 objectIndices.remove(value); 1025 } 1026 1027 return subTree; 1028 } 1029 1030 1038 private final int removeNode(int subTree) { 1039 int left = leftSubTree[subTree]; 1040 int right = rightSubTree[subTree]; 1041 1042 if (left == -1 || right == -1) { 1043 int result = -1; 1044 1045 if (left == -1 && right == -1) { 1046 result = nextUnsorted[subTree]; 1048 } else { 1049 if (left == -1) { 1051 result = right; 1052 } else { 1053 result = left; 1054 } 1055 1056 try { 1057 result = partition(result, new FastProgressReporter()); 1058 } catch (InterruptedException e) { 1059 1060 } 1061 if (result == -1) { 1062 result = nextUnsorted[subTree]; 1063 } else { 1064 int unsorted = nextUnsorted[subTree]; 1065 nextUnsorted[result] = unsorted; 1066 int additionalNodes = 0; 1067 if (unsorted != -1) { 1068 parentTree[unsorted] = result; 1069 additionalNodes = treeSize[unsorted]; 1070 } 1071 treeSize[result] += additionalNodes; 1072 } 1073 } 1074 1075 replaceNode(subTree, result); 1076 destroyNode(subTree); 1077 return result; 1078 } 1079 1080 Edge nextSmallest = new Edge(subTree, DIR_LEFT); 1083 while (!nextSmallest.isNull()) { 1084 nextSmallest.advance(DIR_RIGHT); 1085 } 1086 1087 Edge nextLargest = new Edge(subTree, DIR_RIGHT); 1088 while (!nextLargest.isNull()) { 1089 nextLargest.advance(DIR_LEFT); 1090 } 1091 1092 int replacementNode = -1; 1094 1095 1097 int leftSize = getSubtreeSize(left); 1098 int rightSize = getSubtreeSize(right); 1099 1100 if (leftSize > rightSize) { 1102 replacementNode = nextSmallest.getStart(); 1103 1104 Edge unsorted = new Edge(replacementNode, DIR_UNSORTED); 1107 while (!unsorted.isNull()) { 1108 int target = unsorted.getTarget(); 1109 1110 if (!isLess(target, replacementNode)) { 1111 unsorted.setTarget(nextUnsorted[target]); 1112 nextLargest.setTarget(addUnsorted(nextLargest.getTarget(), target)); 1113 } else { 1114 unsorted.advance(DIR_UNSORTED); 1115 } 1116 } 1117 1118 forceRecomputeTreeSize(unsorted.getStart(), replacementNode); 1119 forceRecomputeTreeSize(nextLargest.getStart(), subTree); 1120 } else { 1121 replacementNode = nextLargest.getStart(); 1122 1123 Edge unsorted = new Edge(replacementNode, DIR_UNSORTED); 1126 while (!unsorted.isNull()) { 1127 int target = unsorted.getTarget(); 1128 1129 if (isLess(target, replacementNode)) { 1130 unsorted.setTarget(nextUnsorted[target]); 1131 nextSmallest.setTarget(addUnsorted(nextSmallest.getTarget(), target)); 1132 } else { 1133 unsorted.advance(DIR_UNSORTED); 1134 } 1135 } 1136 1137 forceRecomputeTreeSize(unsorted.getStart(), replacementNode); 1138 forceRecomputeTreeSize(nextSmallest.getStart(), subTree); 1139 } 1140 1141 Object replacementContent = contents[replacementNode]; 1144 contents[replacementNode] = contents[subTree]; 1145 contents[subTree] = replacementContent; 1146 1147 if (objectIndices != null) { 1148 objectIndices.put(replacementContent, subTree); 1149 1154 } 1156 1157 int replacementParent = parentTree[replacementNode]; 1158 1159 replaceNode(replacementNode, removeNode(replacementNode)); 1160 1163 forceRecomputeTreeSize(replacementParent, subTree); 1164 recomputeTreeSize(subTree); 1165 1166 1168 return subTree; 1169 } 1170 1171 1174 public final void clear() { 1175 lastNode = 0; 1176 setArraySize(MIN_CAPACITY); 1177 root = -1; 1178 firstUnusedNode = -1; 1179 objectIndices = null; 1180 1181 testInvariants(); 1182 } 1183 1184 1189 public Comparator getComparator() { 1190 return comparator; 1191 } 1192 1193 1208 final int getFirst(Object [] result, boolean sorted, FastProgressReporter mon) throws InterruptedException { 1209 int returnValue = getRange(result, 0, sorted, mon); 1210 1211 testInvariants(); 1212 1213 return returnValue; 1214 } 1215 1216 1227 public final int getFirst(Object [] result, boolean sorted) { 1228 int returnValue = 0; 1229 1230 try { 1231 returnValue = getFirst(result, sorted, new FastProgressReporter()); 1232 } catch (InterruptedException e) { 1233 } 1234 1235 testInvariants(); 1236 1237 return returnValue; 1238 } 1239 1240 1257 final int getRange(Object [] result, int rangeStart, boolean sorted, FastProgressReporter mon) throws InterruptedException { 1258 return getRange(result, 0, rangeStart, root, sorted, mon); 1259 } 1260 1261 1274 public final int getRange(Object [] result, int rangeStart, boolean sorted) { 1275 int returnValue = 0; 1276 1277 try { 1278 returnValue = getRange(result, rangeStart, sorted, new FastProgressReporter()); 1279 } catch (InterruptedException e) { 1280 } 1281 1282 testInvariants(); 1283 1284 return returnValue; 1285 } 1286 1287 1293 public final Object getItem(int index) { 1294 Object [] result = new Object [1]; 1295 try { 1296 getRange(result, index, false, new FastProgressReporter()); 1297 } catch (InterruptedException e) { 1298 } 1300 Object returnValue = result[0]; 1301 1302 testInvariants(); 1303 1304 return returnValue; 1305 } 1306 1307 1315 public final Object [] getItems(boolean sorted) { 1316 Object [] result = new Object [size()]; 1317 1318 getRange(result, 0, sorted); 1319 1320 return result; 1321 } 1322 1323 private final int getRange(Object [] result, int resultIdx, int rangeStart, int node, boolean sorted, FastProgressReporter mon) throws InterruptedException { 1324 if (node == -1) { 1325 return 0; 1326 } 1327 1328 int availableSpace = result.length - resultIdx; 1329 1330 if (rangeStart == 0) { 1332 if (treeSize[node] <= availableSpace) { 1333 return getChildren(result, resultIdx, node, sorted, mon); 1334 } 1335 } 1336 1337 node = partition(node, mon); 1338 if (node == -1) { 1339 return 0; 1340 } 1341 1342 int inserted = 0; 1343 1344 int numberLessThanNode = getSubtreeSize(leftSubTree[node]); 1345 1346 if (rangeStart < numberLessThanNode) { 1347 if (inserted < availableSpace) { 1348 inserted += getRange(result, resultIdx, rangeStart, leftSubTree[node], sorted, mon); 1349 } 1350 } 1351 1352 if (rangeStart <= numberLessThanNode) { 1353 if (inserted < availableSpace) { 1354 result[resultIdx + inserted] = contents[node]; 1355 inserted++; 1356 } 1357 } 1358 1359 if (inserted < availableSpace) { 1360 inserted += getRange(result, resultIdx + inserted, 1361 Math.max(rangeStart - numberLessThanNode - 1, 0), rightSubTree[node], sorted, mon); 1362 } 1363 1364 return inserted; 1365 } 1366 1367 1376 private final int getChildren(Object [] result, int resultIdx, int node, boolean sorted, FastProgressReporter mon) throws InterruptedException { 1377 if (node == -1) { 1378 return 0; 1379 } 1380 1381 int tempIdx = resultIdx; 1382 1383 if (sorted) { 1384 node = partition(node, mon); 1385 if (node == -1) { 1386 return 0; 1387 } 1388 } 1389 1390 if (tempIdx < result.length) { 1392 tempIdx += getChildren(result, tempIdx, leftSubTree[node], sorted, mon); 1393 } 1394 1395 if (tempIdx < result.length) { 1397 Object value = contents[node]; 1398 if (value != lazyRemovalFlag) { 1399 result[tempIdx++] = value; 1400 } 1401 } 1402 1403 if (tempIdx < result.length) { 1405 tempIdx += getChildren(result, tempIdx, rightSubTree[node], sorted, mon); 1406 } 1407 1408 for (int unsortedNode = nextUnsorted[node]; unsortedNode != -1 && tempIdx < result.length; 1410 unsortedNode = nextUnsorted[unsortedNode]) { 1411 1412 result[tempIdx++] = contents[unsortedNode]; 1413 } 1414 1415 return tempIdx - resultIdx; 1416 } 1417 1418 1424 public boolean contains(Object item) { 1425 Assert.isNotNull(item); 1426 boolean returnValue = (getObjectIndex(item) != -1); 1427 1428 testInvariants(); 1429 1430 return returnValue; 1431 } 1432} 1433 | Popular Tags |