001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.collections4.list; 018 019import java.util.AbstractList; 020import java.util.Collection; 021import java.util.ConcurrentModificationException; 022import java.util.Iterator; 023import java.util.ListIterator; 024import java.util.NoSuchElementException; 025 026import org.apache.commons.collections4.ArrayStack; 027import org.apache.commons.collections4.OrderedIterator; 028 029/** 030 * A <code>List</code> implementation that is optimised for fast insertions and 031 * removals at any index in the list. 032 * <p> 033 * This list implementation utilises a tree structure internally to ensure that 034 * all insertions and removals are O(log n). This provides much faster performance 035 * than both an <code>ArrayList</code> and a <code>LinkedList</code> where elements 036 * are inserted and removed repeatedly from anywhere in the list. 037 * <p> 038 * The following relative performance statistics are indicative of this class: 039 * <pre> 040 * get add insert iterate remove 041 * TreeList 3 5 1 2 1 042 * ArrayList 1 1 40 1 40 043 * LinkedList 5800 1 350 2 325 044 * </pre> 045 * <code>ArrayList</code> is a good general purpose list implementation. 046 * It is faster than <code>TreeList</code> for most operations except inserting 047 * and removing in the middle of the list. <code>ArrayList</code> also uses less 048 * memory as <code>TreeList</code> uses one object per entry. 049 * <p> 050 * <code>LinkedList</code> is rarely a good choice of implementation. 051 * <code>TreeList</code> is almost always a good replacement for it, although it 052 * does use slightly more memory. 053 * 054 * @since 3.1 055 * @version $Id: TreeList.html 972421 2015-11-14 20:00:04Z tn $ 056 */ 057@SuppressWarnings("deprecation") // replace ArrayStack by ArrayDeque when moving to Java 1.6 058public class TreeList<E> extends AbstractList<E> { 059// add; toArray; iterator; insert; get; indexOf; remove 060// TreeList = 1260;7360;3080; 160; 170;3400; 170; 061// ArrayList = 220;1480;1760; 6870; 50;1540; 7200; 062// LinkedList = 270;7360;3350;55860;290720;2910;55200; 063 064 /** The root node in the AVL tree */ 065 private AVLNode<E> root; 066 067 /** The current size of the list */ 068 private int size; 069 070 //----------------------------------------------------------------------- 071 /** 072 * Constructs a new empty list. 073 */ 074 public TreeList() { 075 super(); 076 } 077 078 /** 079 * Constructs a new empty list that copies the specified collection. 080 * 081 * @param coll the collection to copy 082 * @throws NullPointerException if the collection is null 083 */ 084 public TreeList(final Collection<? extends E> coll) { 085 super(); 086 if (!coll.isEmpty()) { 087 root = new AVLNode<E>(coll); 088 size = coll.size(); 089 } 090 } 091 092 //----------------------------------------------------------------------- 093 /** 094 * Gets the element at the specified index. 095 * 096 * @param index the index to retrieve 097 * @return the element at the specified index 098 */ 099 @Override 100 public E get(final int index) { 101 checkInterval(index, 0, size() - 1); 102 return root.get(index).getValue(); 103 } 104 105 /** 106 * Gets the current size of the list. 107 * 108 * @return the current size 109 */ 110 @Override 111 public int size() { 112 return size; 113 } 114 115 /** 116 * Gets an iterator over the list. 117 * 118 * @return an iterator over the list 119 */ 120 @Override 121 public Iterator<E> iterator() { 122 // override to go 75% faster 123 return listIterator(0); 124 } 125 126 /** 127 * Gets a ListIterator over the list. 128 * 129 * @return the new iterator 130 */ 131 @Override 132 public ListIterator<E> listIterator() { 133 // override to go 75% faster 134 return listIterator(0); 135 } 136 137 /** 138 * Gets a ListIterator over the list. 139 * 140 * @param fromIndex the index to start from 141 * @return the new iterator 142 */ 143 @Override 144 public ListIterator<E> listIterator(final int fromIndex) { 145 // override to go 75% faster 146 // cannot use EmptyIterator as iterator.add() must work 147 checkInterval(fromIndex, 0, size()); 148 return new TreeListIterator<E>(this, fromIndex); 149 } 150 151 /** 152 * Searches for the index of an object in the list. 153 * 154 * @param object the object to search 155 * @return the index of the object, -1 if not found 156 */ 157 @Override 158 public int indexOf(final Object object) { 159 // override to go 75% faster 160 if (root == null) { 161 return -1; 162 } 163 return root.indexOf(object, root.relativePosition); 164 } 165 166 /** 167 * Searches for the presence of an object in the list. 168 * 169 * @param object the object to check 170 * @return true if the object is found 171 */ 172 @Override 173 public boolean contains(final Object object) { 174 return indexOf(object) >= 0; 175 } 176 177 /** 178 * Converts the list into an array. 179 * 180 * @return the list as an array 181 */ 182 @Override 183 public Object[] toArray() { 184 // override to go 20% faster 185 final Object[] array = new Object[size()]; 186 if (root != null) { 187 root.toArray(array, root.relativePosition); 188 } 189 return array; 190 } 191 192 //----------------------------------------------------------------------- 193 /** 194 * Adds a new element to the list. 195 * 196 * @param index the index to add before 197 * @param obj the element to add 198 */ 199 @Override 200 public void add(final int index, final E obj) { 201 modCount++; 202 checkInterval(index, 0, size()); 203 if (root == null) { 204 root = new AVLNode<E>(index, obj, null, null); 205 } else { 206 root = root.insert(index, obj); 207 } 208 size++; 209 } 210 211 /** 212 * Appends all of the elements in the specified collection to the end of this list, 213 * in the order that they are returned by the specified collection's Iterator. 214 * <p> 215 * This method runs in O(n + log m) time, where m is 216 * the size of this list and n is the size of {@code c}. 217 * 218 * @param c the collection to be added to this list 219 * @return {@code true} if this list changed as a result of the call 220 * @throws NullPointerException {@inheritDoc} 221 */ 222 @Override 223 public boolean addAll(final Collection<? extends E> c) { 224 if (c.isEmpty()) { 225 return false; 226 } 227 modCount += c.size(); 228 final AVLNode<E> cTree = new AVLNode<E>(c); 229 root = root == null ? cTree : root.addAll(cTree, size); 230 size += c.size(); 231 return true; 232 } 233 234 /** 235 * Sets the element at the specified index. 236 * 237 * @param index the index to set 238 * @param obj the object to store at the specified index 239 * @return the previous object at that index 240 * @throws IndexOutOfBoundsException if the index is invalid 241 */ 242 @Override 243 public E set(final int index, final E obj) { 244 checkInterval(index, 0, size() - 1); 245 final AVLNode<E> node = root.get(index); 246 final E result = node.value; 247 node.setValue(obj); 248 return result; 249 } 250 251 /** 252 * Removes the element at the specified index. 253 * 254 * @param index the index to remove 255 * @return the previous object at that index 256 */ 257 @Override 258 public E remove(final int index) { 259 modCount++; 260 checkInterval(index, 0, size() - 1); 261 final E result = get(index); 262 root = root.remove(index); 263 size--; 264 return result; 265 } 266 267 /** 268 * Clears the list, removing all entries. 269 */ 270 @Override 271 public void clear() { 272 modCount++; 273 root = null; 274 size = 0; 275 } 276 277 //----------------------------------------------------------------------- 278 /** 279 * Checks whether the index is valid. 280 * 281 * @param index the index to check 282 * @param startIndex the first allowed index 283 * @param endIndex the last allowed index 284 * @throws IndexOutOfBoundsException if the index is invalid 285 */ 286 private void checkInterval(final int index, final int startIndex, final int endIndex) { 287 if (index < startIndex || index > endIndex) { 288 throw new IndexOutOfBoundsException("Invalid index:" + index + ", size=" + size()); 289 } 290 } 291 292 //----------------------------------------------------------------------- 293 /** 294 * Implements an AVLNode which keeps the offset updated. 295 * <p> 296 * This node contains the real work. 297 * TreeList is just there to implement {@link java.util.List}. 298 * The nodes don't know the index of the object they are holding. They 299 * do know however their position relative to their parent node. 300 * This allows to calculate the index of a node while traversing the tree. 301 * <p> 302 * The Faedelung calculation stores a flag for both the left and right child 303 * to indicate if they are a child (false) or a link as in linked list (true). 304 */ 305 static class AVLNode<E> { 306 /** The left child node or the predecessor if {@link #leftIsPrevious}.*/ 307 private AVLNode<E> left; 308 /** Flag indicating that left reference is not a subtree but the predecessor. */ 309 private boolean leftIsPrevious; 310 /** The right child node or the successor if {@link #rightIsNext}. */ 311 private AVLNode<E> right; 312 /** Flag indicating that right reference is not a subtree but the successor. */ 313 private boolean rightIsNext; 314 /** How many levels of left/right are below this one. */ 315 private int height; 316 /** The relative position, root holds absolute position. */ 317 private int relativePosition; 318 /** The stored element. */ 319 private E value; 320 321 /** 322 * Constructs a new node with a relative position. 323 * 324 * @param relativePosition the relative position of the node 325 * @param obj the value for the node 326 * @param rightFollower the node with the value following this one 327 * @param leftFollower the node with the value leading this one 328 */ 329 private AVLNode(final int relativePosition, final E obj, 330 final AVLNode<E> rightFollower, final AVLNode<E> leftFollower) { 331 this.relativePosition = relativePosition; 332 value = obj; 333 rightIsNext = true; 334 leftIsPrevious = true; 335 right = rightFollower; 336 left = leftFollower; 337 } 338 339 /** 340 * Constructs a new AVL tree from a collection. 341 * <p> 342 * The collection must be nonempty. 343 * 344 * @param coll a nonempty collection 345 */ 346 private AVLNode(final Collection<? extends E> coll) { 347 this(coll.iterator(), 0, coll.size() - 1, 0, null, null); 348 } 349 350 /** 351 * Constructs a new AVL tree from a collection. 352 * <p> 353 * This is a recursive helper for {@link #AVLNode(Collection)}. A call 354 * to this method will construct the subtree for elements {@code start} 355 * through {@code end} of the collection, assuming the iterator 356 * {@code e} already points at element {@code start}. 357 * 358 * @param iterator an iterator over the collection, which should already point 359 * to the element at index {@code start} within the collection 360 * @param start the index of the first element in the collection that 361 * should be in this subtree 362 * @param end the index of the last element in the collection that 363 * should be in this subtree 364 * @param absolutePositionOfParent absolute position of this node's 365 * parent, or 0 if this node is the root 366 * @param prev the {@code AVLNode} corresponding to element (start - 1) 367 * of the collection, or null if start is 0 368 * @param next the {@code AVLNode} corresponding to element (end + 1) 369 * of the collection, or null if end is the last element of the collection 370 */ 371 private AVLNode(final Iterator<? extends E> iterator, final int start, final int end, 372 final int absolutePositionOfParent, final AVLNode<E> prev, final AVLNode<E> next) { 373 final int mid = start + (end - start) / 2; 374 if (start < mid) { 375 left = new AVLNode<E>(iterator, start, mid - 1, mid, prev, this); 376 } else { 377 leftIsPrevious = true; 378 left = prev; 379 } 380 value = iterator.next(); 381 relativePosition = mid - absolutePositionOfParent; 382 if (mid < end) { 383 right = new AVLNode<E>(iterator, mid + 1, end, mid, this, next); 384 } else { 385 rightIsNext = true; 386 right = next; 387 } 388 recalcHeight(); 389 } 390 391 /** 392 * Gets the value. 393 * 394 * @return the value of this node 395 */ 396 E getValue() { 397 return value; 398 } 399 400 /** 401 * Sets the value. 402 * 403 * @param obj the value to store 404 */ 405 void setValue(final E obj) { 406 this.value = obj; 407 } 408 409 /** 410 * Locate the element with the given index relative to the 411 * offset of the parent of this node. 412 */ 413 AVLNode<E> get(final int index) { 414 final int indexRelativeToMe = index - relativePosition; 415 416 if (indexRelativeToMe == 0) { 417 return this; 418 } 419 420 final AVLNode<E> nextNode = indexRelativeToMe < 0 ? getLeftSubTree() : getRightSubTree(); 421 if (nextNode == null) { 422 return null; 423 } 424 return nextNode.get(indexRelativeToMe); 425 } 426 427 /** 428 * Locate the index that contains the specified object. 429 */ 430 int indexOf(final Object object, final int index) { 431 if (getLeftSubTree() != null) { 432 final int result = left.indexOf(object, index + left.relativePosition); 433 if (result != -1) { 434 return result; 435 } 436 } 437 if (value == null ? value == object : value.equals(object)) { 438 return index; 439 } 440 if (getRightSubTree() != null) { 441 return right.indexOf(object, index + right.relativePosition); 442 } 443 return -1; 444 } 445 446 /** 447 * Stores the node and its children into the array specified. 448 * 449 * @param array the array to be filled 450 * @param index the index of this node 451 */ 452 void toArray(final Object[] array, final int index) { 453 array[index] = value; 454 if (getLeftSubTree() != null) { 455 left.toArray(array, index + left.relativePosition); 456 } 457 if (getRightSubTree() != null) { 458 right.toArray(array, index + right.relativePosition); 459 } 460 } 461 462 /** 463 * Gets the next node in the list after this one. 464 * 465 * @return the next node 466 */ 467 AVLNode<E> next() { 468 if (rightIsNext || right == null) { 469 return right; 470 } 471 return right.min(); 472 } 473 474 /** 475 * Gets the node in the list before this one. 476 * 477 * @return the previous node 478 */ 479 AVLNode<E> previous() { 480 if (leftIsPrevious || left == null) { 481 return left; 482 } 483 return left.max(); 484 } 485 486 /** 487 * Inserts a node at the position index. 488 * 489 * @param index is the index of the position relative to the position of 490 * the parent node. 491 * @param obj is the object to be stored in the position. 492 */ 493 AVLNode<E> insert(final int index, final E obj) { 494 final int indexRelativeToMe = index - relativePosition; 495 496 if (indexRelativeToMe <= 0) { 497 return insertOnLeft(indexRelativeToMe, obj); 498 } 499 return insertOnRight(indexRelativeToMe, obj); 500 } 501 502 private AVLNode<E> insertOnLeft(final int indexRelativeToMe, final E obj) { 503 if (getLeftSubTree() == null) { 504 setLeft(new AVLNode<E>(-1, obj, this, left), null); 505 } else { 506 setLeft(left.insert(indexRelativeToMe, obj), null); 507 } 508 509 if (relativePosition >= 0) { 510 relativePosition++; 511 } 512 final AVLNode<E> ret = balance(); 513 recalcHeight(); 514 return ret; 515 } 516 517 private AVLNode<E> insertOnRight(final int indexRelativeToMe, final E obj) { 518 if (getRightSubTree() == null) { 519 setRight(new AVLNode<E>(+1, obj, right, this), null); 520 } else { 521 setRight(right.insert(indexRelativeToMe, obj), null); 522 } 523 if (relativePosition < 0) { 524 relativePosition--; 525 } 526 final AVLNode<E> ret = balance(); 527 recalcHeight(); 528 return ret; 529 } 530 531 //----------------------------------------------------------------------- 532 /** 533 * Gets the left node, returning null if its a faedelung. 534 */ 535 private AVLNode<E> getLeftSubTree() { 536 return leftIsPrevious ? null : left; 537 } 538 539 /** 540 * Gets the right node, returning null if its a faedelung. 541 */ 542 private AVLNode<E> getRightSubTree() { 543 return rightIsNext ? null : right; 544 } 545 546 /** 547 * Gets the rightmost child of this node. 548 * 549 * @return the rightmost child (greatest index) 550 */ 551 private AVLNode<E> max() { 552 return getRightSubTree() == null ? this : right.max(); 553 } 554 555 /** 556 * Gets the leftmost child of this node. 557 * 558 * @return the leftmost child (smallest index) 559 */ 560 private AVLNode<E> min() { 561 return getLeftSubTree() == null ? this : left.min(); 562 } 563 564 /** 565 * Removes the node at a given position. 566 * 567 * @param index is the index of the element to be removed relative to the position of 568 * the parent node of the current node. 569 */ 570 AVLNode<E> remove(final int index) { 571 final int indexRelativeToMe = index - relativePosition; 572 573 if (indexRelativeToMe == 0) { 574 return removeSelf(); 575 } 576 if (indexRelativeToMe > 0) { 577 setRight(right.remove(indexRelativeToMe), right.right); 578 if (relativePosition < 0) { 579 relativePosition++; 580 } 581 } else { 582 setLeft(left.remove(indexRelativeToMe), left.left); 583 if (relativePosition > 0) { 584 relativePosition--; 585 } 586 } 587 recalcHeight(); 588 return balance(); 589 } 590 591 private AVLNode<E> removeMax() { 592 if (getRightSubTree() == null) { 593 return removeSelf(); 594 } 595 setRight(right.removeMax(), right.right); 596 if (relativePosition < 0) { 597 relativePosition++; 598 } 599 recalcHeight(); 600 return balance(); 601 } 602 603 private AVLNode<E> removeMin() { 604 if (getLeftSubTree() == null) { 605 return removeSelf(); 606 } 607 setLeft(left.removeMin(), left.left); 608 if (relativePosition > 0) { 609 relativePosition--; 610 } 611 recalcHeight(); 612 return balance(); 613 } 614 615 /** 616 * Removes this node from the tree. 617 * 618 * @return the node that replaces this one in the parent 619 */ 620 private AVLNode<E> removeSelf() { 621 if (getRightSubTree() == null && getLeftSubTree() == null) { 622 return null; 623 } 624 if (getRightSubTree() == null) { 625 if (relativePosition > 0) { 626 left.relativePosition += relativePosition + (relativePosition > 0 ? 0 : 1); 627 } 628 left.max().setRight(null, right); 629 return left; 630 } 631 if (getLeftSubTree() == null) { 632 right.relativePosition += relativePosition - (relativePosition < 0 ? 0 : 1); 633 right.min().setLeft(null, left); 634 return right; 635 } 636 637 if (heightRightMinusLeft() > 0) { 638 // more on the right, so delete from the right 639 final AVLNode<E> rightMin = right.min(); 640 value = rightMin.value; 641 if (leftIsPrevious) { 642 left = rightMin.left; 643 } 644 right = right.removeMin(); 645 if (relativePosition < 0) { 646 relativePosition++; 647 } 648 } else { 649 // more on the left or equal, so delete from the left 650 final AVLNode<E> leftMax = left.max(); 651 value = leftMax.value; 652 if (rightIsNext) { 653 right = leftMax.right; 654 } 655 final AVLNode<E> leftPrevious = left.left; 656 left = left.removeMax(); 657 if (left == null) { 658 // special case where left that was deleted was a double link 659 // only occurs when height difference is equal 660 left = leftPrevious; 661 leftIsPrevious = true; 662 } 663 if (relativePosition > 0) { 664 relativePosition--; 665 } 666 } 667 recalcHeight(); 668 return this; 669 } 670 671 //----------------------------------------------------------------------- 672 /** 673 * Balances according to the AVL algorithm. 674 */ 675 private AVLNode<E> balance() { 676 switch (heightRightMinusLeft()) { 677 case 1 : 678 case 0 : 679 case -1 : 680 return this; 681 case -2 : 682 if (left.heightRightMinusLeft() > 0) { 683 setLeft(left.rotateLeft(), null); 684 } 685 return rotateRight(); 686 case 2 : 687 if (right.heightRightMinusLeft() < 0) { 688 setRight(right.rotateRight(), null); 689 } 690 return rotateLeft(); 691 default : 692 throw new RuntimeException("tree inconsistent!"); 693 } 694 } 695 696 /** 697 * Gets the relative position. 698 */ 699 private int getOffset(final AVLNode<E> node) { 700 if (node == null) { 701 return 0; 702 } 703 return node.relativePosition; 704 } 705 706 /** 707 * Sets the relative position. 708 */ 709 private int setOffset(final AVLNode<E> node, final int newOffest) { 710 if (node == null) { 711 return 0; 712 } 713 final int oldOffset = getOffset(node); 714 node.relativePosition = newOffest; 715 return oldOffset; 716 } 717 718 /** 719 * Sets the height by calculation. 720 */ 721 private void recalcHeight() { 722 height = Math.max( 723 getLeftSubTree() == null ? -1 : getLeftSubTree().height, 724 getRightSubTree() == null ? -1 : getRightSubTree().height) + 1; 725 } 726 727 /** 728 * Returns the height of the node or -1 if the node is null. 729 */ 730 private int getHeight(final AVLNode<E> node) { 731 return node == null ? -1 : node.height; 732 } 733 734 /** 735 * Returns the height difference right - left 736 */ 737 private int heightRightMinusLeft() { 738 return getHeight(getRightSubTree()) - getHeight(getLeftSubTree()); 739 } 740 741 private AVLNode<E> rotateLeft() { 742 final AVLNode<E> newTop = right; // can't be faedelung! 743 final AVLNode<E> movedNode = getRightSubTree().getLeftSubTree(); 744 745 final int newTopPosition = relativePosition + getOffset(newTop); 746 final int myNewPosition = -newTop.relativePosition; 747 final int movedPosition = getOffset(newTop) + getOffset(movedNode); 748 749 setRight(movedNode, newTop); 750 newTop.setLeft(this, null); 751 752 setOffset(newTop, newTopPosition); 753 setOffset(this, myNewPosition); 754 setOffset(movedNode, movedPosition); 755 return newTop; 756 } 757 758 private AVLNode<E> rotateRight() { 759 final AVLNode<E> newTop = left; // can't be faedelung 760 final AVLNode<E> movedNode = getLeftSubTree().getRightSubTree(); 761 762 final int newTopPosition = relativePosition + getOffset(newTop); 763 final int myNewPosition = -newTop.relativePosition; 764 final int movedPosition = getOffset(newTop) + getOffset(movedNode); 765 766 setLeft(movedNode, newTop); 767 newTop.setRight(this, null); 768 769 setOffset(newTop, newTopPosition); 770 setOffset(this, myNewPosition); 771 setOffset(movedNode, movedPosition); 772 return newTop; 773 } 774 775 /** 776 * Sets the left field to the node, or the previous node if that is null 777 * 778 * @param node the new left subtree node 779 * @param previous the previous node in the linked list 780 */ 781 private void setLeft(final AVLNode<E> node, final AVLNode<E> previous) { 782 leftIsPrevious = node == null; 783 left = leftIsPrevious ? previous : node; 784 recalcHeight(); 785 } 786 787 /** 788 * Sets the right field to the node, or the next node if that is null 789 * 790 * @param node the new left subtree node 791 * @param next the next node in the linked list 792 */ 793 private void setRight(final AVLNode<E> node, final AVLNode<E> next) { 794 rightIsNext = node == null; 795 right = rightIsNext ? next : node; 796 recalcHeight(); 797 } 798 799 /** 800 * Appends the elements of another tree list to this tree list by efficiently 801 * merging the two AVL trees. This operation is destructive to both trees and 802 * runs in O(log(m + n)) time. 803 * 804 * @param otherTree 805 * the root of the AVL tree to merge with this one 806 * @param currentSize 807 * the number of elements in this AVL tree 808 * @return the root of the new, merged AVL tree 809 */ 810 private AVLNode<E> addAll(AVLNode<E> otherTree, final int currentSize) { 811 final AVLNode<E> maxNode = max(); 812 final AVLNode<E> otherTreeMin = otherTree.min(); 813 814 // We need to efficiently merge the two AVL trees while keeping them 815 // balanced (or nearly balanced). To do this, we take the shorter 816 // tree and combine it with a similar-height subtree of the taller 817 // tree. There are two symmetric cases: 818 // * this tree is taller, or 819 // * otherTree is taller. 820 if (otherTree.height > height) { 821 // CASE 1: The other tree is taller than this one. We will thus 822 // merge this tree into otherTree. 823 824 // STEP 1: Remove the maximum element from this tree. 825 final AVLNode<E> leftSubTree = removeMax(); 826 827 // STEP 2: Navigate left from the root of otherTree until we 828 // find a subtree, s, that is no taller than me. (While we are 829 // navigating left, we store the nodes we encounter in a stack 830 // so that we can re-balance them in step 4.) 831 final ArrayStack<AVLNode<E>> sAncestors = new ArrayStack<AVLNode<E>>(); 832 AVLNode<E> s = otherTree; 833 int sAbsolutePosition = s.relativePosition + currentSize; 834 int sParentAbsolutePosition = 0; 835 while (s != null && s.height > getHeight(leftSubTree)) { 836 sParentAbsolutePosition = sAbsolutePosition; 837 sAncestors.push(s); 838 s = s.left; 839 if (s != null) { 840 sAbsolutePosition += s.relativePosition; 841 } 842 } 843 844 // STEP 3: Replace s with a newly constructed subtree whose root 845 // is maxNode, whose left subtree is leftSubTree, and whose right 846 // subtree is s. 847 maxNode.setLeft(leftSubTree, null); 848 maxNode.setRight(s, otherTreeMin); 849 if (leftSubTree != null) { 850 leftSubTree.max().setRight(null, maxNode); 851 leftSubTree.relativePosition -= currentSize - 1; 852 } 853 if (s != null) { 854 s.min().setLeft(null, maxNode); 855 s.relativePosition = sAbsolutePosition - currentSize + 1; 856 } 857 maxNode.relativePosition = currentSize - 1 - sParentAbsolutePosition; 858 otherTree.relativePosition += currentSize; 859 860 // STEP 4: Re-balance the tree and recalculate the heights of s's ancestors. 861 s = maxNode; 862 while (!sAncestors.isEmpty()) { 863 final AVLNode<E> sAncestor = sAncestors.pop(); 864 sAncestor.setLeft(s, null); 865 s = sAncestor.balance(); 866 } 867 return s; 868 } else { 869 // CASE 2: This tree is taller. This is symmetric to case 1. 870 // We merge otherTree into this tree by finding a subtree s of this 871 // tree that is of similar height to otherTree and replacing it 872 // with a new subtree whose root is otherTreeMin and whose 873 // children are otherTree and s. 874 875 otherTree = otherTree.removeMin(); 876 877 final ArrayStack<AVLNode<E>> sAncestors = new ArrayStack<AVLNode<E>>(); 878 AVLNode<E> s = this; 879 int sAbsolutePosition = s.relativePosition; 880 int sParentAbsolutePosition = 0; 881 while (s != null && s.height > getHeight(otherTree)) { 882 sParentAbsolutePosition = sAbsolutePosition; 883 sAncestors.push(s); 884 s = s.right; 885 if (s != null) { 886 sAbsolutePosition += s.relativePosition; 887 } 888 } 889 890 otherTreeMin.setRight(otherTree, null); 891 otherTreeMin.setLeft(s, maxNode); 892 if (otherTree != null) { 893 otherTree.min().setLeft(null, otherTreeMin); 894 otherTree.relativePosition++; 895 } 896 if (s != null) { 897 s.max().setRight(null, otherTreeMin); 898 s.relativePosition = sAbsolutePosition - currentSize; 899 } 900 otherTreeMin.relativePosition = currentSize - sParentAbsolutePosition; 901 902 s = otherTreeMin; 903 while (!sAncestors.isEmpty()) { 904 final AVLNode<E> sAncestor = sAncestors.pop(); 905 sAncestor.setRight(s, null); 906 s = sAncestor.balance(); 907 } 908 return s; 909 } 910 } 911 912// private void checkFaedelung() { 913// AVLNode maxNode = left.max(); 914// if (!maxNode.rightIsFaedelung || maxNode.right != this) { 915// throw new RuntimeException(maxNode + " should right-faedel to " + this); 916// } 917// AVLNode minNode = right.min(); 918// if (!minNode.leftIsFaedelung || minNode.left != this) { 919// throw new RuntimeException(maxNode + " should left-faedel to " + this); 920// } 921// } 922// 923// private int checkTreeDepth() { 924// int hright = (getRightSubTree() == null ? -1 : getRightSubTree().checkTreeDepth()); 925// // System.out.print("checkTreeDepth"); 926// // System.out.print(this); 927// // System.out.print(" left: "); 928// // System.out.print(_left); 929// // System.out.print(" right: "); 930// // System.out.println(_right); 931// 932// int hleft = (left == null ? -1 : left.checkTreeDepth()); 933// if (height != Math.max(hright, hleft) + 1) { 934// throw new RuntimeException( 935// "height should be max" + hleft + "," + hright + " but is " + height); 936// } 937// return height; 938// } 939// 940// private int checkLeftSubNode() { 941// if (getLeftSubTree() == null) { 942// return 0; 943// } 944// int count = 1 + left.checkRightSubNode(); 945// if (left.relativePosition != -count) { 946// throw new RuntimeException(); 947// } 948// return count + left.checkLeftSubNode(); 949// } 950// 951// private int checkRightSubNode() { 952// AVLNode right = getRightSubTree(); 953// if (right == null) { 954// return 0; 955// } 956// int count = 1; 957// count += right.checkLeftSubNode(); 958// if (right.relativePosition != count) { 959// throw new RuntimeException(); 960// } 961// return count + right.checkRightSubNode(); 962// } 963 964 /** 965 * Used for debugging. 966 */ 967 @Override 968 public String toString() { 969 return new StringBuilder() 970 .append("AVLNode(") 971 .append(relativePosition) 972 .append(',') 973 .append(left != null) 974 .append(',') 975 .append(value) 976 .append(',') 977 .append(getRightSubTree() != null) 978 .append(", faedelung ") 979 .append(rightIsNext) 980 .append(" )") 981 .toString(); 982 } 983 } 984 985 /** 986 * A list iterator over the linked list. 987 */ 988 static class TreeListIterator<E> implements ListIterator<E>, OrderedIterator<E> { 989 /** The parent list */ 990 private final TreeList<E> parent; 991 /** 992 * Cache of the next node that will be returned by {@link #next()}. 993 */ 994 private AVLNode<E> next; 995 /** 996 * The index of the next node to be returned. 997 */ 998 private int nextIndex; 999 /** 1000 * Cache of the last node that was returned by {@link #next()} 1001 * or {@link #previous()}. 1002 */ 1003 private AVLNode<E> current; 1004 /** 1005 * The index of the last node that was returned. 1006 */ 1007 private int currentIndex; 1008 /** 1009 * The modification count that the list is expected to have. If the list 1010 * doesn't have this count, then a 1011 * {@link java.util.ConcurrentModificationException} may be thrown by 1012 * the operations. 1013 */ 1014 private int expectedModCount; 1015 1016 /** 1017 * Create a ListIterator for a list. 1018 * 1019 * @param parent the parent list 1020 * @param fromIndex the index to start at 1021 */ 1022 protected TreeListIterator(final TreeList<E> parent, final int fromIndex) throws IndexOutOfBoundsException { 1023 super(); 1024 this.parent = parent; 1025 this.expectedModCount = parent.modCount; 1026 this.next = parent.root == null ? null : parent.root.get(fromIndex); 1027 this.nextIndex = fromIndex; 1028 this.currentIndex = -1; 1029 } 1030 1031 /** 1032 * Checks the modification count of the list is the value that this 1033 * object expects. 1034 * 1035 * @throws ConcurrentModificationException If the list's modification 1036 * count isn't the value that was expected. 1037 */ 1038 protected void checkModCount() { 1039 if (parent.modCount != expectedModCount) { 1040 throw new ConcurrentModificationException(); 1041 } 1042 } 1043 1044 public boolean hasNext() { 1045 return nextIndex < parent.size(); 1046 } 1047 1048 public E next() { 1049 checkModCount(); 1050 if (!hasNext()) { 1051 throw new NoSuchElementException("No element at index " + nextIndex + "."); 1052 } 1053 if (next == null) { 1054 next = parent.root.get(nextIndex); 1055 } 1056 final E value = next.getValue(); 1057 current = next; 1058 currentIndex = nextIndex++; 1059 next = next.next(); 1060 return value; 1061 } 1062 1063 public boolean hasPrevious() { 1064 return nextIndex > 0; 1065 } 1066 1067 public E previous() { 1068 checkModCount(); 1069 if (!hasPrevious()) { 1070 throw new NoSuchElementException("Already at start of list."); 1071 } 1072 if (next == null) { 1073 next = parent.root.get(nextIndex - 1); 1074 } else { 1075 next = next.previous(); 1076 } 1077 final E value = next.getValue(); 1078 current = next; 1079 currentIndex = --nextIndex; 1080 return value; 1081 } 1082 1083 public int nextIndex() { 1084 return nextIndex; 1085 } 1086 1087 public int previousIndex() { 1088 return nextIndex() - 1; 1089 } 1090 1091 public void remove() { 1092 checkModCount(); 1093 if (currentIndex == -1) { 1094 throw new IllegalStateException(); 1095 } 1096 parent.remove(currentIndex); 1097 if (nextIndex != currentIndex) { 1098 // remove() following next() 1099 nextIndex--; 1100 } 1101 // the AVL node referenced by next may have become stale after a remove 1102 // reset it now: will be retrieved by next call to next()/previous() via nextIndex 1103 next = null; 1104 current = null; 1105 currentIndex = -1; 1106 expectedModCount++; 1107 } 1108 1109 public void set(final E obj) { 1110 checkModCount(); 1111 if (current == null) { 1112 throw new IllegalStateException(); 1113 } 1114 current.setValue(obj); 1115 } 1116 1117 public void add(final E obj) { 1118 checkModCount(); 1119 parent.add(nextIndex, obj); 1120 current = null; 1121 currentIndex = -1; 1122 nextIndex++; 1123 expectedModCount++; 1124 } 1125 } 1126 1127}