AVL树的实现

来源:互联网 发布:构建开放数据生态圈 编辑:程序博客网 时间:2024/05/20 06:49

AVL树:
AVL树也成为平衡二叉树,它是这样定义的:
一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:
1、它的左右子树都是AVL树
2、左子树和右子树高度之差(简称平衡因子)的绝对值不超过1(-1、0、1)


AVL树的插入:
在插入节点后会造成父节点的平衡因子发生改变,需要从下往上更新平衡因子,若某一节点的平衡因子的绝对值大于1,说明以这个结点为根的树已经不平衡,此时就要去通过旋转来让数重新达到平衡状态。

旋转规则:
左单旋:在较高右子树的右侧插入了结点
右单旋:在较高左子树的左侧插入了结点

先左后右:在较高左子树的右侧插入了结点
先右后左:在较高右子树的左侧插入了结点

对于较高子树的理解:
较高子树就是不平衡树中的高度较大的子树。

下面是通过右左旋转达到平衡和通过左旋转达到平衡的例子:

下面是通过左右旋转达到平衡和通过右旋转达到平衡的例子:

通过上面的例子我们可以得到以下结论:
当一棵树不平衡时,如果这棵树根节点和其平衡因子不为0的结点的平衡因子符号相同则通过一次旋转即可重新平衡,否则就需要两次旋转。
根为2,子节点为1,通过左旋转即可平衡
根为2,子节点为-1,通过右左旋转才能平衡
根为-2,子节点为1,通过左右旋转才能平衡
根为-2,子节点为-1,通过右旋转即可平衡

注意:在旋转完成之后记得要把平衡因子修改为适当的值,可以通过画出图片做以分析,得到规律


代码:

