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

问题提出:

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

时间: 2024-10-03 20:31:25

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

泛型Binary Search Tree实现,And和STL map比较的经营业绩

问题叙述性说明: 1.binary search tree它是一种二进制树的.对于key值.比当前节点左孩子少大于右子. 2.binary search tree不是自平衡树.所以,当插入数据不是非常随机时候,性能会接近O(N).N是树中节点数目; 3.理想状态下.时间复杂度是O(lgN), N是树中节点的数目: 4.以下给出一个简单的实现,并比較其和STL map的性能.一样的操作,大约耗时为STL map 的2/3. 代码例如以下: #ifndef _BINARY_SEARCH_TREE_H

支持泛型AVL Tree的简单实现,并和STL map比较了插入,删除,查找的性能

1.问题描述: 1)AVL tree是一种自平衡树.它通过左右子树的高度差来控制树的平衡,当高度差是不大于1的时候,认为树是平衡的.树的平衡保证了树在极端情况下 (输入序列不够随机)的性能.很显然当左右子树高度平衡,保证了任何插入,删除,查找操作平均性能呢个,当不平衡时(有的子树很高),当 要操作的元素在这个子树时,性能会很差: 2)AVL tree 和Red black tree 都是一种平衡树,它的操作的时间复杂度是:O(lgN) ,N是树的节点的数目: 3)本文实现了AVL Tree, 并

[转]SGI STL 红黑树(Red-Black Tree)源代码分析

STL提供了许多好用的数据结构与算法,使我们不必为做许许多多的重复劳动.STL里实现了一个树结构-Red-Black Tree,它也是STL里唯一实现的一个树状数据结构,并且它是map, multimap,set,multiset的底层实现,如果学会了Red-Black Tree,那么对我们高效的运用STL是很有帮助的. 1. 什么是红黑树 红黑树是二叉查找树的一种,由于它能够保证树的高度比较底,所以是一种性能较好的查找树.它需要满足以下几条性质: 1.每个结点或是红的,或是黑的 2.根结点是黑

笔试算法题(51):简介 - 红黑树(RedBlack Tree)

红黑树(Red-Black Tree) 红黑树是一种BST,但是每个节点上增加一个存储位表示该节点的颜色(R或者B):通过对任何一条从root到leaf的路径上节点着色方式的显示,红黑树确保所有路径的差值不会超过一倍,最终使得BST接近平衡: 红黑树内每个节点包含五个属性:color, key, left, right和p,p表示指向父亲节点的指针:一棵BST需要同时满足下述五个性质才能称作红黑树: 每个节点只能是红色或者黑色节点中的一种: 根节点必须是黑色: 每个叶节点(NULL)必须是黑色:

数据结构-红黑树(Red-Black Tree)的C++实现模板

红黑树的实现还真不简单,各种染色旋转足足折腾了笔者几天.. 不过收获也是巨大的.笔者现在终于明白为啥二叉搜索树这么重要了,确实很有用. 下面上代码. 细心的朋友可能会觉得似乎少了那么几个接口,没错,因为 Precessor(求前驱) / Successor(求后继) / getMaximum (求树中最大值)/ getMinimum(求树中最小值)/ Inorder Traversal(中序遍历)/ Postorder Traversal(后序遍历) 这些操作都可以直接用笔者二叉搜索树(BST)

Red-Black Tree

http://pages.cs.wisc.edu/~skrentny/cs367-common/readings/Red-Black-Trees/ http://en.wikipedia.org/wiki/Red–black_tree 1. Every node is either red or black. 2. The root is black. (This rule is sometimes omitted. Since the root can always be changed fr

[Data Structure] 红黑树( Red-Black Tree ) - 笔记

1.  红黑树属性:根到叶子的路径中,最长路径不大于最短路径的两倍. 2. 红黑树是一个二叉搜索树,并且有 a. 每个节点除了有左.右.父节点的属性外,还有颜色属性,红色或者黑色. b. ( 根属性 ) 红黑树的根只能是黑色 c. ( 红色属性 ) 红色节点的子节点只能是黑色 d. ( 黑色属性 ) 从给定的节点到其后代叶子节点的每一条路径上,出现的黑色节点数目一样.其中,从某个节点到其后代叶子节点的路径上出现的黑色节点数,被称为该节点的黑高度( black-height ). 3. 红黑树上的

The easy way to implement a Red-Black tree

Red-Black trees are notorious for being nightmares of pointer manipulation. Instructors will show the theory, but won’t torture their students to implement one. Interviewers will avoid asking about it. They probably couldn’t do it themselves. You sho

Red-Black Tree 红黑树

如果viewer对Red-Black Tree先前没有任何了解,可以看看先搞定AVL树,因为AVL树比红黑树要简单的多 涉及同样的rotate技巧,搞懂了AVL树再和红黑大战三百回合绝对轻松的多. (我见过讲AVL最好的教程就是 Mark Allen Weiss 写的<数据结构与算法分析 C语言描述>里面讲AVL树的部分) AVL树的C语言实现: http://blog.csdn.net/cinmyheart/article/details/20527037 Here we go ~ 笔记贴-