码迷,mamicode.com
首页 > 其他好文 > 详细

泛型的Binary Search Tree的实现,并与STL map进行操作性能上的比较

时间:2014-04-29 13:27:22      阅读:420      评论:0      收藏:0      [点我收藏+]

标签:数据结构   performance   性能   

问题描述:

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_
#define _BINARY_SEARCH_TREE_H_

#include <functional>
#include <algorithm>
#include <iostream>
#include <map>

#include "windows.h"


template<class T, class V, class Cmp = std::less<T> > 
class BinarySearchTree
{
public:

	// node struct
	typedef struct tagBSNode
	{
		T    key;
		V    value;
		tagBSNode*  leftNode;
		tagBSNode*  rightNode;

		tagBSNode():key(), value(),
			        leftNode(0),
					rightNode(0)
		{

		}

		tagBSNode( const T& _key, const V& _value ):key(_key), 
			                                        value(_value),
													leftNode(0),
													rightNode(0)
		{

		}

	}BSTNode, *pBSTNode;


	/*
	* Constructor
	*
	*/
	BinarySearchTree():m_root(0), m_size(0)
	{

	}

	/*
	* Copy constructor
	*
	*/
	BinarySearchTree( const BinarySearchTree& rhs )
	{
		m_root = Clone( rhs.m_root );
		m_size = rhs.m_size;
	}

	/*
	* Destructor
	*
	*/
	~BinarySearchTree()
	{
		Clear();
	}

	/*
	* assignment operator overload
	*
	*/
	BinarySearchTree& operator = ( const BinarySearchTree& rhs )
	{
		if( this != &rhs )
		{
			Clear();

			m_root = Clone( rhs.m_root );
			m_size = rhs.m_size;
		}

		return *this;
	}

	/*
	* Clear all node 
	*
	*/
	void Clear()
	{
		Clear( m_root );
		m_size = 0;
	}

	/*
	* check whether or not empty
	*
	*/
	bool IsEmpty() const 
	{
		return m_size == 0;
	}

	/*
	* Retrieve the number of node in tree
	*
	*/
	size_t Size() const 
	{
		return m_size;
	}

	/*
	*
	*
	*/
	size_t GetSize() const  // only for test
	{
		return Size( m_root );
	}

	/*
	* Insert key and value pair to tree
	*
	*/
	void Insert( const T& key, const V& value )
	{
		Insert( m_root, key, value );
	}

	/*
	* Delete node from tree for given key
	*
	*/
	void Delete( const T& key )
	{
		Delete( m_root, key );
	}

	/*
	* Find element from tree for given key
	*
	*/
	V* Find( const T& key )
	{
		pBSTNode node = Find( m_root, key );
		if( node )
			return &node->value;

		return 0;
	}

	/*
	* Find the the element of max key 
	*
	*/
	V* FindMax( T& key )
	{
		pBSTNode node = FindMax( m_root );
		if( node )
		{
			key = node->key;
			return &node->value;
		}

		return 0;
	}

	/*
	* Find the the element of min key 
	*
	*/
	V* FinMin( T& key )
	{
		pBSTNode node = FindMin( m_root );
		if( node )
		{
			key = node->key;
			return &node->value;
		}

		return 0;
	}

	/*
	* inoder traversal
	*
	*/
	void InorderVisitor( void (*visitor)( const T&, const V& ) )
	{
		InorderVisitor( m_root, visitor );
	}

	/*
	* preoder traversal
	*
	*/
	void PreOrderVisitor( void (*visitor)( const T&, const V&  )  )
	{
		PreOrderVisitor( m_root, visitor );
	}

	/*
	* postoder traversal
	*
	*/
	void PostOrderVisitor( void (*visitor)( const T&, const V& ) )
	{
		PostOrderVisitor( m_root, visitor );
	}

protected:

	/*
	* Implement clone operation
	*
	*/
	pBSTNode Clone( pBSTNode root )
	{
		if( 0 == root )
			return root;

		pBSTNode node = new BSTNode( root->key, root->value );
		node->leftNode = Clone( root->leftNode );
		node->rightNode = Clone( root->rightNode );

		return node;
	}

	/*
	* Implement clear opreation
	*
	*/
	void Clear( pBSTNode& root )
	{
		if( 0 == root )
			return;

		Clear( root->leftNode );
		Clear( root->rightNode );

		delete root;
		root = 0;

	}


	/*
	* Retrieve the number of node by way of recursive
	*
	*/
	size_t Size( pBSTNode root ) const 
	{
		if( 0 == root )
			return 0;

		return 1 + Size( root->leftNode ) + Size( root->rightNode );
	}

	/*
	* Implement insert operation
	*
	*/
	void Insert( pBSTNode& root,const T& key, const V& value )
	{
		if( 0 == root )
		{
			root = new BSTNode( key, value );
			m_size++;
		}

		if( root->key < key )
		{
			Insert( root->rightNode, key, value );
		}
		else if( root->key > key )
		{
			Insert( root->leftNode, key, value );
		}
	}

	/*
	* Implement delete operation
	*
	*/
	void Delete( pBSTNode& root, const T& key )
	{
		if( 0 == root )
			return;

		if( root->key < key )
		{
			Delete( root->rightNode, key );
		}
		else if( root->key > key )
		{
			Delete( root->leftNode, key );
		}
		else
		{
			if( root->leftNode && root->rightNode )
			{
				pBSTNode minNode = FindMin( root->rightNode );
				root->key  = minNode->key;
				root->value = minNode->value;

				Delete( root->rightNode,  minNode->key );
			}
			else 
			{
				pBSTNode node = root;
				root = root->leftNode ? root->leftNode: root->rightNode;

				delete node;
				node = 0;

				m_size--;  //very important
				
			}

			
		}
	}


