AVL树要解决的问题
为了尽量降低二叉搜索树的高度,减少树的平均搜索长度。
AVL树定义
或者是空树。
或者是具有下列性质的二叉搜索树:它的左子树和右子树都是AVL树,且左子树和右子树的高度之差的绝对值不超过1。
NOTE:
AVL树种左子树和右子树高度的差值称为平衡因子,平衡因子的值只能为-1、0和1,如果平衡因子的绝对值大于1,这棵二叉搜索树就失去了平衡,不再是AVL树。
AVL树的高度保持在O(lgn),平均搜索长度也可保持在O(lgn).
AVL树实现
要让AVL树时时刻刻保持平衡,就要在AVL树出现不平衡时及时恢复平衡。
AVL树的不平衡一共有四种情况:
只要解决这四种基本情况就行了。
首先给出AVL树抽象数据类型和结点类。
#include <iostream>
using namespace std;
//AVL树结点类
template <class Type>
class AVLNode
{
public:
AVLNode() : left( NULL ), right( NULL ), balance( 0 ) {}
AVLNode( Type d, AVLNode* l = NULL, AVLNode* r = NULL )
: data( d ), left( l ), right( r ), balance( 0 ) {}
Type data;
AVLNode* left, *right;
int balance; //平衡因子
};
//AVL树定义
template <class Type>
class AVLTree
{
public:
AVLTree() : root( NULL ), shorter( true ) {} //构造一棵空AVLTree
AVLTree( Type ref ) : refValue( ref ), root( NULL ), shorter( true ) {} //指定输入终止标志的AVLTree
int Insert( Type x ) { int taller; return Insert( root, x, taller ); }
Type Min();
Type Max();
int Depth() const; //求树的高度
void Remove(const Type& x) { Remove( x, root, shorter ); }
private:
AVLNode<Type>* root; //根节点的指针
Type refValue; //插入结束的标志
int shorter;
protected:
int Insert( AVLNode<Type>* &tree, Type x, int &taller ); //插入
void RotateLeft( AVLNode<Type>* tree, AVLNode<Type>*& newTree ); //左单旋转
void RotateRight( AVLNode<Type>* tree, AVLNode<Type>*& newTree ); //右单旋转
void LeftBalance( AVLNode<Type>*& tree, int& taller ); //左平衡化
void RightBalance( AVLNode<Type>*& tree, int& taller ); //右平衡化
void Remove( const Type& x, AVLNode<Type>*& ptr, int& shorter ); //删除元素
AVLNode<Type>* Min( AVLNode<Type>* ptr );
AVLNode<Type>* Max( AVLNode<Type>* ptr );
template <class T>
friend istream& operator >>( istream& in, AVLTree<T>& tree );
template <class T>
friend ostream& operator <<( ostream& out, AVLTree<T>& tree );
void traverse( AVLNode<Type>* ptr, ostream& out ) const; //中序遍历
int Depth( AVLNode<Type>* l ) const;//求树高度
};
/*
* o
* o
* o 这种情况是左单旋转
*/
//右子树比左子树高,对以tree为根的AVL树做左单旋转,旋转后新根在newTree
template <class Type>
void AVLTree<Type>::RotateLeft( AVLNode<Type>* tree, AVLNode<Type>*& newTree )
{
newTree = tree->right; //新根为C
tree->right = newTree->left; //结点C的左子树转为结点A的右子树
newTree->left = tree; //结点A成为结点C的左子树
}
/*
* o
* o
*o 这种情况需要右单旋转
*/
//左子树比右子树高,对以tree为根的AVL树做右单旋转,旋转后新根在newTree
//是左单旋转的镜象
template <class Type>
void AVLTree<Type>::RotateRight( AVLNode<Type>* tree, AVLNode<Type>*& newTree )
{
newTree = tree->left; //新根为B
tree->left = newTree->right; //结点B的右子树转为结点A的左子树
newTree->right = tree; //结点A成为结点B的右子树
}
/*
* o
*o
* o 这种情况需要先左后右双旋转
*/
//
template <class Type>
void AVLTree<Type>::LeftBalance( AVLNode<Type>*& Tree, int& taller )
{
AVLNode<Type>* rightsub, *leftsub = Tree->left;
switch( leftsub->balance )
{
case -1: // '/'型 需要进行右单旋转
Tree->balance = leftsub->balance = 0; //右单旋转之后Tree和leftsub平衡因子都为0
RotateRight( Tree, Tree );
taller = 0;
break;
case 0:
cout << "LeftBalance error : Tree already balanced.\n" << endl;
break;
case 1: // '<'型 需要进行先左后右双旋转
rightsub = leftsub->right; //设置调节完成之后的平衡因子
switch( rightsub->balance )
{
case -1:
Tree->balance = 1;
leftsub->balance = 0;
break;
case 0:
Tree->balance = leftsub->balance = 0;
break;
case 1:
Tree->balance = 0;
leftsub->balance = -1;
break;
}
rightsub->balance = 0;
RotateLeft( leftsub, Tree->left );
RotateRight( Tree, Tree );
taller = 0;
}
}
/*
* o
* o
* o 这种情况需要先右后左双旋转
*/
template <class Type>
void AVLTree<Type>::RightBalance( AVLNode<Type>*& Tree, int& taller )
{
AVLNode<Type>* rightsub = Tree->right, *leftsub;
switch ( rightsub->balance )
{
case 1:
Tree->balance = rightsub->balance = 0;
RotateLeft( Tree, Tree );
taller = 0;
break;
case 0:
cout << "RightBalance error: Tree already balanced.\n" << endl;
break;
case -1:
leftsub = rightsub->left;
switch( leftsub->balance )
{
case 1:
Tree->balance = -1;
rightsub->balance = 0;
break;
case 0:
Tree->balance = rightsub->balance = 0;
break;
case -1:
Tree->balance = 0;
rightsub->balance = 1;
break;
}
leftsub->balance = 0;
RotateRight( rightsub, Tree->right );
RotateLeft( Tree, Tree );
taller = 0;
}
}
插入
//插入
//在以tree为根的AVL树中插入新元素x,如果插入成功,taller返回1,否则返回0
template <class Type>
int AVLTree<Type>::Insert( AVLNode<Type>*& tree, Type x, int &taller )
{
int success;
if ( tree == NULL )
{
tree = new AVLNode<Type>( x );
success = (tree != NULL ? 1 : 0);
if ( success )
taller = 1;
}
else if ( x < tree->data ) //在左子树插入
{
success = Insert( tree->left, x, taller );
if ( taller )
{
switch ( tree->balance )
{
case -1:
LeftBalance( tree, taller );
break;
case 0:
tree->balance = -1;
break;
case 1:
tree->balance = 0;
taller = 0;
break;
}
}
}
else //在右子树插入
{
success = Insert( tree->right, x, taller );
if ( taller )
{
switch( tree->balance )
{
case -1:
tree->balance = 0;
taller = 0;
break;
case 0:
tree->balance = 1;
break;
case 1:
RightBalance( tree, taller );
break;
}
}
return success;
}
}
最大、最小值
template <class Type>
AVLNode<Type>* AVLTree<Type>::Min( AVLNode<Type>* ptr )
{
if ( ptr == NULL )
return NULL;
while ( ptr->left != NULL )
{
ptr = ptr->left;
}
return ptr;
}
template <class Type>
AVLNode<Type>* AVLTree<Type>::Max( AVLNode<Type>* ptr )
{
if ( ptr == NULL )
return NULL;
while ( ptr->right != NULL )
{
ptr = ptr->right;
}
return ptr;
}
template <class Type>
Type AVLTree<Type>::Min()
{
AVLNode<Type>* temp;
temp = Min( root );
return temp == NULL ? refValue : temp->data;
}
template <class Type>
Type AVLTree<Type>::Max()
{
AVLNode<Type>* temp;
temp = Max( root );
return temp == NULL ? refValue : temp->data;
}
删除
template <class Type>
void AVLTree<Type>::Remove( const Type& x, AVLNode<Type>*& ptr, int& shorter )
{
int taller;
if ( ptr == NULL )
return ;
if ( x == ptr->data )
{
//情况1:如果被删元素有两个子女,将被删元素转移到子女上,将情况转换为2
if ( ptr->left != NULL && ptr->right != NULL )
{
AVLNode<Type>* leftMax = Max( ptr->left ); //左孩子中最大的
ptr->data = leftMax->data; //中序遍历直接前驱的值赋给要删结点
Remove( leftMax->data, ptr->left, shorter ); //在左子树中删除中序遍历中的直接前驱
}
//如果被删元素最多有一个子女,删除结点,修改父结点指向
else
{
//被删结点两个子女都为空,直接删除
if ( ptr->left == NULL && ptr->right == NULL )
{
delete ptr;
ptr = NULL;
}
//被删结点的左子女为空,将右子女赋值给要删结点。
else if ( ptr->left == NULL )
{
AVLNode<Type>* temp = ptr;
ptr = temp->right;
delete temp;
shorter = true;
}
//被删结点的右子女为空,将左子女赋值给要删结点。
else
{
AVLNode<Type>* temp = ptr;
ptr = temp->left;
delete temp;
shorter = true;
}
}
}
else if ( x < ptr->data )
{
Remove( x, ptr->left, shorter );
if ( shorter )
{
switch ( ptr->balance )
{
case 1:
ptr->balance = 0;
shorter = true;
break;
case 0:
ptr->balance = -1;
shorter = false;
break;
case -1:
RightBalance( ptr, taller );
if ( ptr->right->balance == 0 )
shorter = false;
else
shorter = true;
break;
}
}
}
else
{
Remove( x, ptr->right, shorter );
if ( shorter )
{
switch ( ptr->balance )
{
case 1:
LeftBalance( ptr, taller );
if ( ptr->left->balance = 0 )
shorter = false;
else
shorter = true;
break;
case 0:
ptr->balance = 1;
shorter = false;
break;
case -1:
ptr->balance = 0;
shorter = true;
break;
}
}
}
}
输入输出
template <class Type>
istream& operator >>( istream& in, AVLTree<Type> &tree )
{
Type item;
cout << "Construct AVL tree:\n";
cout << " Input Data( end with " << tree.refValue << " ): ";
in >> item;
while ( item != tree.refValue )
{
tree.Insert( item );
in >> item;
}
return in;
}
template <class Type>
ostream& operator <<( ostream& out, AVLTree<Type>& tree )
{
cout << "Inorder traversal of AVL tree.\n";
tree.traverse( tree.root, out );
return out;
}
//中序遍历
template <class Type>
void AVLTree<Type>::traverse( AVLNode<Type>* ptr, ostream& out ) const
{
if ( ptr != NULL )
{
traverse( ptr->left, out );
out << ptr->data << " " ;
traverse( ptr->right, out );
}
}
测试
int main( void )
{
AVLTree<int> tree(0);
cin >> tree;
cout << tree << endl;
tree.Remove( 7 );
cout << tree << endl;
cout << tree.Min() << endl;
cout << tree.Max() << endl;
return 0;
}
563

被折叠的 条评论
为什么被折叠?



