泛型的RedBlack Tree的实现,并和STL map 做了简单的性能比较

来源:互联网 发布:模仿周杰伦的网络 编辑:程序博客网 时间:2024/06/10 04:55

问题提出:

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 looproot->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

2 0