	/*
	* Implement find operation
	*
	*/
	pBSTNode Find( pBSTNode root, const T& key )
	{
		if( 0 == root )
			return root;

		if( root->key < key )
		{
			return Find( root->rightNode, key );
		}
		else if( root->key > key )
		{
			return Find( root->leftNode, key );
		}
		else
		{
			return root;
		}
	}

	/*
	* Find implement no recursive
	*
	*/
	pBSTNode FindUtil( pBSTNode root, const T& key )
	{
		if( 0 == root )
			return root;

		pBSTNode cur = root;
		while( root )
		{
			cur = root;
			if( root->key < key )
			{
				root = root->rightNode;
			}
			else if( root->key > key )
			{
				root = root->leftNode;
			}
			else
			{
				break;
			}	
		}

		if( cur  && cur->key == key )
			return cur;

		return 0;
	}


	/*
	* Implement find max element operation
	*
	*/
	pBSTNode FindMax( pBSTNode root )
	{
		if( 0 == root )
			return root;

		while( root->rightNode )
		{
			root = root->rightNode;
		}

		return root;
	}

	/*
	* Implement find min element operation
	*
	*/
	pBSTNode FindMin( pBSTNode root )
	{
		if( 0 == root )
			return root;

		while( root->leftNode )
		{
			root = root->leftNode;
		}

		return root;
	}


	/*
	* Implement inorder traversal
	*
	*/
	void InorderVisitor( pBSTNode root, void (*visitor)( const T&, const V& ) )
	{
		if( 0 == root )
			return;

		InorderVisitor( root->leftNode, visitor );
		visitor( root->key, root->value );
		InorderVisitor( root->rightNode, visitor );
	}

	/*
	* Implement preorder traversal
	*
	*/
	void PreOrderVisitor( pBSTNode root, void (*visitor)( const T&, const V& )  )
	{
		if( 0 == root )
			return;

		visitor( root->key, root->value );
		InorderVisitor( root->leftNode, visitor );
		InorderVisitor( root->rightNode, visitor );
	}

	/*
	* Implement postorder traversal
	*
	*/
	void PostOrderVisitor( pBSTNode root, void (*visitor)( const T&, const V& ) )
	{
		if( 0 == root )
			return;

		InorderVisitor( root->leftNode, visitor );		
		InorderVisitor( root->rightNode, visitor );
		visitor( root->key, root->value );
	}

protected:

	pBSTNode  m_root;

	size_t    m_size;
};


/*
* Test STL map
*
*/
void TestSTLMapBST()
{
	const int Len = 200000;
	//int key[Len];
	//int value[Len];

	int* key = new int[Len];
	int* value = new int[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 );

	delete [] key;
	delete [] value;

}




/*
* vistior function for output information when traversal tree
*
*/
template<class T, class V>
void Visitor( const T& key, const V& value )
{
	std::cout << "key: "  << key << "," <<"value: " << value << std::endl;
}


/*
* unit test
*
*/
void TestBST()
{
	const int Len = 200000;
	//int key[Len];
	//int value[Len];

	int* key = new int[Len];
	int* value = new int[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();

	BinarySearchTree<int, int> treeObj;
	for( int i = 0; i < Len; i++ )
	{
		treeObj.Insert( key[i], value[i] );
	}

	for( int i = 0; i < Len; i++ )
	{
		int* val = treeObj.Find( key[i] );
		assert( *val == value[i] );
	}

	int minKey = -1;
	int* minValue = treeObj.FinMin( minKey );
	assert( minKey == 0 );

	int maxKey = -1;
	int* maxValue = treeObj.FindMax( maxKey );
	assert( maxKey == Len - 1 );

	size_t size = treeObj.Size();
	assert(  size == Len );

	int flagCount = 0;
	for( int i = 0; i < Len; i++ )
	{
		if( !(i % 15) )
		{
			treeObj.Delete( i );
			int* val = treeObj.Find( i );
			assert( !val );

			flagCount++;
		}
	}

	unsigned long interval = GetTickCount() - start;
	printf( " binary search tree consume time is %d \n", interval );

	size = treeObj.Size();
	size_t count = treeObj.GetSize();

	BinarySearchTree<int, int> newTreeObj;
	for( int i = 0; i < 10; i++ )
	{
		newTreeObj.Insert( key[i], value[i] );
	}

	treeObj = newTreeObj;
	newTreeObj.Clear();

	std::cout<< "begin inorder traversal " << std::endl;
	treeObj.InorderVisitor( Visitor<int, int> );

	std::cout<< "begin postorder traversal " << std::endl;
	treeObj.PostOrderVisitor( Visitor<int, int> );

	std::cout<< "begin preorder traversal " << std::endl;
	treeObj.PreOrderVisitor( Visitor<int, int> );

	treeObj.Clear();


	delete [] key;
	delete [] value;
}


void TestBSTSuite()
{
	TestSTLMapBST();
	TestBST();
}



#endif 


泛型的Binary Search Tree的实现,并与STL map进行操作性能上的比较

标签:数据结构   performance   性能   

原文地址:http://blog.csdn.net/manthink2005/article/details/24634605

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!