泛型的RedBlack Tree的实现,并和STL map 做了简单的性能比较
时间:2014-04-29 13:33:20
收藏:0
阅读:459
问题提出:
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(); } #endifcompile and run in visual studio 2005
评论(0)