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

来源:互联网 发布:剑网三网络助手 编辑:程序博客网 时间:2024/06/12 20:41

1.问题描述:

   1)AVL tree是一种自平衡树。它通过左右子树的高度差来控制树的平衡,当高度差是不大于1的时候,认为树是平衡的。树的平衡保证了树在极端情况下
         (输入序列不够随机)的性能。很显然当左右子树高度平衡,保证了任何插入,删除,查找操作平均性能呢个,当不平衡时(有的子树很高),当
          要操作的元素在这个子树时,性能会很差;

  2)AVL tree 和Red black tree 都是一种平衡树,它的操作的时间复杂度是:O(lgN) ,N是树的节点的数目;
  3)本文实现了AVL Tree, 并和STL map做了操作性能上的比较,结果发现:AVL tree 的消耗时间稍微多一些大约比Red Black tree多出8%;
  4)本文没有封装迭代器(iterator),随后可以完成这个工作;
  5)由于表达力有限,关于AVL tree的算法详述请参见维基百科;


2:程序代码

#ifndef _AVL_TREE_H_#define _AVL_TREE_H_#include <algorithm>#include <functional>#include <map>#include "windows.h"#define Max( a, b ) ( (a > b )? (a):(b))template<class T, class V, class Cmp = std::less<T> > class AVLTree{public:typedef struct tagAVLNode{T      key;V      data;int    height;tagAVLNode* leftChild;tagAVLNode* rightChild;tagAVLNode():key(), data(), height(0),          leftChild(0), rightChild(0){}tagAVLNode( const T& _key, const V& _data ):key( _key ),  data(_data),                         height(1), leftChild(0), rightChild(0){}~tagAVLNode(){key.~T();data.~V();}}AVLNode, *pAVLNode;AVLTree():m_root(0), m_size(0){}/** Copy constructor**/AVLTree( const AVLTree& rhs ){Clear();m_root = Clone( rhs.m_root );}/** Destructor**/~AVLTree(){Clear();}/** overload assignment operator **/AVLTree& operator = ( const AVLTree& rhs ){if( this != &rhs ){Clear();m_root = Clone( rhs.m_root );}return m_root;}/** Retrieve the number of node for the given avl tree**/size_t Size() const {return m_size;}/** Clear all node **/void Clear(){Clear( m_root );}/** Insert key value pair to avl tree**/void Insert( const T& _key, const V& _value ){m_root = Insert( m_root, _key, _value );}/** Delete node for given key**/void Delete( const T& _key ){m_root = Delete( m_root, _key );}/** Find the pointer of value for given key**/V*  Find( const T& _key ){return Find( m_root, _key );}/** Find the min value**/V& FindMin( T& key ){pAVLNode node = FindMin( m_root );if( node ){key = node->key;return node->data;}}/** Find the max value **/V& FindMax( T& key ){pAVLNode node = FindMax( m_root );if( node ){key = node->key;return node->data;}}protected:/** Clone avl tree **/pAVLNode Clone( pAVLNode root ){if( 0 == root )return 0;pAVLNode newNode = new AVLNode( root->key, root->data );newNode->leftChild = Clone( root->leftChild );newNode->rightChild = Clone( root->rightChild );return newNode;}/****/size_t Size( pAVLNode root ) const {if( 0 == root )return 0;return 1 + Size( root->leftChild ) + Size( root->rightChild );}/****/int GetBalance( pAVLNode root ){if( 0 == root )return 0;return GetHeight( root->leftChild )  - GetHeight( root->rightChild );}/****/int GetHeight( pAVLNode root ){if( 0 == root )return 0;return root->height;}/** Left Rotate**/pAVLNode LeftRotate( pAVLNode node ){pAVLNode y = node->rightChild;node->rightChild = y->leftChild;y->leftChild = node;node->height = Max( GetHeight( node->leftChild ), GetHeight( node->rightChild ) ) + 1; // important y->height = Max( GetHeight( y->leftChild ), GetHeight( y->rightChild ) ) + 1;return y;}/** Right rotate**/pAVLNode RightRotate( pAVLNode node ){pAVLNode y = node->leftChild;node->leftChild = y->rightChild;y->rightChild = node;node->height = Max( GetHeight( node->leftChild ), GetHeight( node->rightChild ) ) + 1; // important y->height = Max( GetHeight( y->leftChild ), GetHeight( y->rightChild )) + 1;return y;}/** Clear all node **/void Clear( pAVLNode root ){if( 0 == root )return;Clear( root->leftChild );Clear( root->rightChild );delete root;root = 0;}/** Insert key value pair to avl tree**/pAVLNode Insert( pAVLNode root, const T& _key, const V& _value ){if( 0 == root ){root = new AVLNode( _key, _value );m_size++;return root;}else if( root->key >  _key  ){root->leftChild = Insert( root->leftChild, _key, _value );}else if( root->key < _key ){root->rightChild = Insert( root->rightChild, _key, _value );}// update heightroot->height = Max( GetHeight( root->leftChild ), GetHeight( root->rightChild ) );// rebalance treeint balance = GetBalance( root );if( balance > 1 )  //left child tree more high {if( _key < root->leftChild->key  ) //left left case{return RightRotate( root );}else if( _key > root->leftChild->key ) // left right case{root->leftChild = LeftRotate( root->leftChild );return RightRotate( root );}}else if( balance <- 1 )  // right child tree more high{if( _key > root->rightChild->key )  // right right case{return LeftRotate( root );}else if( _key < root->rightChild->key ) // right left case{root->rightChild = RightRotate( root->rightChild );LeftRotate( root );}}return root;}/** Delete node for given key**/pAVLNode Delete( pAVLNode root, const T& _key ){if( 0 == root )return 0;if( root->key < _key ){root->rightChild = Delete( root->rightChild, _key );}else if( root->key > _key ){root->leftChild = Delete( root->leftChild, _key );}else{if( root->leftChild ){if( root->rightChild ) // left right child exist case 1{pAVLNode minNode = FindMin( root->rightChild );root->key = minNode->key;root->data = minNode->data;root->rightChild = Delete( root->rightChild, minNode->key );}else                    // only left child exist{pAVLNode cur = root;root = root->leftChild;delete cur;cur = 0;}}else{if( root->rightChild )   // only right child exist{pAVLNode minNode = FindMin( root->rightChild );root->key = minNode->key;root->data = minNode->data;root->rightChild = Delete( root->rightChild, minNode->key );}else                    // no child exist{delete root;root = 0;}}m_size--;}if( 0 == root )return 0;// update heightroot->height = Max( GetHeight( root->leftChild ), GetHeight( root->leftChild ) ) + 1;//rebalance treeint balance = GetBalance( root );if( balance > 1 && GetBalance( root->leftChild ) >= 0 ){return RightRotate( root );}if( balance > 1 && GetBalance( root->leftChild ) < 0 ){root->leftChild = LeftRotate( root->leftChild );return RightRotate( root );}if( balance < -1 && GetBalance( root->rightChild ) <= 0 ){return LeftRotate( root );}if( balance < -1 && GetBalance( root->rightChild ) > 0 ){root->rightChild = RightRotate( root->rightChild );return LeftRotate( root );}return root;}/** Find node for given key**/V*  Find( pAVLNode root, const T& _key ){if( 0 == root ){return 0;}if( root->key > _key ){return Find( root->leftChild, _key );}else if( root->key < _key ){return Find( root->rightChild, _key );}else {return &root->data;}}/** Find the node of min key value **/pAVLNode FindMin( pAVLNode root ){if( 0 == root )return 0;pAVLNode cur = root;while( root->leftChild ){cur = root->leftChild;root = cur;}return cur;}/** Find the node of max key value **/pAVLNode FindMax( pAVLNode root ){if( 0 == root )return 0;pAVLNode cur = root;while( root->rightChild ){cur = root->rightChild;root = cur;}return cur;}protected:pAVLNode  m_root;size_t    m_size;};/** Test map**/void TestSTLMap(){const int Len = 100000;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> mapObj;for( int i = 0; i < Len; i++ ){mapObj.insert( std::make_pair( key[i], value[i] ) );}for( int i = 0; i < Len; i++ ){std::map<int, int>::iterator iter = mapObj.find( key[i] );assert( iter != mapObj.end() );assert( iter->second == value[i] );}for( int i = 0; i < Len; i++ ){if( !(i % 15) ){mapObj.erase( key[i] );std::map<int, int>::iterator iter = mapObj.find( key[i] );assert( iter == mapObj.end() );}}unsigned long interval = GetTickCount() - start;printf( " map consume time is %d \n", interval );}/** Test avl tree**/void TestAVLTree(){const int Len = 100000;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();AVLTree<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.FindMin( minKey );assert( minKey == 0 );int maxKey = -1;int maxValue = treeObj.FindMax( maxKey );assert( maxKey == Len - 1 );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 );}}size = treeObj.Size();unsigned long interval = GetTickCount() - start;printf( " avl tree consume time is %d \n", interval );}/** Test interface**/void TestSuit(){TestSTLMap();TestAVLTree();}#endif 


0 0
原创粉丝点击