Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
294 changes: 294 additions & 0 deletions redBlackTree.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
public class RedBlackTree {
/**
* Construct the tree.
*/
public RedBlackTree( ) {
header = new RedBlackNode( null );
header.left = header.right = nullNode;
}

/**
* Compare item and t.element, using compareTo, with
* caveat that if t is header, then item is always larger.
* This routine is called if is possible that t is header.
* If it is not possible for t to be header, use compareTo directly.
*/
private final int compare( Comparable item, RedBlackNode t ) {
if( t == header )
return 1;
else
return item.compareTo( t.element );
}

/**
* Insert into the tree.
* @param item the item to insert.
* @throws DuplicateItemException if item is already present.
*/
public void insert( Comparable item ) {
current = parent = grand = header;
nullNode.element = item;

while( compare( item, current ) != 0 ) {
great = grand; grand = parent; parent = current;
current = compare( item, current ) < 0 ?
current.left : current.right;

// Check if two red children; fix if so
if( current.left.color == RED && current.right.color == RED )
handleReorient( item );
}

// Insertion fails if already present
if( current != nullNode )
throw new DuplicateItemException( item.toString( ) );
current = new RedBlackNode( item, nullNode, nullNode );

// Attach to parent
if( compare( item, parent ) < 0 )
parent.left = current;
else
parent.right = current;
handleReorient( item );
}

/**
* Remove from the tree.
* @param x the item to remove.
* @throws UnsupportedOperationException if called.
*/
public void remove( Comparable x ) {
throw new UnsupportedOperationException( );
}

/**
* Find the smallest item the tree.
* @return the smallest item or null if empty.
*/
public Comparable findMin( ) {
if( isEmpty( ) )
return null;

RedBlackNode itr = header.right;

while( itr.left != nullNode )
itr = itr.left;

return itr.element;
}

/**
* Find the largest item in the tree.
* @return the largest item or null if empty.
*/
public Comparable findMax( ) {
if( isEmpty( ) )
return null;

RedBlackNode itr = header.right;

while( itr.right != nullNode )
itr = itr.right;

return itr.element;
}

/**
* Find an item in the tree.
* @param x the item to search for.
* @return the matching item or null if not found.
*/
public Comparable find( Comparable x ) {
nullNode.element = x;
current = header.right;

for( ; ; ) {
if( x.compareTo( current.element ) < 0 )
current = current.left;
else if( x.compareTo( current.element ) > 0 )
current = current.right;
else if( current != nullNode )
return current.element;
else
return null;
}
}

/**
* Make the tree logically empty.
*/
public void makeEmpty( ) {
header.right = nullNode;
}

/**
* Print all items.
*/
public void printTree( ) {
printTree( header.right );
}

/**
* Internal method to print a subtree in sorted order.
* @param t the node that roots the tree.
*/
private void printTree( RedBlackNode t ) {
if( t != nullNode ) {
printTree( t.left );
System.out.println( t.element );
printTree( t.right );
}
}

/**
* Test if the tree is logically empty.
* @return true if empty, false otherwise.
*/
public boolean isEmpty( ) {
return header.right == nullNode;
}

/**
* Internal routine that is called during an insertion
* if a node has two red children. Performs flip and rotations.
* @param item the item being inserted.
*/
private void handleReorient( Comparable item ) {
// Do the color flip
current.color = RED;
current.left.color = BLACK;
current.right.color = BLACK;

if( parent.color == RED ) // Have to rotate
{
grand.color = RED;
if( ( compare( item, grand ) < 0 ) !=
( compare( item, parent ) < 0 ) )
parent = rotate( item, grand ); // Start dbl rotate
current = rotate( item, great );
current.color = BLACK;
}
header.right.color = BLACK; // Make root black
}

/**
* Internal routine that performs a single or double rotation.
* Because the result is attached to the parent, there are four cases.
* Called by handleReorient.
* @param item the item in handleReorient.
* @param parent the parent of the root of the rotated subtree.
* @return the root of the rotated subtree.
*/
private RedBlackNode rotate( Comparable item, RedBlackNode parent ) {
if( compare( item, parent ) < 0 )
return parent.left = compare( item, parent.left ) < 0 ?
rotateWithLeftChild( parent.left ) : // LL
rotateWithRightChild( parent.left ) ; // LR
else
return parent.right = compare( item, parent.right ) < 0 ?
rotateWithLeftChild( parent.right ) : // RL
rotateWithRightChild( parent.right ); // RR
}

/**
* Rotate binary tree node with left child.
*/
private static RedBlackNode rotateWithLeftChild( RedBlackNode k2 ) {
RedBlackNode k1 = k2.left;
k2.left = k1.right;
k1.right = k2;
return k1;
}

/**
* Rotate binary tree node with right child.
*/
private static RedBlackNode rotateWithRightChild( RedBlackNode k1 ) {
RedBlackNode k2 = k1.right;
k1.right = k2.left;
k2.left = k1;
return k2;
}

private static class RedBlackNode {
// Constructors
RedBlackNode( Comparable theElement ) {
this( theElement, null, null );
}

RedBlackNode( Comparable theElement, RedBlackNode lt, RedBlackNode rt ) {
element = theElement;
left = lt;
right = rt;
color = RedBlackTree.BLACK;
}

Comparable element; // The data in the node
RedBlackNode left; // Left child
RedBlackNode right; // Right child
int color; // Color
}

private RedBlackNode header;
private static RedBlackNode nullNode;
static // Static initializer for nullNode
{
nullNode = new RedBlackNode( null );
nullNode.left = nullNode.right = nullNode;
}

private static final int BLACK = 1; // Black must be 1
private static final int RED = 0;

// Used in insert routine and its helpers
private static RedBlackNode current;
private static RedBlackNode parent;
private static RedBlackNode grand;
private static RedBlackNode great;


// Test program
public static void main( String [ ] args ) {
RedBlackTree t = new RedBlackTree( );
final int NUMS = 400000;
final int GAP = 35461;

System.out.println( "Checking... (no more output means success)" );

for( int i = GAP; i != 0; i = ( i + GAP ) % NUMS )
t.insert( new Integer( i ) );

if( ((Integer)(t.findMin( ))).intValue( ) != 1 ||
((Integer)(t.findMax( ))).intValue( ) != NUMS - 1 )
System.out.println( "FindMin or FindMax error!" );

for( int i = 1; i < NUMS; i++ )
if( ((Integer)(t.find( new Integer( i ) ))).intValue( ) != i )
System.out.println( "Find error1!" );
}
}


/**
* Exception class for duplicate item errors
* in search tree insertions.
* @author Mark Allen Weiss
*/
public class DuplicateItemException extends RuntimeException
{
/**
* Construct this exception object.
*/
public DuplicateItemException( )
{
super( );
}
/**
* Construct this exception object.
* @param message the error message.
*/
public DuplicateItemException( String message )
{
super( message );
}
}