📄 treelist.java
字号:
* Gets the rightmost child of this node.
*
* @return the rightmost child (greatest index)
*/
private AVLNode max() {
return (getRightSubTree() == null) ? this : right.max();
}
/**
* 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.
*/
AVLNode remove(int index) {
int indexRelativeToMe = index - relativePosition;
if (indexRelativeToMe == 0) {
return removeSelf();
}
if (indexRelativeToMe > 0) {
setRight(right.remove(indexRelativeToMe), right.right);
if (relativePosition < 0) {
relativePosition++;
}
} else {
setLeft(left.remove(indexRelativeToMe), left.left);
if (relativePosition > 0) {
relativePosition--;
}
}
recalcHeight();
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();
}
/**
* Removes this node from the tree.
*
* @return the node that replaces this one in the parent
*/
private AVLNode removeSelf() {
if (getRightSubTree() == null && getLeftSubTree() == null) {
return null;
}
if (getRightSubTree() == null) {
if (relativePosition > 0) {
left.relativePosition += relativePosition + (relativePosition > 0 ? 0 : 1);
}
left.max().setRight(null, right);
return left;
}
if (getLeftSubTree() == null) {
right.relativePosition += relativePosition - (relativePosition < 0 ? 0 : 1);
right.min().setLeft(null, left);
return right;
}
if (heightRightMinusLeft() > 0) {
// more on the right, so delete from the right
AVLNode rightMin = right.min();
value = rightMin.value;
if (leftIsPrevious) {
left = rightMin.left;
}
right = right.removeMin();
if (relativePosition < 0) {
relativePosition++;
}
} else {
// more on the left or equal, so delete from the left
AVLNode leftMax = left.max();
value = leftMax.value;
if (rightIsNext) {
right = leftMax.right;
}
AVLNode leftPrevious = left.left;
left = left.removeMax();
if (left == null) {
// special case where left that was deleted was a double link
// only occurs when height difference is equal
left = leftPrevious;
leftIsPrevious = true;
}
if (relativePosition > 0) {
relativePosition--;
}
}
recalcHeight();
return this;
}
//-----------------------------------------------------------------------
/**
* 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!");
}
}
/**
* Gets the relative position.
*/
private int getOffset(AVLNode node) {
if (node == null) {
return 0;
}
return node.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;
}
/**
* Sets the height by calculation.
*/
private void recalcHeight() {
height = Math.max(
getLeftSubTree() == null ? -1 : getLeftSubTree().height,
getRightSubTree() == null ? -1 : getRightSubTree().height) + 1;
}
/**
* Returns the height of the node or -1 if the node is null.
*/
private int getHeight(AVLNode node) {
return (node == null ? -1 : node.height);
}
/**
* Returns the height difference right - left
*/
private int heightRightMinusLeft() {
return getHeight(getRightSubTree()) - getHeight(getLeftSubTree());
}
private AVLNode rotateLeft() {
AVLNode newTop = right; // can't be faedelung!
AVLNode movedNode = getRightSubTree().getLeftSubTree();
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;
}
/**
* Sets the left field to the node, or the previous node if that is null
*
* @param node the new left subtree node
* @param previous the previous node in the linked list
*/
private void setLeft(AVLNode node, AVLNode previous) {
leftIsPrevious = (node == null);
left = (leftIsPrevious ? previous : node);
recalcHeight();
}
/**
* Sets the right field to the node, or the next node if that is null
*
* @param node the new left subtree node
* @param next the next node in the linked list
*/
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);
// }
// }
//
// 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);
//
// 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);
// }
// return height;
// }
//
// private int checkLeftSubNode() {
// if (getLeftSubTree() == null) {
// return 0;
// }
// int count = 1 + left.checkRightSubNode();
// if (left.relativePosition != -count) {
// throw new RuntimeException();
// }
// return count + left.checkLeftSubNode();
// }
//
// private int checkRightSubNode() {
// AVLNode right = getRightSubTree();
// if (right == null) {
// return 0;
// }
// int count = 1;
// count += right.checkLeftSubNode();
// if (right.relativePosition != count) {
// throw new RuntimeException();
// }
// return count + right.checkRightSubNode();
// }
/**
* 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;
/**
* Cache of the next node that will be returned by {@link #next()}.
*/
protected AVLNode next;
/**
* The index of the next node to be returned.
*/
protected int nextIndex;
/**
* Cache of the last node that was returned by {@link #next()}
* or {@link #previous()}.
*/
protected AVLNode current;
/**
* The index of the last node that was returned.
*/
protected int currentIndex;
/**
* The modification count that the list is expected to have. If the list
* doesn't have this count, then a
* {@link 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;
this.currentIndex = -1;
}
/**
* 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 (currentIndex == -1) {
throw new IllegalStateException();
}
if (nextIndex == currentIndex) {
// remove() following previous()
next = next.next();
parent.remove(currentIndex);
} else {
// remove() following next()
parent.remove(currentIndex);
nextIndex--;
}
current = null;
currentIndex = -1;
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++;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -