泛型的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();
}


#endif 
compile and run in visual studio 2005

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!