平衡二叉树

         AVL树是带有平衡条件的二叉查找树,能保证树的深度是O(logN)。平衡条件--每个节点的左子树和右子树的高度最多差1

        *证明:假设高度为h且节点数最少的AVL树中,节点数为S(h) 

          树由根节点,左子树和右子树组成。树的高度为h,所以必然有一个子树的高度为h-1,为了达到最少节点的目的且满足左右子树的高度最多差1的条件,另外一棵子树高度则为(h-1)-1 =h-2。树是满足最少节点数的,所以左右子树的节点数也应该对应的是满足高度为h-1h-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),即是斐波那契数列形式。

       那么高度为hAVL树的节点数 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值