scolebourne 2004/05/12 16:24:45
Modified: collections/src/test/org/apache/commons/collections/list
TestTreeList.java
collections/src/java/org/apache/commons/collections/list
TreeList.java
Log:
Improve implementation of TreeList to perform better, fix bugs
bug 26680, 28930
Revision Changes Path
1.2 +4 -5
jakarta-commons/collections/src/test/org/apache/commons/collections/list/TestTreeList.java
Index: TestTreeList.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/collections/src/test/org/apache/commons/collections/list/TestTreeList.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- TestTreeList.java 10 May 2004 19:59:03 -0000 1.1
+++ TestTreeList.java 12 May 2004 23:24:44 -0000 1.2
@@ -37,15 +37,14 @@
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
-// System.out.println(" add; insert; get; indexOf; remove");
+// System.out.println(" add; toArray; iterator; insert; get;
indexOf; remove");
// System.out.print(" TreeList = ");
// benchmark(new TreeList());
// System.out.print("\n ArrayList = ");
// benchmark(new java.util.ArrayList());
// System.out.print("\n LinkedList = ");
-// benchmark(new NodeCachingLinkedList());
-
// benchmark(new java.util.LinkedList());
+// benchmark(new NodeCachingLinkedList());
}
public static Test suite() {
@@ -83,7 +82,7 @@
System.out.print(System.currentTimeMillis() - start + ";");
start = System.currentTimeMillis();
- for (int i = 0; i < 10000; i++) {
+ for (int i = 0; i < 50000; i++) {
int j = (int) (Math.random() * 110000);
l.get(j);
}
1.2 +471 -299
jakarta-commons/collections/src/java/org/apache/commons/collections/list/TreeList.java
Index: TreeList.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/list/TreeList.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- TreeList.java 10 May 2004 19:59:03 -0000 1.1
+++ TreeList.java 12 May 2004 23:24:45 -0000 1.2
@@ -17,6 +17,12 @@
import java.util.AbstractList;
import java.util.Collection;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+import org.apache.commons.collections.OrderedIterator;
/**
* A <code>List</code> implementation that is optimised for fast insertions and
@@ -27,21 +33,21 @@
* than both an <code>ArrayList</code> and a <code>LinkedList</code> where elements
* are inserted and removed repeatedly from anywhere in the list.
* <p>
- * The trade-off versus <code>ArrayList</code> is memory usage.
<code>TreeList</code>
- * stores each entry in an object which uses up more memory. Also,
<code>ArrayList</code>
- * is faster if additions and removals only occur at the end of the list, not in
the middle.
- * <p>
- * The trade-off versus <code>LinkedList</code> is based on how you use the list.
- * If additions and removals only occur at the start or end of the list, not in the
- * middle then <code>LinkedList</code> is faster.
- * <p>
- * The following performance statistics are indicative of this class:
+ * The following relative performance statistics are indicative of this class:
* <pre>
- * add insert get
- * TreeList 300 501 110
- * ArrayList 70 20390 20
- * LinkedList 50 226636 279742
+ * get add insert iterate remove
+ * TreeList 3 5 1 2 1
+ * ArrayList 1 1 40 1 40
+ * LinkedList 5800 1 350 2 325
* </pre>
+ * <code>ArrayList</code> is a good general purpose list implementation.
+ * It is faster than <code>TreeList</code> for most operations except inserting
+ * and removing in the middle of the list. <code>ArrayList</code> also uses less
+ * memory as <code>TreeList</code> uses one object per entry.
+ * <p>
+ * <code>LinkedList</code> is rarely a good choice of implementation.
+ * <code>TreeList</code> is almost always a good replacement for it, although it
+ * does use sligtly more memory.
*
* @since Commons Collections 3.1
* @version $Revision$ $Date$
@@ -50,10 +56,10 @@
* @author Stephen Colebourne
*/
public class TreeList extends AbstractList {
-// Add; insert; get
-// tree = 980;170;50;
-// array = 280;6920;0;
-// linked = 380;55480;55800;
+// add; toArray; iterator; insert; get; indexOf; remove
+// TreeList = 1260;7360;3080; 160; 170;3400; 170;
+// ArrayList = 220;1480;1760; 6870; 50;1540; 7200;
+// LinkedList = 270;7360;3350;55860;290720;2910;55200;
/** The root node in the AVL tree */
private AVLNode root;
@@ -106,13 +112,33 @@
*
* @return an iterator over the list
*/
-// public Iterator iterator() {
-// // override to go 65% faster
-// if (size() == 0) {
-// return IteratorUtils.EMPTY_ITERATOR;
-// }
-// return new TreeIterator(this);
-// }
+ public Iterator iterator() {
+ // override to go 75% faster
+ return listIterator(0);
+ }
+
+ /**
+ * Gets a ListIterator over the list.
+ *
+ * @return the new iterator
+ */
+ public ListIterator listIterator() {
+ // override to go 75% faster
+ return listIterator(0);
+ }
+
+ /**
+ * Gets a ListIterator over the list.
+ *
+ * @param fromIndex the index to start from
+ * @return the new iterator
+ */
+ public ListIterator listIterator(int fromIndex) {
+ // override to go 75% faster
+ // cannot use IteratorUtils.EMPTY_ITERATOR as iterator.add() must work
+ checkInterval(fromIndex, 0, size());
+ return new TreeListIterator(this, fromIndex);
+ }
/**
* Searches for the index of an object in the list.
@@ -142,7 +168,7 @@
* @return the list as an array
*/
public Object[] toArray() {
- // override to go 40% faster
+ // override to go 20% faster
Object[] array = new Object[size()];
if (root != null) {
root.toArray(array, root.relativePosition);
@@ -158,9 +184,10 @@
* @param obj the element to add
*/
public void add(int index, Object obj) {
+ modCount++;
checkInterval(index, 0, size());
if (root == null) {
- root = new AVLNode(index, obj);
+ root = new AVLNode(index, obj, null, null);
} else {
root = root.insert(index, obj);
}
@@ -190,6 +217,7 @@
* @return the previous object at that index
*/
public Object remove(int index) {
+ modCount++;
checkInterval(index, 0, size() - 1);
Object result = get(index);
root = root.remove(index);
@@ -201,6 +229,7 @@
* Clears the list, removing all entries.
*/
public void clear() {
+ modCount++;
root = null;
size = 0;
}
@@ -226,29 +255,44 @@
* <p>
* This node contains the real work.
* TreeList is just there to implement [EMAIL PROTECTED] java.util.List}.
+ * The nodes don't know the index of the object they are holding. They
+ * do know however their position relative to their parent node.
+ * This allows to calculate the index of a node while traversing the tree.
+ * <p>
+ * The Faedelung calculation stores a flag for both the left and right child
+ * to indicate if they are a child (false) or a link as in linked list (true).
*/
static class AVLNode {
- /** The left child node */
+ /** The left child node or the predecessor if [EMAIL PROTECTED]
#leftIsPrevious}.*/
private AVLNode left;
- /** The right child node */
+ /** Flag indicating that left reference is not a subtree but the
predecessor. */
+ private boolean leftIsPrevious;
+ /** The right child node or the successor if [EMAIL PROTECTED]
#rightIsNext}. */
private AVLNode right;
- /** How many levels of left/right are below this one */
+ /** Flag indicating that right reference is not a subtree but the
successor. */
+ private boolean rightIsNext;
+ /** How many levels of left/right are below this one. */
private int height;
- /** The relative position, root holds absolute position */
+ /** The relative position, root holds absolute position. */
private int relativePosition;
- /** The stored element */
+ /** The stored element. */
private Object value;
/**
* Constructs a new node with a relative position.
*
* @param relativePosition the relative position of the node
- * @param obj the element
+ * @param obj the value for the ndoe
+ * @param rightFollower the node with the value following this one
+ * @param leftFollower the node with the value leading this one
*/
- public AVLNode(int relativePosition, Object obj) {
- super();
+ private AVLNode(int relativePosition, Object obj, AVLNode rightFollower,
AVLNode leftFollower) {
this.relativePosition = relativePosition;
- this.value = obj;
+ value = obj;
+ rightIsNext = true;
+ leftIsPrevious = true;
+ right = rightFollower;
+ left = leftFollower;
}
/**
@@ -280,9 +324,9 @@
return this;
}
- AVLNode nextNode = ((indexRelativeToMe < 0) ? left : right);
+ AVLNode nextNode = ((indexRelativeToMe < 0) ? getLeftSubTree() :
getRightSubTree());
if (nextNode == null) {
- int i = 1;
+ return null;
}
return nextNode.get(indexRelativeToMe);
}
@@ -291,7 +335,7 @@
* Locate the index that contains the specified object.
*/
int indexOf(Object object, int index) {
- if (left != null) {
+ if (getLeftSubTree() != null) {
int result = left.indexOf(object, index + left.relativePosition);
if (result != -1) {
return result;
@@ -300,7 +344,7 @@
if (value == null ? value == object : value.equals(object)) {
return index;
}
- if (right != null) {
+ if (getRightSubTree() != null) {
return right.indexOf(object, index + right.relativePosition);
}
return -1;
@@ -308,64 +352,50 @@
/**
* Stores the node and its children into the array specified.
+ *
+ * @param array the array to be filled
+ * @param index the index of this node
*/
void toArray(Object[] array, int index) {
array[index] = value;
- if (left != null) {
+ if (getLeftSubTree() != null) {
left.toArray(array, index + left.relativePosition);
}
- if (right != null) {
+ if (getRightSubTree() != null) {
right.toArray(array, index + right.relativePosition);
}
}
- //-----------------------------------------------------------------------
/**
- * Balances according to the AVL algorithm.
+ * Gets the next node in the list after this one.
+ *
+ * @return the next node
*/
- private AVLNode balance() {
- switch (heightRightMinusLeft()) {
- case 1 :
- case 0 :
- case -1 :
- return this;
- case -2 :
- if (left.heightRightMinusLeft() > 0) {
- setLeft(left.rotateLeft());
- }
- return rotateRight();
- case 2 :
- if (right.heightRightMinusLeft() < 0) {
- setRight(right.rotateRight());
- }
- return rotateLeft();
- default :
- throw new RuntimeException("tree inconsistent!");
+ AVLNode next() {
+ if (rightIsNext || right == null) {
+ return right;
}
+ return right.min();
}
/**
- * Returns the height of the node or -1 if the node is null.
+ * Gets the node in the list before this one.
*
- * Convenience method.
- */
- private int getHeight(AVLNode n) {
- return (n == null ? -1 : n.height);
- }
-
- /**
- * Returns the height difference
+ * @return the previous node
*/
- private int heightRightMinusLeft() {
- return getHeight(right) - getHeight(left);
+ AVLNode previous() {
+ if (leftIsPrevious || left == null) {
+ return left;
+ }
+ return left.max();
}
/**
- * Inserts a node at the position index.
+ * Inserts a node at the position index.
*
- * @param index is the index of the position relative to the position of
- * the parent node.
- * @param obj is the object to be stored in the position.
+ * @param index is the index of the position relative to the position of
+ * the parent node.
+ * @param obj is the object to be stored in the position.
*/
AVLNode insert(int index, Object obj) {
int indexRelativeToMe = index - relativePosition;
@@ -380,12 +410,12 @@
private AVLNode insertOnLeft(int indexRelativeToMe, Object obj) {
AVLNode ret = this;
- if (left == null) {
- left = new AVLNode(-1, obj);
+ if (getLeftSubTree() == null) {
+ setLeft(new AVLNode(-1, obj, this, left), null);
} else {
- left = left.insert(indexRelativeToMe, obj);
-
+ setLeft(left.insert(indexRelativeToMe, obj), null);
}
+
if (relativePosition >= 0) {
relativePosition++;
}
@@ -397,11 +427,10 @@
private AVLNode insertOnRight(int indexRelativeToMe, Object obj) {
AVLNode ret = this;
- if (right == null) {
- right = new AVLNode(+1, obj);
+ if (getRightSubTree() == null) {
+ setRight(new AVLNode(+1, obj, right, this), null);
} else {
- right = right.insert(indexRelativeToMe, obj);
-
+ setRight(right.insert(indexRelativeToMe, obj), null);
}
if (relativePosition < 0) {
relativePosition--;
@@ -411,77 +440,44 @@
return ret;
}
- private void recalcHeight() {
- height = Math.max(left == null ? -1 : left.height, right == null ? -1 :
right.height) + 1;
- }
-
- private AVLNode rotateLeft() {
- AVLNode newTop = right;
- AVLNode movedNode = right.left;
-
- int newTopPosition = relativePosition + getOffset(right);
- int myNewPosition = -right.relativePosition;
- int movedPosition = getOffset(right) + getOffset(movedNode);
-
- setRight(right.left);
- newTop.setLeft(this);
-
- setOffset(newTop, newTopPosition);
- setOffset(this, myNewPosition);
- setOffset(movedNode, movedPosition);
- return newTop;
- }
-
- private int getOffset(AVLNode node) {
- if (node == null) {
- return 0;
- }
- return node.relativePosition;
- }
-
- private AVLNode rotateRight() {
- AVLNode newTop = left;
- AVLNode movedNode = left.right;
-
- int newTopPosition = relativePosition + getOffset(left);
- int myNewPosition = -left.relativePosition;
- int movedPosition = getOffset(left) + getOffset(movedNode);
-
- setLeft(left.right);
- newTop.setRight(this);
-
- setOffset(newTop, newTopPosition);
- setOffset(this, myNewPosition);
- setOffset(movedNode, movedPosition);
- return newTop;
-
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the left node, returning null if its a faedelung.
+ */
+ private AVLNode getLeftSubTree() {
+ return (leftIsPrevious ? null : left);
}
- private void setLeft(AVLNode node) {
- left = node;
- recalcHeight();
+ /**
+ * Gets the right node, returning null if its a faedelung.
+ */
+ private AVLNode getRightSubTree() {
+ return (rightIsNext ? null : right);
}
- private int setOffset(AVLNode node, int newOffest) {
- if (node == null) {
- return 0;
- }
- int oldOffset = getOffset(node);
- node.relativePosition = newOffest;
- return oldOffset;
+ /**
+ * Gets the rightmost child of this node.
+ *
+ * @return the rightmost child (greatest index)
+ */
+ private AVLNode max() {
+ return (getRightSubTree() == null) ? this : right.max();
}
- private void setRight(AVLNode node) {
- right = node;
- recalcHeight();
+ /**
+ * Gets the leftmost child of this node.
+ *
+ * @return the leftmost child (smallest index)
+ */
+ private AVLNode min() {
+ return (getLeftSubTree() == null) ? this : left.min();
}
/**
* Removes the node at a given position.
*
- * @param index is the index of the element to be removed relative to
- * the position of the parent node of the current node.
- * @return the new root of the tree
+ * @param index is the index of the element to be removed relative to the
position of
+ * the parent node of the current node.
*/
AVLNode remove(int index) {
int indexRelativeToMe = index - relativePosition;
@@ -490,12 +486,12 @@
return removeSelf();
}
if (indexRelativeToMe > 0) {
- right = right.remove(indexRelativeToMe);
+ setRight(right.remove(indexRelativeToMe), right.right);
if (relativePosition < 0) {
relativePosition++;
}
} else {
- left = left.remove(indexRelativeToMe);
+ setLeft(left.remove(indexRelativeToMe), left.left);
if (relativePosition > 0) {
relativePosition--;
}
@@ -504,28 +500,62 @@
return balance();
}
+ private AVLNode removeMax() {
+ if (getRightSubTree() == null) {
+ return removeSelf();
+ }
+ setRight(right.removeMax(), right.right);
+ if (relativePosition < 0) {
+ relativePosition++;
+ }
+ recalcHeight();
+ return balance();
+ }
+
+ private AVLNode removeMin() {
+ if (getLeftSubTree() == null) {
+ return removeSelf();
+ }
+ setLeft(left.removeMin(), left.left);
+ if (relativePosition > 0) {
+ relativePosition--;
+ }
+ recalcHeight();
+ return balance();
+ }
+
private AVLNode removeSelf() {
- if (right == null && left == null)
+ if (getRightSubTree() == null && getLeftSubTree() == null)
return null;
- if (right == null) {
+ if (getRightSubTree() == null) {
if (relativePosition > 0) {
left.relativePosition += relativePosition + (relativePosition >
0 ? 0 : 1);
}
+ left.max().setRight(null, right);
return left;
}
- if (left == null) {
+ if (getLeftSubTree() == null) {
right.relativePosition += relativePosition - (relativePosition < 0
? 0 : 1);
+ right.min().setLeft(null, left);
return right;
}
if (heightRightMinusLeft() > 0) {
- value = right.min().value;
+ AVLNode rightMin = right.min();
+ value = rightMin.value;
+ if (leftIsPrevious) {
+ left = rightMin.left;
+ }
right = right.removeMin();
if (relativePosition < 0) {
relativePosition++;
}
} else {
- value = left.max().value;
+ AVLNode leftMax = left.max();
+ value = leftMax.value;
+ if (rightIsNext) {
+ right = leftMax.right;
+ }
left = left.removeMax();
if (relativePosition > 0) {
relativePosition--;
@@ -535,179 +565,321 @@
return this;
}
- private AVLNode removeMin() {
- if (left == null) {
- return removeSelf();
+ //-----------------------------------------------------------------------
+ /**
+ * Balances according to the AVL algorithm.
+ */
+ private AVLNode balance() {
+ switch (heightRightMinusLeft()) {
+ case 1 :
+ case 0 :
+ case -1 :
+ return this;
+ case -2 :
+ if (left.heightRightMinusLeft() > 0) {
+ setLeft(left.rotateLeft(), null);
+ }
+ return rotateRight();
+ case 2 :
+ if (right.heightRightMinusLeft() < 0) {
+ setRight(right.rotateRight(), null);
+ }
+ return rotateLeft();
+ default :
+ throw new RuntimeException("tree inconsistent!");
}
- left = left.removeMin();
- adjustOffsetForRemovalLeft();
- recalcHeight();
- return balance();
}
- private void adjustOffsetForRemovalLeft() {
- if (relativePosition > 0) {
- relativePosition--;
+ /**
+ * Gets the relative position.
+ */
+ private int getOffset(AVLNode node) {
+ if (node == null) {
+ return 0;
}
+ return node.relativePosition;
}
- private void adjustOffsetForRemovalRight() {
- if (relativePosition < 0) {
- relativePosition++;
+ /**
+ * Sets the relative position.
+ */
+ private int setOffset(AVLNode node, int newOffest) {
+ if (node == null) {
+ return 0;
}
+ int oldOffset = getOffset(node);
+ node.relativePosition = newOffest;
+ return oldOffset;
}
- private AVLNode min() {
- return (left == null) ? this : left.min();
- }
-
- private AVLNode removeMax() {
- if (right == null) {
- return removeSelf();
- }
- right = right.removeMax();
- adjustOffsetForRemovalRight();
- recalcHeight();
- return balance();
+ /**
+ * Sets the height by calculation.
+ */
+ private void recalcHeight() {
+ height = Math.max(
+ getLeftSubTree() == null ? -1 : getLeftSubTree().height,
+ getRightSubTree() == null ? -1 : getRightSubTree().height) + 1;
}
- private AVLNode max() {
- return (right == null) ? this : right.max();
+ /**
+ * Returns the height of the node or -1 if the node is null.
+ */
+ private int getHeight(AVLNode node) {
+ return (node == null ? -1 : node.height);
}
/**
- * Used for debugging.
+ * Returns the height difference right - left
*/
- public String toString() {
- return "AVLNode(" + relativePosition + "," + (left != null) + "," +
value + "," + (right != null) + ")";
+ private int heightRightMinusLeft() {
+ return getHeight(getRightSubTree()) - getHeight(getLeftSubTree());
}
- }
+ private AVLNode rotateLeft() {
+ AVLNode newTop = right; // can't be faedelung!
+ AVLNode movedNode = getRightSubTree().getLeftSubTree();
- //-----------------------------------------------------------------------
-// /**
-// * Iterator over the TreeList.
-// * <p>
-// * This iterator is good at iteration, but bad at removal.
-// * Implementing ListIterator would be even more complex, so has been avoided.
-// */
-// static class TreeIterator implements Iterator {
-// /** The parent list */
-// private final TreeList parent;
-// /** A stack built up during iteration to avoid each node referencing its
parent */
-// private ArrayStack stack = new ArrayStack();
-// /** Whether remove is currently allowed */
-// private boolean canRemoveOrSet;
-// /** The last node returned */
-// private AVLNode lastNode;
-// /** The next index */
-// private int nextIndex;
-//
-// /**
-// * Constructor.
-// *
-// * @param parent the parent list
-// */
-// TreeIterator(TreeList parent) {
-// this.parent = parent;
-// }
-//
-// private AVLNode findNext() {
-// AVLNode node = lastNode;
-// if (node == null) {
-// node = parent.root;
-// while (node.left != null) {
-// stack.add(node);
-// node = node.left;
-// }
-// return node;
-// }
-// if (node.right != null) {
-// node = node.right;
-// while (node.left != null) {
-// stack.add(node);
-// node = node.left;
-// }
-// return node;
-// }
-// if (stack.isEmpty()) {
-// throw new NoSuchElementException();
-// }
-// return (AVLNode) stack.pop();
-// }
+ int newTopPosition = relativePosition + getOffset(newTop);
+ int myNewPosition = -newTop.relativePosition;
+ int movedPosition = getOffset(newTop) + getOffset(movedNode);
+
+ setRight(movedNode, newTop);
+ newTop.setLeft(this, null);
+
+ setOffset(newTop, newTopPosition);
+ setOffset(this, myNewPosition);
+ setOffset(movedNode, movedPosition);
+ return newTop;
+ }
+
+ private AVLNode rotateRight() {
+ AVLNode newTop = left; // can't be faedelung
+ AVLNode movedNode = getLeftSubTree().getRightSubTree();
+
+ int newTopPosition = relativePosition + getOffset(newTop);
+ int myNewPosition = -newTop.relativePosition;
+ int movedPosition = getOffset(newTop) + getOffset(movedNode);
+
+ setLeft(movedNode, newTop);
+ newTop.setRight(this, null);
+
+ setOffset(newTop, newTopPosition);
+ setOffset(this, myNewPosition);
+ setOffset(movedNode, movedPosition);
+ return newTop;
+ }
+
+ private void setLeft(AVLNode node, AVLNode previous) {
+ leftIsPrevious = (node == null);
+ left = (leftIsPrevious ? previous : node);
+ recalcHeight();
+ }
+
+ private void setRight(AVLNode node, AVLNode next) {
+ rightIsNext = (node == null);
+ right = (rightIsNext ? next : node);
+ recalcHeight();
+ }
+
+// private void checkFaedelung() {
+// AVLNode maxNode = left.max();
+// if (!maxNode.rightIsFaedelung || maxNode.right != this) {
+// throw new RuntimeException(maxNode + " should right-faedel to " +
this);
+// }
+// AVLNode minNode = right.min();
+// if (!minNode.leftIsFaedelung || minNode.left != this) {
+// throw new RuntimeException(maxNode + " should left-faedel to " +
this);
+// }
+// }
//
-// public boolean hasNext() {
-// return (nextIndex < parent.size());
-// }
+// private int checkTreeDepth() {
+// int hright = (getRightSubTree() == null ? -1 :
getRightSubTree().checkTreeDepth());
+// // System.out.print("checkTreeDepth");
+// // System.out.print(this);
+// // System.out.print(" left: ");
+// // System.out.print(_left);
+// // System.out.print(" right: ");
+// // System.out.println(_right);
//
-// public Object next() {
-// if (hasNext() == false) {
-// throw new NoSuchElementException();
+// int hleft = (left == null ? -1 : left.checkTreeDepth());
+// if (height != Math.max(hright, hleft) + 1) {
+// throw new RuntimeException(
+// "height should be max" + hleft + "," + hright + " but is " +
height);
// }
-// lastNode = findNext();
-// nextIndex++;
-// canRemoveOrSet = true;
-// return lastNode.getValue();
+// return height;
// }
//
-// public int nextIndex() {
-// return nextIndex;
+// private int checkLeftSubNode() {
+// if (getLeftSubTree() == null) {
+// return 0;
+// }
+// int count = 1 + left.checkRightSubNode();
+// if (left.relativePosition != -count) {
+// throw new RuntimeException();
+// }
+// return count + left.checkLeftSubNode();
// }
-//
-//// public boolean hasPrevious() {
-//// return (nextIndex > 0);
-//// }
-////
-//// public Object previous() {
-//// if (hasPrevious() == false) {
-//// throw new NoSuchElementException();
-//// }
-//// return parent.get(nextIndex--);
-//// }
-////
-//// public int previousIndex() {
-//// return nextIndex() - 1;
-//// }
-//
-// public void remove() {
-// if (canRemoveOrSet == false) {
-// throw new IllegalStateException();
+//
+// private int checkRightSubNode() {
+// AVLNode right = getRightSubTree();
+// if (right == null) {
+// return 0;
// }
-// if (nextIndex == 1) {
-// parent.remove(--nextIndex);
-// this.lastNode = null;
-// this.stack.clear();
-// } else if (hasNext()) {
-// AVLNode nextNode = findNext();
-// parent.remove(--nextIndex);
-// TreeIterator it = new TreeIterator(parent);
-// AVLNode node = null;
-// while (it.hasNext()) {
-// it.next();
-// if (it.lastNode == nextNode) {
-// this.stack = it.stack;
-// break;
-// }
-// node = it.lastNode;
-// }
-// this.lastNode = node;
-// } else {
-// parent.remove(--nextIndex);
-// this.lastNode = parent.root.get(parent.size() - 1);
-// this.stack.clear();
+// int count = 1;
+// count += right.checkLeftSubNode();
+// if (right.relativePosition != count) {
+// throw new RuntimeException();
// }
-// canRemoveOrSet = false;
+// return count + right.checkRightSubNode();
// }
-//
-//// public void set(Object obj) {
-//// if (canRemoveOrSet == false) {
-//// throw new IllegalStateException();
-//// }
-//// lastNode.setValue(obj);
-//// }
-////
-//// public void add(Object obj) {
-//// }
-// }
+
+ /**
+ * Used for debugging.
+ */
+ public String toString() {
+ return "AVLNode(" + relativePosition + "," + (left != null) + "," +
value +
+ "," + (getRightSubTree() != null) + ", faedelung " + rightIsNext +
" )";
+ }
+ }
+
+ /**
+ * A list iterator over the linked list.
+ */
+ static class TreeListIterator implements ListIterator, OrderedIterator {
+ /** The parent list */
+ protected final TreeList parent;
+ /**
+ * The node that will be returned by [EMAIL PROTECTED] #next()}. If this is
equal
+ * to [EMAIL PROTECTED] AbstractLinkedList#header} then there are no more
values to return.
+ */
+ protected AVLNode next;
+ /**
+ * The index of [EMAIL PROTECTED] #next}.
+ */
+ protected int nextIndex;
+ /**
+ * The last node that was returned by [EMAIL PROTECTED] #next()} or [EMAIL
PROTECTED]
+ * #previous()}. Set to <code>null</code> if [EMAIL PROTECTED] #next()} or
[EMAIL PROTECTED]
+ * #previous()} haven't been called, or if the node has been removed
+ * with [EMAIL PROTECTED] #remove()} or a new node added with [EMAIL
PROTECTED] #add(Object)}.
+ * Should be accessed through [EMAIL PROTECTED] #getLastNodeReturned()} to
enforce
+ * this behaviour.
+ */
+ protected AVLNode current;
+ /**
+ * The index of [EMAIL PROTECTED] #current}.
+ */
+ protected int currentIndex;
+ /**
+ * The modification count that the list is expected to have. If the list
+ * doesn't have this count, then a
+ * [EMAIL PROTECTED] java.util.ConcurrentModificationException} may be
thrown by
+ * the operations.
+ */
+ protected int expectedModCount;
+
+ /**
+ * Create a ListIterator for a list.
+ *
+ * @param parent the parent list
+ * @param fromIndex the index to start at
+ */
+ protected TreeListIterator(TreeList parent, int fromIndex) throws
IndexOutOfBoundsException {
+ super();
+ this.parent = parent;
+ this.expectedModCount = parent.modCount;
+ this.next = (parent.root == null ? null : parent.root.get(fromIndex));
+ this.nextIndex = fromIndex;
+ }
+
+ /**
+ * Checks the modification count of the list is the value that this
+ * object expects.
+ *
+ * @throws ConcurrentModificationException If the list's modification
+ * count isn't the value that was expected.
+ */
+ protected void checkModCount() {
+ if (parent.modCount != expectedModCount) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ public boolean hasNext() {
+ return (nextIndex < parent.size());
+ }
+
+ public Object next() {
+ checkModCount();
+ if (!hasNext()) {
+ throw new NoSuchElementException("No element at index " + nextIndex
+ ".");
+ }
+ if (next == null) {
+ next = parent.root.get(nextIndex);
+ }
+ Object value = next.getValue();
+ current = next;
+ currentIndex = nextIndex++;
+ next = next.next();
+ return value;
+ }
+
+ public boolean hasPrevious() {
+ return (nextIndex > 0);
+ }
+
+ public Object previous() {
+ checkModCount();
+ if (!hasPrevious()) {
+ throw new NoSuchElementException("Already at start of list.");
+ }
+ if (next == null) {
+ next = parent.root.get(nextIndex - 1);
+ } else {
+ next = next.previous();
+ }
+ Object value = next.getValue();
+ current = next;
+ currentIndex = --nextIndex;
+ return value;
+ }
+
+ public int nextIndex() {
+ return nextIndex;
+ }
+
+ public int previousIndex() {
+ return nextIndex() - 1;
+ }
+
+ public void remove() {
+ checkModCount();
+ if (current == null) {
+ throw new IllegalStateException();
+ }
+ parent.remove(currentIndex);
+ current = null;
+ currentIndex = -1;
+ nextIndex--;
+ expectedModCount++;
+ }
+
+ public void set(Object obj) {
+ checkModCount();
+ if (current == null) {
+ throw new IllegalStateException();
+ }
+ current.setValue(obj);
+ }
+
+ public void add(Object obj) {
+ checkModCount();
+ parent.add(nextIndex, obj);
+ current = null;
+ currentIndex = -1;
+ nextIndex++;
+ expectedModCount++;
+ }
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]