data_structures_free
This commit is contained in:
219
net/datastructures/RBTree.java
Normal file
219
net/datastructures/RBTree.java
Normal file
@@ -0,0 +1,219 @@
|
||||
|
||||
|
||||
package net.datastructures;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Realization of a red-black Tree by extending a binary search tree.
|
||||
*
|
||||
* @author Michael Goodrich, Roberto Tamassia, Eric Zamore
|
||||
*/
|
||||
|
||||
//begin#fragment RBTree
|
||||
/** Realization of a dictionary by means of a red-black tree. */
|
||||
public class RBTree<K,V>
|
||||
extends BinarySearchTree<K,V> implements Dictionary<K,V> {
|
||||
public RBTree() { super(); }
|
||||
public RBTree(Comparator<K> C) { super(C); }
|
||||
/** Nested class for the nodes of a red-black tree */
|
||||
protected static class RBNode<K,V> extends BTNode<Entry<K,V>> {
|
||||
protected boolean isRed; // we add a color field to a BTNode
|
||||
RBNode() {/* default constructor */}
|
||||
/** Preferred constructor */
|
||||
RBNode(Entry<K,V> element, BTPosition<Entry<K,V>> parent,
|
||||
BTPosition<Entry<K,V>> left, BTPosition<Entry<K,V>> right) {
|
||||
super(element, parent, left, right);
|
||||
isRed = false;
|
||||
}
|
||||
public boolean isRed() {return isRed;}
|
||||
public void makeRed() {isRed = true;}
|
||||
public void makeBlack() {isRed = false;}
|
||||
public void setColor(boolean color) {isRed = color;}
|
||||
}
|
||||
//end#fragment RBTree
|
||||
//begin#fragment insertItem
|
||||
/** Creates a new tree node. */
|
||||
protected BTPosition<Entry<K,V>> createNode(Entry<K,V> element,
|
||||
BTPosition<Entry<K,V>> parent, BTPosition<Entry<K,V>> left,
|
||||
BTPosition<Entry<K,V>> right) {
|
||||
return new RBNode<K,V>(element,parent,left,right); // a red-black node
|
||||
}
|
||||
//end#fragment insertItem
|
||||
/** Inserts an item into the dictionary and returns the newly
|
||||
* created entry. */
|
||||
//begin#fragment insertItem
|
||||
public Entry<K,V> insert(K k, V x) throws InvalidKeyException {
|
||||
Entry<K,V> toReturn = super.insert(k, x);
|
||||
Position<Entry<K,V>> posZ = actionPos; // start at the insertion position
|
||||
setRed(posZ);
|
||||
if (isRoot(posZ))
|
||||
setBlack(posZ);
|
||||
else
|
||||
remedyDoubleRed(posZ); // fix a double-red color violation
|
||||
return toReturn;
|
||||
}
|
||||
//end#fragment insertItem
|
||||
/** Remedies a double red violation at a given node caused by insertion. */
|
||||
//begin#fragment insertItem
|
||||
protected void remedyDoubleRed(Position<Entry<K,V>> posZ) {
|
||||
Position<Entry<K,V>> posV = parent(posZ);
|
||||
if (isRoot(posV))
|
||||
return;
|
||||
if (!isPosRed(posV))
|
||||
return;
|
||||
// we have a double red: posZ and posV
|
||||
if (!isPosRed(sibling(posV))) { // Case 1: trinode restructuring
|
||||
posV = restructure(posZ);
|
||||
setBlack(posV);
|
||||
setRed(left(posV));
|
||||
setRed(right(posV));
|
||||
}
|
||||
else { // Case 2: recoloring
|
||||
setBlack(posV);
|
||||
setBlack(sibling(posV));
|
||||
Position<Entry<K,V>> posU = parent(posV);
|
||||
if (isRoot(posU))
|
||||
return;
|
||||
setRed(posU);
|
||||
remedyDoubleRed(posU);
|
||||
}
|
||||
}
|
||||
//end#fragment insertItem
|
||||
/** Removes and returns the given entry from the dictionary. */
|
||||
//begin#fragment remedyDoubleBlack
|
||||
public Entry<K,V> remove(Entry<K,V> ent) throws InvalidEntryException {
|
||||
Entry<K,V> toReturn = super.remove(ent);
|
||||
Position<Entry<K,V>> posR = actionPos;
|
||||
if (toReturn != null) {
|
||||
if (wasParentRed(posR) || isRoot(posR) || isPosRed(posR))
|
||||
setBlack(posR);
|
||||
else
|
||||
remedyDoubleBlack(posR);
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
//end#fragment remedyDoubleBlack
|
||||
/** Remedies a double black violation at a given node caused by removal. */
|
||||
//begin#fragment remedyDoubleBlack
|
||||
protected void remedyDoubleBlack(Position<Entry<K,V>> posR) {
|
||||
Position<Entry<K,V>> posX, posY, posZ;
|
||||
boolean oldColor;
|
||||
posX = parent(posR);
|
||||
posY = sibling(posR);
|
||||
if (!isPosRed(posY)) {
|
||||
posZ = redChild(posY);
|
||||
if (hasRedChild(posY)) { // Case 1: trinode restructuring
|
||||
oldColor = isPosRed(posX);
|
||||
posZ = restructure(posZ);
|
||||
setColor(posZ, oldColor);
|
||||
setBlack(posR);
|
||||
setBlack(left(posZ));
|
||||
setBlack(right(posZ));
|
||||
return;
|
||||
}
|
||||
setBlack(posR);
|
||||
setRed(posY);
|
||||
if (!isPosRed(posX)) { // Case 2: recoloring
|
||||
if (!isRoot(posX))
|
||||
remedyDoubleBlack(posX);
|
||||
return;
|
||||
}
|
||||
setBlack(posX);
|
||||
return;
|
||||
} // Case 3: adjustment
|
||||
if (posY == right(posX)) posZ = right(posY);
|
||||
else posZ = left(posY);
|
||||
restructure(posZ);
|
||||
setBlack(posY);
|
||||
setRed(posX);
|
||||
remedyDoubleBlack(posR);
|
||||
}
|
||||
//end#fragment remedyDoubleBlack
|
||||
|
||||
/** Returns whether a node is red. */
|
||||
protected boolean isPosRed(Position<Entry<K,V>> position) {
|
||||
return ((RBNode) position).isRed();
|
||||
}
|
||||
|
||||
/** Returns whether the former parent of a node was red. */
|
||||
private boolean wasParentRed(Position<Entry<K,V>> position){
|
||||
if (!isRoot(position)) {
|
||||
if(!isPosRed(position) && !isPosRed(parent(position))) {
|
||||
if (isExternal(sibling(position)) ||
|
||||
(hasTwoExternalChildren(sibling(position)) &&
|
||||
isPosRed(sibling(position))))
|
||||
return true; //then position's old parent was red
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns whether an internal node has two external children. */
|
||||
private boolean hasTwoExternalChildren(Position<Entry<K,V>> position){
|
||||
if (isExternal(left(position))
|
||||
&& isExternal(right(position)))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Colors a node red. */
|
||||
protected void setRed(Position<Entry<K,V>> position) {
|
||||
((RBNode) position).makeRed();
|
||||
}
|
||||
|
||||
/** Colors a node black. */
|
||||
protected void setBlack(Position<Entry<K,V>> position) {
|
||||
((RBNode) position).makeBlack();
|
||||
}
|
||||
|
||||
/** Sets the color of a node.
|
||||
* @param color <tt>true</tt> to color the node red, <tt>false</tt>
|
||||
* to color the node black*/
|
||||
protected void setColor(Position<Entry<K,V>> position, boolean color) {
|
||||
((RBNode) position).setColor(color);
|
||||
}
|
||||
|
||||
/** Returns a red child of a node. */
|
||||
protected Position<Entry<K,V>> redChild(Position<Entry<K,V>> position) {
|
||||
Position<Entry<K,V>> child = left(position);
|
||||
if (isPosRed(child))
|
||||
return child;
|
||||
child = right(position);
|
||||
if (isPosRed(child))
|
||||
return child;
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Returns whether a node has a red child. */
|
||||
protected boolean hasRedChild(Position<Entry<K,V>> position){
|
||||
if (isPosRed(left(position)) || isPosRed(right(position)))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps the colors of <tt>a</tt> and <tt>b</tt> if they are
|
||||
* different and returns whether <tt>a</tt> was red.
|
||||
*/
|
||||
protected boolean swapColor(Position<Entry<K,V>> a, Position<Entry<K,V>> b){
|
||||
boolean wasRed = false;
|
||||
if (isPosRed(a) && !isPosRed(b)){
|
||||
wasRed = true;
|
||||
setBlack(a);
|
||||
setRed(b);
|
||||
}
|
||||
else if (!isPosRed(a) && isPosRed(b)){
|
||||
setBlack(b);
|
||||
setRed(a);
|
||||
}
|
||||
return wasRed;
|
||||
}
|
||||
|
||||
/** Swaps the colors and elements at the two nodes. */
|
||||
protected void swap(Position<Entry<K,V>> swapPos, Position<Entry<K,V>> remPos){
|
||||
swapColor(remPos, swapPos);
|
||||
swapElements(swapPos, remPos);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user