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}