AVL树

以下图的平衡因子统一为左子树高度减去右子树高度。

附上:单个节点声明的代码
struct AVLTreeNode
{
    AVLTreeNode(const K& key, const V& value)
    : _pLeft(NULL)
    , _pRight(NULL)
    , _pParent(NULL)
    , _key(key)
    , _value(value)
    , _bf(0)
    {}


    AVLTreeNode<K, V> *_pLeft;
    AVLTreeNode<K, V> *_pRight;
    AVLTreeNode<K, V> *_pParent;
    K _key;
    V _value;
    int _bf;       // 平衡因子:right-left
};
左单旋 (右右 - 在较高右子树的右侧插入节点)

这里写图片描述

具体列子

这里写图片描述

分析

如图能引发左单旋,那必定是在引起不平衡的节点的较高右字树的右侧插入,至于这个点是在节点C的左边插入还是右边插入都没有关系,都可以通过左旋转达到平衡,这个平衡后的图如上所示,真正发生变化的点,一个SubR一个引发不平衡的节点,而再引发旋转后这俩个点都平衡了,平衡因子为0。

附上 - 左单旋代码:
void _RotateL(Node* pParent)
    {
        if (pParent)
        {
            Node *pPParent = pParent->_pParent;
            Node * pSubR = pParent->_pRight;
            Node * pSubRL = pParent->_pLeft;
            if (pSubRL)
            {
                pSubRL->_pParent = pParent;
            }
            pParent->_pRight = pSubRL;
            pSubR->_pLeft = pParent;
            pParent->_pParent = pSubR;
            pSubR->_pParent = pPParent;
            if (pPParent == NULL)
            {
                _pRoot = pSubR;
            }
            else
            {
                if (pPParent->_pLeft == pParent) pPParent->_pLeft = pSubR;
                else
                    pPParent->_pRight = pSubR;
            }
            pSubR->_bf = 0;
            pParent->_bf = 0;
        }
    }
右单旋 (左左-在较高左子树中的左侧插入节点)
图示

这里写图片描述
这里写图片描述

附上 -右单旋代码:
void _RotateR(Node* pParent)
    {
        if (pParent)
        {
            Node*pPParent = pParent->_pParent;
            Node*pSubL = pParent->_pLeft;
            Node*pSubLR = pSubL->_pRight;
            if (pSubLR)
            {
                pSubLR->_pParent = pParent;
            }
            pParent->_pLeft = pSubLR;
            pParent->_pParent = pSubL;
            pSubL->_pRight = pParent;
            pSubL->_pParent = pPParent;  
            if (pPParent==NULL)
            {
                _pRoot = pSubL;
            }
            else
            {
                if (pParent->_pRight == pParent)pParent->_pRight = pSubL;
                else
                    pParent->_pLeft = pSubL;
            }
            pSubL->_bf = 0;
            pParent->_bf = 0;

        }
    }
右左双旋(右左-在较高右子树的左侧插入)
分析

如下面这个图,这里双旋有三种情况:
1.h为0的时候,那么 10 无左子树,30无右子树,20这个节点必定是新增节点,因为20和它子树高度和为h , h 为0说明20不存在,它这里是新增节点。那这个时候20的平衡因子是0。
2.当新增节点在20这个节点的左子树的情况下,20 节点为-1。这个时候双旋完后 , b的高度新增完后为h , 它给了10之后,10的节点的平衡因子平衡了,但是 c 跟了30,30 此时 平衡因子为1。
3.当新增节点在C,20节点平衡因子为1。这时候双旋完后,C跟了30,C的高度新增后为 h ,那么 30此时是平衡的,相反 高度 为 h-1 的 b跟了10,那么此时10的平衡因子是-1。

图示

这里写图片描述
这里写图片描述
这里写图片描述

void _RotateRL(Node* pParent)
    {
        Node *PsubR = pParent->_pRight;
        Node* pSubRL = PsubR->_pLeft;
        int bf = pSubRL->_bf;
        _RotateR(pParent->_pRight);
        _Rotate(pParent);
        if (bf == -1) pParent->_bf = 1;
        else PsubR->_bf = -1;
    }
