AVL树

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;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值