平衡二叉树

来源:互联网 发布:剑三成女金发脸型数据 编辑:程序博客网 时间:2024/05/14 14:24

         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

0 0