#include<iostream>#include<windows.h>using namespace std;template<typename K, typename V>struct AVLTreeNode{    AVLTreeNode()    {}    AVLTreeNode(const K& _key, const V& _value = V())        : key(_key)        , value(_value)        , bf(0)        , pLeft(NULL)        , pRight(NULL)        , pParent(NULL)    {}    K key;    V value;    int bf;    AVLTreeNode *pLeft;    AVLTreeNode *pRight;    AVLTreeNode *pParent;};template<typename K, typename V>class AVLTree{    typedef AVLTreeNode<K, V> Node;public:    AVLTree()        :pRoot(NULL)    {}    bool Inserter(const K& _key)    {        //        Node* pCur = pRoot;        Node* parent = NULL;        if (NULL == pRoot)        {            pRoot = new Node(_key);            return true;        }        else        {            //找到插入位置            while (pCur)            {                if (pCur->key < _key)                {                    parent = pCur;                    pCur = pCur->pRight;                }                else if (pCur->key > _key)                {                    parent = pCur;                    pCur = pCur->pLeft;                }                else                    return false;            }            //插入结点            pCur = new Node(_key);            if (parent->key > _key)            {                parent->pLeft = pCur;            }            else                parent->pRight = pCur;            pCur->pParent = parent;        }        //自下向上更新平衡因子        while (parent)        {            //更新当前结点父节点的平衡因子            if (parent->pLeft == pCur)            {                parent->bf--;            }            else            {                parent->bf++;            }            //如果其父节点的平衡因子为0,则说明达到平衡            if (0 == parent->bf)            {                break;            }            //如果是1,则继续向上更新            else if (1 == parent->bf || -1 == parent->bf)            {                pCur = parent;                parent = pCur->pParent;            }            //不是1,就可能是+-2,此时子树不平衡需要调整            //一旦parent的因子绝对值==2,说明其需要调整,此时较高子树是相对于它而言的            else            {                //右子树高                if (parent->bf == 2)                {                    //右子树的右侧高                    if (pCur->bf == 1)                    {                        //左旋转                        RotateLeft(parent);                        break;                    }                    //右子树的左侧高                    else                    {                        //右左旋转                        RotateRL(pCur);                        break;                    }                }                //左子树高                else                {                    //左子树的左侧高                    if (pCur->bf == -1)                    {                        //右旋                        RotateRight(parent);                        break;                    }                    //左子树的右侧高                    else                    {                        //左右旋转                        RotateLR(pCur);                        break;                    }                }            }        }        return true;    }    bool IsBalanceTree()//判断树是不是AVL树    {        return _IsBalanceTree(pRoot);    }    int Hight()//求书的高度    {        return _Hight(pRoot);    }    void InOrder()    {        _InOrder(pRoot);        cout << endl;    }private:    bool _IsBalanceTree(Node *pRoot)    {        if (NULL == pRoot)            return true;        int left = _Hight(pRoot->pLeft);        int right = _Hight(pRoot->pRight);        if (pRoot->bf != (right - left) || std::abs(pRoot->bf) > 1)            return false;        return _IsBalanceTree(pRoot->pLeft) && _IsBalanceTree(pRoot->pRight);    }    void _InOrder(Node* pRoot)    {        if (NULL == pRoot)            return;        _InOrder(pRoot->pLeft);        cout << pRoot->key << " ";        _InOrder(pRoot->pRight);    }    int _Hight(Node* pRoot)    {        if (NULL == pRoot)            return 0;        if (NULL == pRoot->pLeft && NULL == pRoot->pRight)            return 1;        int left = _Hight(pRoot->pLeft)+1;        int right = _Hight(pRoot->pRight)+1;        return left > right ? left : right;    }    //左旋---->就是用父节点的右孩子去替换父节点,将父节点连接在其右孩子的左侧    void RotateLeft(Node *parent)    {        Node* pParent = parent->pParent;        Node* pSubR = parent->pRight;        Node* pSubRL = pSubR->pLeft;        //父节点的右链接右孩子的左结点        parent->pRight = pSubRL;        //右孩子成为父节点的父节点        parent->pParent = pSubR;        //右孩子的左结点存在,更新其父节点        if (pSubRL)            pSubRL->pParent = parent;        //更新右孩子的父节点和左结点        pSubR->pParent = pParent;        pSubR->pLeft = parent;        //如果pParent存在        if (pParent)        {            //说明这是一颗子树            //将右节点连接在pParent的左或者右            if (pParent->pLeft == parent)            {                pParent->pLeft = pSubR;            }            else            {                pParent->pRight = pSubR;            }        }        //pParent不存在,说明父节点是树根        else//这是树根将变为右节点            pRoot = pSubR;        //将其平衡因子置0        parent->bf = pSubR->bf = 0;    }    //右旋    void RotateRight(Node* parent)    {        Node* pParent = parent->pParent;        Node* pSubL = parent->pLeft;        Node* pSubLR = pSubL->pRight;        parent->pLeft = pSubLR;        parent->pParent = pSubL;        if (pSubLR)            pSubLR->pParent = parent;        pSubL->pParent = pParent;        pSubL->pRight = parent;        if (pParent)        {            if (pParent->pLeft == parent)                pParent->pLeft = pSubL;            else                pParent->pRight = pSubL;        }        else        {            pRoot = pSubL;        }        parent->bf = pSubL->bf = 0;    }    //左右旋转    void RotateLR(Node* parent)    {        //判断其右孩子的平衡因子        int bf = parent->pRight->bf;        //parent左旋,parent下降其父节点成为其父节点的父节点        RotateLeft(parent);        //parent之前的父节点右旋        RotateRight(parent->pParent->pParent);        if (bf == -1)        {//说明parent接受了其右孩子的左孩子,            parent->pParent->pRight->bf = 1;        }        else if (1 == bf)        {            //说明parent的父节点,接受了其右孩子的右孩子            parent->bf = -1;        }    }    //右左旋转    void RotateRL(Node* parent)    {        int bf = parent->pLeft->bf;        RotateRight(parent);        RotateLeft(parent->pParent->pParent);        if (1 == bf)        {            parent->pParent->pLeft->bf = -1;        }        else if (-1 == bf)        {            parent->bf = 1;        }    }protected:    Node* pRoot;};