问题提出:
1.RedBlack Tree是一种简单的自平衡树。它通过属性约束来实现树的平衡,保证在树上没有一条路是别的路的2倍长。
2. 它有以下五条属性约束:
1) 每个node是红色或者黑色;
2) 每个叶子node是黑色;
3)根node是黑色;
4)若一个node是黑色,则它的两个孩子node是红色;
5) 对每个node,若有从这个node到它的子孙叶子(node)的路上包含有相同数目的黑色节点;
3. 本文的实现是参考introduction to algorithm 书中的讲述;
4. 本文和STL map做了简单的性能比较,结果基本上不相上下;
代码如下:
#ifndef _RED_BLACK_TREE_H_
#define _RED_BLACK_TREE_H_
#include <functional>
#include <algorithm>
#include <map>
/*
* encapsulate red black tree only for challenge self
*
*/
template<class T, class V, class Cmp = std::less<T> >
class RedBlackTree
{
public:
enum COLOR
{
RED,
BLACK
};
typedef struct tagRedBlackNode
{
T key;
V value;
tagRedBlackNode* parent;
tagRedBlackNode* leftChild;
tagRedBlackNode* rightChild;
COLOR color;
tagRedBlackNode():key(), value(),
parent(0), leftChild(0),
rightChild(0), color()
{
}
tagRedBlackNode( const T& _key, const T& _value ): key(_key),
value(_value),
leftChild(0),
rightChild(0),
color(RED)
{
}
}RedBlackNode, *pRedBlackNode;
/*
*
*
*/
RedBlackTree():m_root(0), m_size(0)
{
}
/*
* Copy constructor
*
*/
RedBlackTree( const RedBlackTree& rhs )
{
m_root = Clone( rhs.m_root );
m_size = rhs.m_size;
}
/*
*
*
*/
~RedBlackTree()
{
Clear();
}
/*
* assignment operator overload
*
*/
RedBlackTree& operator = ( const RedBlackTree& rhs )
{
if( this != &rhs )
{
Clear();
m_root = Clone( rhs.m_root );
m_size = rhs.m_size;
}
return *this;
}
/*
*
*
*/
bool IsEmpty() const
{
return Size == 0;
}
/*
* Remove all node
*
*/
void Clear()
{
Clear( m_root );
m_size = 0;
}
/*
* Retrieve the number of node
*
*/
size_t Size() const
{
return m_size;
}
/*
*
*
*/
void Insert( const T& key, const V& value )
{
InsertUtil( key, value );
}
/*
* Find value from tree for given key
*
*/
V* Find( const T& key )
{
return Find( m_root, key );
}
/*
* delete node from tree for given key
*
*/
void Delete( const T& key )
{
Delete( m_root, key );
}
/*
* Retrieve the element of min
*
*/
V* FindMin( T& key )
{
pRedBlackNode node = FindMin( m_root );
if( node )
{
key = node->key;
return &node->value;
}
return 0;
}
/*
* Retrieve the element of max
*
*/
V* FindMax( T& key )
{
pRedBlackNode node = FindMax( m_root );
if( node )
{
key = node->key;
return &node->value;
}
return 0;
}
size_t GetSize() const
{
return Size( m_root );
}
protected:
/*
* get the number of node by recursive method
*
*/
size_t Size( pRedBlackNode root ) const
{
if( 0 == root )
return 0;
return 1 + Size( root->leftChild ) + Size( root->rightChild );
}
/*
* Clone tree
*
*/
pRedBlackNode Clone( pRedBlackNode root )
{
if( 0 == root )
return root;
pRedBlackNode newNode = new RedBlackNode( root->key, root->value );
newNode->leftChild = Clone( root->leftChild );
newNode->rightChild = Clone( root->rightChild );
if( newNode->leftChild )
newNode->leftChild->parent = newNode;
if( newNode->rightChild )
newNode->rightChild->parent = newNode;
return newNode;
}
/*
* Clear all elements
*
*/
void Clear( pRedBlackNode& root )
{
if( 0 == root )
return;
Clear( root->leftChild );
Clear( root->rightChild );
delete root;
root = 0;
}
/*
* Reabalance when complete delete operation
*
*/
void DeleteReablance( pRedBlackNode root )
{
if( 0 == root->parent )
return;
while( root != m_root && BLACK == root->color )
{
if( root == root->parent->leftChild )
{
pRedBlackNode y = root->parent->rightChild;
if( RED == y->color )
{
y->color = BLACK;
root->parent->color = RED;
LeftRotate( root->parent );
y = root->parent->rightChild;
}
if( y->leftChild && BLACK == y->leftChild->color && y->rightChild && BLACK == y->rightChild->color )
{
y->color = RED;
root = root->parent;
}
else
{
if( y->rightChild && BLACK == y->rightChild->color )
{
y->leftChild->color = BLACK;
y->color = RED;
RightRotate( y );
y = root->parent;
}
y->color = root->parent->color;
root->color = BLACK;
if( y->rightChild )
y->rightChild->color = BLACK;
LeftRotate( root->parent );
root = m_root;
}
}
else if( root == root->parent->rightChild )
{
pRedBlackNode y = root->parent->leftChild;
if( RED == y->color )
{
y->color = BLACK;
root->parent->color = RED;
RightRotate( root->parent );
y = root->parent->leftChild;
}
if( y->leftChild && BLACK == y->leftChild->color && y->rightChild && BLACK == y->rightChild->color )
{
y->color = RED;
root = root->parent;
}
else
{
if( y->leftChild && BLACK == y->leftChild->color )
{
y->rightChild->color = BLACK;
y->color = RED;
LeftRotate( y );
y = root->parent;
}
y->color = root->parent->color;
root->color = BLACK;
if( y->leftChild )
y->leftChild->color = BLACK;
RightRotate( root->parent );
root = m_root;
}
}
}// terminal while loop
root->color = BLACK;
}
/*
* reabalance tree when complete insert operation
*
*/
void InsertReablance( pRedBlackNode root )
{
if( 0 == root->parent )
{
root->color = BLACK;
return;
}
while( root->parent && RED == root->parent->color )
{
if( root->parent->parent )
{
if( root->parent == root->parent->parent->leftChild ) // uncle right
{
pRedBlackNode y = root->parent->parent->rightChild;
if( y && RED == y->color ) // case 1
{
root->parent->color = BLACK;
y->color = BLACK;
root->parent->parent->color = RED;
root = root->parent->parent;
}
else
{
if( root == root->parent->rightChild )
{
root = root->parent;
LeftRotate( root );
}
root->parent->color = BLACK;
root->parent->parent->color = RED;
RightRotate( root->parent->parent );
}
}
else if( root->parent == root->parent->parent->rightChild ) // uncle left
{
pRedBlackNode y = root->parent->parent->leftChild;
if( y && RED == y->color ) // case 1
{
root->parent->color = BLACK;
y->color = BLACK;
root->parent->parent->color = RED;
root = root->parent->parent;
}
else
{
if( root == root->parent->leftChild )
{
root = root->parent;
RightRotate( root );
}
root->parent->color = BLACK;
root->parent->parent->color = RED;
LeftRotate( root->parent->parent );
}
}
}
}
m_root->color = BLACK;
}
/*
*Insert element to redblack tree
*
*/
void InsertUtil( const T& key, const V& value )
{
pRedBlackNode root = m_root;
pRedBlackNode cur = root;
while( root )
{
cur = root;
if( key < root->key )
{
root = root->leftChild;
}
else if( key > root->key )
{
root = root->rightChild;
}
}
pRedBlackNode newNode = new RedBlackNode( key, value );
newNode->parent = cur;
if( 0 == cur )
{
m_root = newNode;
}
else if( cur->key > newNode->key )
{
cur->leftChild = newNode;
}
else if( cur->key < newNode->key )
{
cur->rightChild = newNode;
}
InsertReablance( newNode );
m_size++;
}
/*
* Delete element from redblack tree
*
*/
pRedBlackNode DeleteUtil( pRedBlackNode root, const T& key )
{
if( 0 == root )
return 0;
pRedBlackNode y = 0;
if( 0 == root->leftChild ||
0 == root->rightChild )
{
y = root;
}
else
{
y = Successor( root );
}
pRedBlackNode x = 0;
if( y->leftChild != 0 )
{
x = y->leftChild;
}
else
{
x = y->rightChild;
}
if( 0 == y->parent )
{
m_root = x;
}
else if( y == y->parent->leftChild )
{
x = y->parent->leftChild;
}
else
{
x = y->parent->rightChild;
}
x->parent = y->parent;
if( y != root )
{
root->key = y->key;
root->value = y->value;
}
if( BLACK == y->color )
{
DeleteReablance( x );
}
return y;
}
/*
*
*
*/
pRedBlackNode Insert( pRedBlackNode root, const T& key, const V& value )
{
if( 0 == root )
{
root = new RedBlackNode( key, value );
return root;
}
if( root->key < key )
{
root->rightChild = Insert( root->rightChild, key, value );
}
else if( root->key > key )
{
root->leftChild = Insert( root->leftChild, key, value );
}
}
/*
*
*
*/
V* Find( pRedBlackNode root, const T& key )
{
if( 0 == root )
return 0;
pRedBlackNode cur = root;
while( root )
{
cur = root;
if( root->key < key )
{
root = root->rightChild;
}
else if( root->key > key )
{
root = root->leftChild;
}
else
{
break;
}
}
if( cur->key == key )
{
return &cur->value;
}
return 0;
}
/*
*
*
*/
void Delete( pRedBlackNode root, const T& key )
{
if( 0 == root )
return;
if( root->key < key )
{
Delete( root->rightChild, key );
}
else if( root->key > key )
{
Delete( root->leftChild, key );
}
else
{
pRedBlackNode delNode = DeleteUtil( root, key );
if( delNode->parent->leftChild == delNode )
{
delNode->parent->leftChild = 0;
}
else
{
delNode->parent->rightChild = 0;
}
delete delNode;
delNode = 0;
m_size--;
}
}
/*
*
*
*/
pRedBlackNode FindMin( pRedBlackNode root )
{
if( 0 == root )
return root;
while( root->leftChild )
{
root = root->leftChild;
}
return root;
}
/*
*
*
*/
pRedBlackNode FindMax( pRedBlackNode root )
{
if( 0 == root )
return root;
while( root->rightChild )
{
root = root->rightChild;
}
return root;
}
/*
*
*
*/
void LeftRotate( pRedBlackNode root )
{
pRedBlackNode y = root->rightChild;
root->rightChild = y->leftChild;
if( y->leftChild )
y->leftChild->parent = root;
y->parent = root->parent;
if( root == m_root )
{
m_root = y;
}
else if( root->parent->leftChild == root )
{
root->parent->leftChild = y;
}
else
{
root->parent->rightChild = y;
}
y->leftChild = root;
root->parent = y;
}
/*
*
*
*/
void RightRotate( pRedBlackNode root )
{
pRedBlackNode y = root->leftChild;
root->leftChild = y->rightChild;
if( y->rightChild )
y->rightChild->parent = root;
y->parent = root->parent;
if( root == m_root )
{
m_root = y;
}
else if( root->parent->leftChild == root )
{
root->parent->leftChild = y;
}
else
{
root->parent->rightChild = y;
}
y->rightChild = root;
root->parent = y;
}
/*
*
*
*/
pRedBlackNode Successor( pRedBlackNode root )
{
if( 0 == root )
return root;
if( root->rightChild )
{
root = FindMin( root->rightChild );
}
else
{
pRedBlackNode y = root->parent;
if( 0 == y )
return root;
while( root == y->rightChild )
{
root = y;
y = y->parent;
}
if( root->rightChild != y )
{
root = y;
}
}
return root;
}
/*
*
*
*/
pRedBlackNode Predecessor( pRedBlackNode root )
{
if( 0 == root )
return root;
if( root->leftChild )
{
root = FindMax( root->leftChild );
}
else
{
pRedBlackNode y = root->parent;
if( 0 == y )
return root;
while( root == y->leftChild )
{
root = y;
y = y->parent;
}
root = y;
}
return root;
}
protected:
pRedBlackNode m_root;
size_t m_size;
};
/*
* Test STL map
*
*/
void TestSTLMapRbTree()
{
const int Len = 10000;
int key[Len];
int value[Len];
for( int i = 0; i < Len; i++ )
{
key[i] = i;
value[i] = i;
}
std::random_shuffle( key, key + Len );
std::random_shuffle( value, value + Len );
unsigned long start = GetTickCount();
std::map<int, int> treeObj;
for( int i = 0; i < Len; i++ )
{
treeObj.insert( std::make_pair( key[i], value[i] ) );
}
size_t count = treeObj.size();
for( int i = 0; i < Len; i++ )
{
std::map<int, int>::iterator iter = treeObj.find( key[i] );
assert( iter != treeObj.end() );
assert( iter->second == value[i] );
}
for( int i = 0; i < Len; i++ )
{
if( !(i % 15) )
{
treeObj.erase( key[i] );
std::map<int, int>::iterator iter = treeObj.find( key[i] );
assert( iter == treeObj.end() );
}
}
unsigned long interval = GetTickCount() - start;
printf( " STL map consume time is %d \n", interval );
}
/*
* Unit test for redblack tree
*
*/
void TestRedBlackTree()
{
const int Len = 10000;
int key[Len];
int value[Len];
for( int i = 0; i < Len; i++ )
{
key[i] = i;
value[i] = i;
}
std::random_shuffle( key, key + Len );
std::random_shuffle( value, value + Len );
unsigned long start = GetTickCount();
RedBlackTree<int, int> treeObj;
for( int i = 0; i < Len; i++ )
{
treeObj.Insert( key[i], value[i] );
}
size_t count = treeObj.GetSize();
for( int i = 0; i < Len; i++ )
{
int* val = treeObj.Find( key[i] );
assert( *val == value[i] );
}
int minKey = -1;
int* minValue = treeObj.FindMin( minKey );
assert( minKey == 0 );
assert( minValue != 0 );
int maxKey = -1;
int* maxValue = treeObj.FindMax( maxKey );
assert( maxKey == Len - 1 );
assert( maxValue != 0 );
size_t size = treeObj.Size();
assert( size == Len );
for( int i = 0; i < Len; i++ )
{
if( !(i % 15) )
{
treeObj.Delete( i );
int* val = treeObj.Find( i );
assert( !val );
}
}
RedBlackTree<int, int> newTreeObj;
newTreeObj = treeObj;
assert(newTreeObj.Size() == treeObj.Size());
newTreeObj.Clear();
treeObj.Clear();
unsigned long interval = GetTickCount() - start;
printf( " redblack tree consume time is %d \n", interval );
}
void TestSuiteRBTree()
{
TestSTLMapRbTree();
TestRedBlackTree();
}
#endif
compile and run in visual studio 2005