左右双旋(左右-在较高左子树的右侧插入)

这里写图片描述这里写图片描述这里写图片描述

void _RotateLR(Node* pParent)
    {
        Node * PsubL = pParent->_pLeft;
        Node * psubLR = PsubL->_pRight;
        int bf = psubLR->_bf;
        _RotateL(pParent->_pLeft);
        _RotateR(pParent);
        if (bf == 1) pParent->_bf = -1;
        else PsubL->_bf = 1;
    }

整个AVL树的实现

#include<iostream>
#include<assert.h>
using namespace std;
template<class K , class V>
struct AVLTreeNode
{
public:
    using Node = AVLTreeNode<K, V>;
    AVLTreeNode(const K & key, const V & value)
        :_pLeft(NULL), _pRight(NULL), _pParent(NULL), _Key(key), _value(value), _bf(0)
    {}


    Node * _pLeft;
    Node * _pRight;
    Node * _pParent;
    K _Key;
    V _value;
    int _bf;
};
template<class K , class V>
class AVLTree
{
    typedef AVLTreeNode<K,V> Node;
public:
    AVLTree()
        :_root(nullptr)
    {}
    AVLTree(const K arr[], size_t size)
    {
        for (size_t idx = 0 l idx < size; ++idx)
        {
            Insert(idx, arr[idx]);
        }
    }
    bool Insert(const K& key, const V & value)
    {
        if (nullptr == _root)
        {
            _root = new Node(key, value);
            return false;
        }
        else
        {
            Node * pCur = _root;
            Node * parent = nullptr;
            while (pCur)
            {
                if (key < pCur->_Key)
                {
                    parent = pCur;
                    pCur = pCur->_pLeft;
                }
                else if (key > pCur->_Key)
                {
                    parent = pCur;
                    pCur = pCur->_pRight;
                }
                else
                {
                    return false;
                }
            }
            pCur = new Node(key, value);
            if (key < parent->_Key)
            {
                parent->_pLeft = pCur;
                pCur->_pParent = parent;
            }
            else
            {
                parent->_pRight = pCur;
                pCur->_pParent = parent;
            }
            while (parent)
            {
                if (pCur == parent->_pLeft)
                    parent->_bf--;
                else
                    parent->_bf++;
                if (parent->_bf == 0)
                    return true;
                else if (parent->_bf == -1 || parent->_bf == 1)
                {
                    pCur = parent;
                    parent = pCur->_pParent;

                }
                else if (parent->_bf==-2||parent->_bf == 2)
                {
                    /*旋转*/
                    if (parent->_bf == 2 && parent->_pRight->_bf == 1) // bf==2 说明parent的右子树高 , 那么我们可以查看右子树的bf的值,bf==1在右子树右侧插入,bf==-1 在右子树左侧插入
                        RotateL(parent);
                    else if (parent->_bf == 2 && parent->_pRight->_bf == -1)
                        RotateRL(parent);
                    else if (parent->_bf == -2 && parent->_pLeft->_bf == -1)
                        RotateR(parent);
                    else if (parent->_bf == -2 && parent->_pLeft->_bf == 1)
                        RotateLR(parent);
                    break;
                }
                else
                {
                    cerr << "有bug!!!!在插入的时候" << endl;
                    assert(false);
                }
            }
        }
    }
protected:
    void RotateL(Node * parent) // 向左旋转
    {
        Node*SubR = parent->_pRight;
        Node*SubRL = SubR->_pLeft;
        Node*grandfather = parent->_pParent;
        if (SubRL)
            SubRL->_pParent = parent;
        parent->_pRight = SubRL;
        SubR->_pLeft = parent;
        if (grandfather)
        {
            if (grandfather->_pLeft == parent)
                grandfather->_pLeft = SubR;
            else
                grandfather->_pRight = SubR;
        }
        else
        {
            _root = SubR;
            SubR->_pParent = NULL;
        }
        parent->_pParent = SubR;
        SubR->_pParent = grandfather;
        parent->_bf = 0;
        SubR->_bf = 0;
    }
    void RotateR(Node * parent) //向右旋转
    {
        Node * SubL = parent->_pLeft;
        Node * SubLR = SubL->_pRight;
        Node * grandfather = parent->_pParent;
        if (SubLR)
            SubLR->_pParent = parent;
        parent->_pLeft = SubLR;
        SubL->_pRight = parent;
        if (grandfather)
        {
            if (grandfather->_pLeft == parent)
                grandfather->_pLeft = SubL;
            else
                grandfather->_pRight = SubL;
        }
        else
        {
            _root = SubL;
            SubL->_pParent = NULL;
        }
        parent->_pParent = SubL;
        SubL->_pParent = grandfather;
        parent->_bf = 0;
        SubL->_bf = 0;
    }
    void RotateLR(Node* parent)
    {
        Node*SubL = parent->_pLeft;
        Node*SubLR = SubL->_pRight;
        int bf = SubLR->_bf;
        RotateL(SubL);
        RotateR(parent);
        if (bf == 1)
            SubL->_bf = -1;
        if (bf == -1)
            parent->_bf = 1;
    }
    void RotateRL(Node* parent)
    {
        Node*SubR = parent->_pRight;
        Node*SubRL = SubR->_pLeft;
        int bf = SubRL->_bf;
        RotateR(SubR);
        RotateL(parent);
        if (bf == 1)
            parent->_bf = -1;
        if (bf == -1)
            SubR->_bf = 1;
    }
public:
     Node * const GetRoot()
    {
        return _root;
    }
    void Inorder(Node*Root)
    {
        if (Root==NULL)
            return;
        Inorder(Root->_pLeft);
        cout << Root->_Key<<" " ;
        Inorder(Root->_pRight);
    }
    bool IsBalance(Node*Root)
    {
        int Height=0;
        return _IsBalance(Root, Height);
    }
    private:
    bool _IsBalance(Node*Root, int & Height)
    {
        if (Root == NULL)
        {
            Height = 0;
            return true;
        }
        int left = 0;
        if (!_IsBalance(Root->_pLeft, left))
            return false;
        int right = 0;
        if (!_IsBalance(Root->_pRight, right))
            return false;
        Height = (left > right) ? left + 1 : right + 1;
        return abs(left-right) < 2;
    }

private:
    Node * _root;
};
void TesTAVL()
{
    int arr[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
    AVLTree<int,int> Tree;
    for (int i = 0; i<sizeof(arr) / sizeof(arr[0]);++i)
    {
        Tree.Insert(arr[i],i);
    }
     AVLTreeNode<int, int> * Root = Tree.GetRoot();
    Tree.Inorder(Root);
    if (Tree.IsBalance(Root))
        co(left-right) < 2;
    }ut << "AVL树平衡的" << endl;
}
int main()
{
    TesTAVL();
    return 0;
}

判断平衡的方法

方法1 时间复杂度 O(N^2)
bool  Height (Node * Root)
{
     if(Root == NULL )
        return 0;
     if(Root->_pleft==NULL&&Root->_pRight==NULL)
     {
           return 1;
     }
     int left = Height(Root->_pleft);
     int Right = Height(Root->_pRight);
     return (left>right)? left+1: right+1;
}
bool IsBalance(Node*Root)
{
      if(Root==NULL)
         true;
      int left = Height(Root->_pLeft);
      int Right = Height(Root->_pRight);
     return abs(left-Right)<2&&IsBalance(Root->_pLeft)&&IsBalance(Root->_pRight);
}
方法2 时间复杂度O(N)
bool IsBalance(Node*Root)
    {
        int Height=0;
        return _IsBalance(Root, Height);
    }
    private:
    bool _IsBalance(Node*Root, int & Height)
    {
        if (Root == NULL)
        {
            Height = 0;
            return true;
        }
        int left = 0;
        if (!_IsBalance(Root->_pLeft, left))
            return false;
        int right = 0;
        if (!_IsBalance(Root->_pRight, right))
            return false;
        Height = (left > right) ? left + 1 : right + 1;
        return abs(left-right) < 2;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值