AVL树是带有平衡条件的二叉查找树,能保证树的深度是O(logN)。平衡条件--每个节点的左子树和右子树的高度最多差1。
*证明:假设高度为h且节点数最少的AVL树中,节点数为S(h)。
树由根节点,左子树和右子树组成。树的高度为h,所以必然有一个子树的高度为h-1,为了达到最少节点的目的且满足左右子树的高度最多差1的条件,另外一棵子树高度则为(h-1)-1 =h-2。树是满足最少节点数的,所以左右子树的节点数也应该对应的是满足高度为h-1和h-2的最少节点数,S(h-1)和S(h-2)
则有 S(h) = S(h-1) + S(h-2) + 1,其中S(0) = 1,S(1) = 2。式子稍作变换,S(h)+1= ( S(h-1)+1) + ( S(h-2)+1),即是斐波那契数列形式。
那么高度为h的AVL树的节点数 N >= S(h) = Ω(φ^h) ---> h = O( logN).
*旋转
树的平衡靠旋转来维持。
把进行插入操作后必须重新平衡的节点叫做a。当树的高度不平衡时,a点的两颗子树的高度差为2,不平衡可能出现在下面四种情况中:
1.对a的左儿子的左子树进行一次插入。
2.对a的左儿子的右子树进行一次插入。
3.对a的右儿子的左子树进行一次插入。
4.对a的右儿子的右子树进行一次插入。
其中1,4两种情况是对称的,2,3是对称的。
第一种情况是插入到“外边”的情况(1,4),通过单旋转进行调整。
第二种情况是插入到“内边”的情况(2,3),通过双旋转进行调整。
template<typename T>
class AvlTree
{
struct Node;
typedef Node * Position;
public:
AvlTree() { root_ = NULL;}
void insert( const T &x) { insert( x, root_);}
void remove( const T &x) { remove( x, root_);}
Position find( const T &x) { return find( x, root_);}
Position findMin( ) { return findMin( root_);}
Position findMax( ) { return findMax( root_);}
int height() { return height(root_);}
virtual ~AvlTree() { makeEmpty( root_);}
private:
struct Node
{
T data;
Node * left;
Node * right;
int height;
};
Position root_;
void makeEmpty( Position & t)
{
if( t==NULL) return;
makeEmpty( t->left);
makeEmpty( t->right);
delete t;
}
int height( const Position & t) const
{
if ( t==NULL) return -1;
else return t->height;
}
Position find( const T &x, const Position & t) const
{
if ( t==NULL) return NULL;
if( x<t->data) return find( x, t->left);
else if( x>t->data) return find( x, t->right);
else return t;
}
Position findMin( const Position &t) const
{
if( t==NULL) return NULL;
if( t->left!=NULL) return findMin( t->left);
else return t;
}
Position findMax( const Position &t) const
{
if( t==NULL) return NULL;
if( t->right!=NULL) return findMax( t->right);
else return t;
}
void singleRotateWithLeft( Position & t)
{
Position tmp = t;
t = t->left;
tmp->left = t->right;
t->right = tmp;
tmp->height = max( height( tmp->left), height( tmp->right)) +1;
t->height = max( height( t->left), height( t->right)) +1;
}
void singleRotateWithRight( Position & t)
{
Position tmp = t;
t = t->right;
tmp->right = t->left;
t->left = tmp;
tmp->height = max( height( tmp->left), height( tmp->right))+1;
t->height = max( height( t->left), height( t->right))+1;
}
void doubleRotateWithLeft( Position & t)
{
singleRotateWithRight( t->left);
singleRotateWithLeft( t);
}
void doubleRotateWithRight( Position & t)
{
singleRotateWithLeft( t->right);
singleRotateWithRight( t);
}
void rotate( Position & t)
{
if( !t) return;
int dist = height( t->left) - height( t->right); // 左右子树高度差
if( dist<=1 && dist>=-1) return;
if( dist == 2) // 左子树高
{
if( height( t->left->left) > height( t->left->right)) //外边节点高出,单旋
singleRotateWithLeft(t);
else //内边节点高出,双旋
doubleRotateWithLeft(t);
}
else if ( dist == -2) //右子树高
{
if( height( t->right->right)> height( t->right->left)) //外边节点高出,单旋
singleRotateWithRight(t);
else //内边节点高出,双旋
doubleRotateWithRight(t);
}
}
void insert( const T & x, Position & t)
{
if( t==NULL)
{
t = new Node;
t->data = x;
t->left = t->right = NULL;
t->height = 0;
return;
}
if( x < t->data)
insert( x, t->left);
else if( x > t->data)
insert( x, t->right);
t->height = max( height(t->left), height( t->right)) + 1; //更新高度
rotate(t);
}
void remove( const T & x, Position & t)
{
if( t==NULL) return;
if( x < t->data)
remove( x, t->left);
else if ( x > t->data)
remove( x, t->right);
else if( t->left && t->right)
{
Position tmp;
switch( x%2) //左右子树同时存在,查找左子树最大节点或者右子树最小节点替换
{
case 0:
tmp = findMin( t->right);
t->data = tmp->data;
remove( t->data, t->right);
break;
case 1:
tmp = findMax( t->left);
t->data = tmp->data;
remove( t->data, t->left);
break;
}
}
else
{
Position tmp = t;
t = t->left ? t->left : t->right;
delete tmp;
}
if( t)
t->height = max( height( t->left), height( t->right))+1; //更新高度
else return;
rotate( t);
}
};
参考《数据结构与算法分析-c++语言描述》-Mark Allen Weiss