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