📄 treebidimap.java
字号:
}
return rval;
}
/**
* copy the color from one node to another, dealing with the fact
* that one or both nodes may, in fact, be null
*
* @param from the node whose color we're copying; may be null
* @param to the node whose color we're changing; may be null
* @param index the KEY or VALUE int
*/
private static void copyColor(final Node from, final Node to, final int index) {
if (to != null) {
if (from == null) {
// by default, make it black
to.setBlack(index);
} else {
to.copyColor(from, index);
}
}
}
/**
* is the specified node red? if the node does not exist, no, it's
* black, thank you
*
* @param node the node (may be null) in question
* @param index the KEY or VALUE int
*/
private static boolean isRed(final Node node, final int index) {
return ((node == null) ? false : node.isRed(index));
}
/**
* is the specified black red? if the node does not exist, sure,
* it's black, thank you
*
* @param node the node (may be null) in question
* @param index the KEY or VALUE int
*/
private static boolean isBlack(final Node node, final int index) {
return ((node == null) ? true : node.isBlack(index));
}
/**
* force a node (if it exists) red
*
* @param node the node (may be null) in question
* @param index the KEY or VALUE int
*/
private static void makeRed(final Node node, final int index) {
if (node != null) {
node.setRed(index);
}
}
/**
* force a node (if it exists) black
*
* @param node the node (may be null) in question
* @param index the KEY or VALUE int
*/
private static void makeBlack(final Node node, final int index) {
if (node != null) {
node.setBlack(index);
}
}
/**
* get a node's grandparent. mind you, the node, its parent, or
* its grandparent may not exist. no problem
*
* @param node the node (may be null) in question
* @param index the KEY or VALUE int
*/
private static Node getGrandParent(final Node node, final int index) {
return getParent(getParent(node, index), index);
}
/**
* get a node's parent. mind you, the node, or its parent, may not
* exist. no problem
*
* @param node the node (may be null) in question
* @param index the KEY or VALUE int
*/
private static Node getParent(final Node node, final int index) {
return ((node == null) ? null : node.getParent(index));
}
/**
* get a node's right child. mind you, the node may not exist. no
* problem
*
* @param node the node (may be null) in question
* @param index the KEY or VALUE int
*/
private static Node getRightChild(final Node node, final int index) {
return (node == null) ? null : node.getRight(index);
}
/**
* get a node's left child. mind you, the node may not exist. no
* problem
*
* @param node the node (may be null) in question
* @param index the KEY or VALUE int
*/
private static Node getLeftChild(final Node node, final int index) {
return (node == null) ? null : node.getLeft(index);
}
/**
* is this node its parent's left child? mind you, the node, or
* its parent, may not exist. no problem. if the node doesn't
* exist ... it's its non-existent parent's left child. If the
* node does exist but has no parent ... no, we're not the
* non-existent parent's left child. Otherwise (both the specified
* node AND its parent exist), check.
*
* @param node the node (may be null) in question
* @param index the KEY or VALUE int
*/
private static boolean isLeftChild(final Node node, final int index) {
return (node == null)
? true
: ((node.getParent(index) == null) ?
false : (node == node.getParent(index).getLeft(index)));
}
/**
* is this node its parent's right child? mind you, the node, or
* its parent, may not exist. no problem. if the node doesn't
* exist ... it's its non-existent parent's right child. If the
* node does exist but has no parent ... no, we're not the
* non-existent parent's right child. Otherwise (both the
* specified node AND its parent exist), check.
*
* @param node the node (may be null) in question
* @param index the KEY or VALUE int
*/
private static boolean isRightChild(final Node node, final int index) {
return (node == null)
? true
: ((node.getParent(index) == null) ?
false : (node == node.getParent(index).getRight(index)));
}
/**
* do a rotate left. standard fare in the world of balanced trees
*
* @param node the node to be rotated
* @param index the KEY or VALUE int
*/
private void rotateLeft(final Node node, final int index) {
Node rightChild = node.getRight(index);
node.setRight(rightChild.getLeft(index), index);
if (rightChild.getLeft(index) != null) {
rightChild.getLeft(index).setParent(node, index);
}
rightChild.setParent(node.getParent(index), index);
if (node.getParent(index) == null) {
// node was the root ... now its right child is the root
rootNode[index] = rightChild;
} else if (node.getParent(index).getLeft(index) == node) {
node.getParent(index).setLeft(rightChild, index);
} else {
node.getParent(index).setRight(rightChild, index);
}
rightChild.setLeft(node, index);
node.setParent(rightChild, index);
}
/**
* do a rotate right. standard fare in the world of balanced trees
*
* @param node the node to be rotated
* @param index the KEY or VALUE int
*/
private void rotateRight(final Node node, final int index) {
Node leftChild = node.getLeft(index);
node.setLeft(leftChild.getRight(index), index);
if (leftChild.getRight(index) != null) {
leftChild.getRight(index).setParent(node, index);
}
leftChild.setParent(node.getParent(index), index);
if (node.getParent(index) == null) {
// node was the root ... now its left child is the root
rootNode[index] = leftChild;
} else if (node.getParent(index).getRight(index) == node) {
node.getParent(index).setRight(leftChild, index);
} else {
node.getParent(index).setLeft(leftChild, index);
}
leftChild.setRight(node, index);
node.setParent(leftChild, index);
}
/**
* complicated red-black insert stuff. Based on Sun's TreeMap
* implementation, though it's barely recognizable any more
*
* @param insertedNode the node to be inserted
* @param index the KEY or VALUE int
*/
private void doRedBlackInsert(final Node insertedNode, final int index) {
Node currentNode = insertedNode;
makeRed(currentNode, index);
while ((currentNode != null)
&& (currentNode != rootNode[index])
&& (isRed(currentNode.getParent(index), index))) {
if (isLeftChild(getParent(currentNode, index), index)) {
Node y = getRightChild(getGrandParent(currentNode, index), index);
if (isRed(y, index)) {
makeBlack(getParent(currentNode, index), index);
makeBlack(y, index);
makeRed(getGrandParent(currentNode, index), index);
currentNode = getGrandParent(currentNode, index);
} else {
if (isRightChild(currentNode, index)) {
currentNode = getParent(currentNode, index);
rotateLeft(currentNode, index);
}
makeBlack(getParent(currentNode, index), index);
makeRed(getGrandParent(currentNode, index), index);
if (getGrandParent(currentNode, index) != null) {
rotateRight(getGrandParent(currentNode, index), index);
}
}
} else {
// just like clause above, except swap left for right
Node y = getLeftChild(getGrandParent(currentNode, index), index);
if (isRed(y, index)) {
makeBlack(getParent(currentNode, index), index);
makeBlack(y, index);
makeRed(getGrandParent(currentNode, index), index);
currentNode = getGrandParent(currentNode, index);
} else {
if (isLeftChild(currentNode, index)) {
currentNode = getParent(currentNode, index);
rotateRight(currentNode, index);
}
makeBlack(getParent(currentNode, index), index);
makeRed(getGrandParent(currentNode, index), index);
if (getGrandParent(currentNode, index) != null) {
rotateLeft(getGrandParent(currentNode, index), index);
}
}
}
}
makeBlack(rootNode[index], index);
}
/**
* complicated red-black delete stuff. Based on Sun's TreeMap
* implementation, though it's barely recognizable any more
*
* @param deletedNode the node to be deleted
*/
private void doRedBlackDelete(final Node deletedNode) {
for (int index = FIRST_INDEX; index < NUMBER_OF_INDICES; index++) {
// if deleted node has both left and children, swap with
// the next greater node
if ((deletedNode.getLeft(index) != null) && (deletedNode.getRight(index) != null)) {
swapPosition(nextGreater(deletedNode, index), deletedNode, index);
}
Node replacement =
((deletedNode.getLeft(index) != null) ? deletedNode.getLeft(index) : deletedNode.getRight(index));
if (replacement != null) {
replacement.setParent(deletedNode.getParent(index), index);
if (deletedNode.getParent(index) == null) {
rootNode[index] = replacement;
} else if (deletedNode == deletedNode.getParent(index).getLeft(index)) {
deletedNode.getParent(index).setLeft(replacement, index);
} else {
deletedNode.getParent(index).setRight(replacement, index);
}
deletedNode.setLeft(null, index);
deletedNode.setRight(null, index);
deletedNode.setParent(null, index);
if (isBlack(deletedNode, index)) {
doRedBlackDeleteFixup(replacement, index);
}
} else {
// replacement is null
if (deletedNode.getParent(index) == null) {
// empty tree
rootNode[index] = null;
} else {
// deleted node had no children
if (isBlack(deletedNode, index)) {
doRedBlackDeleteFixup(deletedNode, index);
}
if (deletedNode.getParent(index) != null) {
if (deletedNode == deletedNode.getParent(index).getLeft(index)) {
deletedNode.getParent(index).setLeft(null, index);
} else {
deletedNode.getParent(index).setRight(null, index);
}
deletedNode.setParent(null, index);
}
}
}
}
shrink();
}
/**
* complicated red-black delete stuff. Based on Sun's TreeMap
* implementation, though it's barely recognizable any more. This
* rebalances the tree (somewhat, as red-black trees are not
* perfectly balanced -- perfect balancing takes longer)
*
* @param replacementNode the node being replaced
* @param index the KEY or VALUE int
*/
private void doRedBlackDeleteFixup(final Node replacementNode, final int index) {
Node currentNode = replacementNode;
while ((currentNode != rootNode[index]) && (isBlack(currentNode, index))) {
if (isLeftChild(currentNode, index)) {
Node siblingNode = getRightChild(getParent(currentNode, index), index);
if (isRed(siblingNode, index)) {
makeBlack(siblingNode, index);
makeRed(getParent(currentNode, index), index);
rotateLeft(getParent(currentNode, index), index);
siblingNode = getRightChild(getParent(currentNode, index), index);
}
if (isBlack(getLeftChild(siblingNode, index), index)
&& isBlack(getRightChild(siblingNode, index), index)) {
makeRed(siblingNode, index);
currentNode = getParent(currentNode, index);
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -