AVL树的实现

AVL树又名高度平衡的搜索二叉树,上一篇文章我们讲到二叉搜索树时,说到它存在一个问题:退化,这使得它的时间复杂度从O(lgN)降到了O(N)。为了解决这个问题,出现了一棵新的树,也就是AVLtree,我们先来看看它的性质:
1,它是一棵搜索 二叉树,所以满足每个节点的值大于左子树中任意节点的值,并且小于右子树中任意节点的值。
2,它是一棵平衡树,他要求每个节点的左右子树的深度之差不能超过1,即这棵树的倒数第二层节点是满的。
3,每一棵子树都是一棵AVL树;
4,每个节点都有一个平衡因子bf,取值为-1、0、1 。它的值等于右子树的深度减去左子树的深度。

AVL树节点的结构如下:

template<class K,class V>
struct AVLTreeNode
{
    AVLTreeNode<K,V>* _left;
    AVLTreeNode<K,V>* _right;
    AVLTreeNode<K,V>* _parent;

    K _key;
    V _value;

    int _bf;  //平衡因子

    AVLTreeNode(const K& key,const V& value)
        :_left(NULL),_right(NULL),_parent(NULL),_key(key),_value(value),_bf(0)
    {}
};

对于AVL树的操作,这里主要讲解一下插入
插入操作中,通过对平衡因子的判定来进行相应的旋转操作来改变树的结构。整个过程可以分为三个过程:1,寻找插入位置;2,插入;3,调整(重点也是难点)。对此我画了个流程图,如下:
这里写图片描述

代码如下:

    bool Insert(const K& key,const V& value)
    {
        if (_root == NULL)
        {
            _root = new Node(key, value);
            return true;
        }
        Node* cur = _root;
        Node* parent = cur;
        while (cur)
        {
            if (key > cur->_key)
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (key < cur->_key)
            {
                parent = cur;       
                cur = cur->_left;
            }
            else
                return false;
        }
        //找到插入的位置   插入
        cur = new Node(key, value);
        cur->_parent = parent;

        if (parent->_key > key)
            parent->_left = cur;
        else
            parent->_right = cur;

        //调整平衡因子
        while (parent)
        {
            if (cur == parent->_left)
                parent->_bf--;
            else
                parent->_bf++;
            if (parent->_bf == 0)
            {
                break;
            }
            else if (parent->_bf == 1 || parent->_bf == -1)
            {
                cur = parent;
                parent = cur->_parent;
            }
            else   // parent->_bf == 2  /  == -2
            {
                //旋转
                if (parent->_bf == 2)
                {
                    if (cur->_bf == 1)
                    {
                        RotateL(parent);
                    }
                    else
                    {
                        RotateRL(parent);
                    }
                }
                else
                {
                    if (cur->_bf == 1)
                    {
                        RotateLR(parent);
                    }
                    else
                    {
                        RotateR(parent);
                    }
                }
                break;
            }
        }
        return true;
    }

下面我们再一次来看一下四种旋转(LL, LR, RR, RL):
1,对于LL,在左旋之后,只需将该节点(parent)和右孩子根节点(subR)的平衡因子置为0即可。
这里写图片描述

代码如下:

void RotateL(Node* parent)
    {
        Node* subR = parent->_right;
        Node* subRL = subR->_left;

        parent->_right = subRL;
        if (subRL)
            subRL->_parent = parent;

        subR->_left = parent;
        Node* pparent = parent->_parent;
        if (pparent)
        {
            parent->_parent = subR;     
            if (pparent->_left == parent)
                pparent->_left = subR;
            else
                pparent->_right = subR;
        }
        else
            _root = subR;

        subR->_parent = pparent;

        subR->_bf = parent->_bf = 0;
    }

2,对于RR,在右旋之后,只需将该节点(parent)和左孩子根节点(subL)的平衡因子置为0即可。
这里写图片描述
代码如下:

void RotateR(Node* parent)
    {
        Node* subL = parent->_left;
        Node* subLR = subL->_right;

        parent->_left = subLR;
        if (subLR)
            subLR->_parent = parent;

        subL->_right = parent;
        Node* pparent = parent->_parent;
        if (pparent)
        {
            parent->_parent = subL;
            if (pparent->_left == parent)
                pparent->_left = subL;
            else
                pparent->_right = subL;
        }
        else
            _root = subL;

        subL->_parent = pparent;

        subL->_bf = parent->_bf = 0;
    }

3,对于LR,保存subLR的平衡因子,用于后面判断:如果为1,subRL的右孩子会补为parent的左孩子,subL的右节点无人补,是空,subL的bf置为-1,如果为-1,subLR的左孩子会补为subL的右孩子,而parent的左节点无人补,parent的bf置为1
这里写图片描述
代码如下:

void RotateLR(Node* parent)
    {
        Node* subL = parent->_left;
        Node* subLR = parent->_right;
        int bf = subLR->_bf;

        RotateL(parent->_left);
        RotateR(parent);

        if (bf == 1)
        {
            subL->_bf = -1;
        }
        else if (bf == -1)
        {
            parent->_bf = 1;
        }

        subLR->_bf = 0;

    }

4,对于RL,保存subRL的平衡因子,用于后面判断:如果为1,subRL的右孩子会补为subR的左孩子,parent的右节点无人补,是空,parent的bf置为-1,如果为-1,subRL的左孩子会补为parent的右孩子,而subR的左节点无人补,subR的bf置为1
这里写图片描述
代码如下:

void RotateRL(Node* parent)  //先旋转,后调整平衡因子
    {
        Node* subR = parent->_right;
        Node* subRL = subR->_left;
        int bf = subRL->_bf;

        RotateR(parent->_right);
        RotateL(parent);

        if (1 == bf)   //subRL的右孩子会补为subR的左孩子,parent的右节点无人补,是空,bf置为-1
        {
            parent->_bf = -1;
        }
        else if (-1 == bf)   //subRL的左孩子会补为parent的右孩子,而subR的左节点无人补,bf置为1
        {
            subR->_bf = 1;
        }

        subRL->_bf = 0;
    }

这样AVL树的插入就解决了,我们需要一个函数来判定该树是否是AVL树。这个简单,只需遍历整棵树,看他的平衡因子是否正确即可。代码如下:

    bool IsBalance()
    {
        int depth = 0;
        return _IsBalance(_root, depth);
    }


    bool _IsBalance(Node* root, int& depth)
    {
        if (root == NULL)
        {
            depth = 0;
            return true;
        }
        int leftDepth = 0;
        int rightDepth = 0;
        if (_IsBalance(root->_left, leftDepth) == false)
            return false;

        if (_IsBalance(root->_right, rightDepth) == false)
            return false;

        if ((rightDepth - leftDepth) != root->_bf)
        {
            cout << "bf 异常" << root->_key << endl;
            //return false;
        }

        depth = rightDepth > leftDepth ? rightDepth + 1 : leftDepth + 1;
        return abs(rightDepth - leftDepth) < 2;

    }

像查找,求深度等这种问题的解决就不具体讲解了,后面附有完整代码。

完整代码

#include<iostream>

using namespace std;

template<class K,class V>
struct AVLTreeNode
{
    AVLTreeNode<K,V>* _left;
    AVLTreeNode<K,V>* _right;
    AVLTreeNode<K,V>* _parent;

    K _key;
    V _value;

    int _bf;  //平衡因子

    AVLTreeNode(const K& key,const V& value)
        :_left(NULL),_right(NULL),_parent(NULL),_key(key),_value(value),_bf(0)
    {}
};

template<class K,class V>
class AVLTree
{
    typedef AVLTreeNode<K,V> Node;
public:
    AVLTree()
        :_root(NULL)
    {}

    ~AVLTree()
    {
        _Delete(_root);
    }

    bool Insert(const K& key,const V& value)
    {
        if (_root == NULL)
        {
            _root = new Node(key, value);
            return true;
        }
        Node* cur = _root;
        Node* parent = cur;
        while (cur)
        {
            if (key > cur->_key)
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (key < cur->_key)
            {
                parent = cur;       
                cur = cur->_left;
            }
            else
                return false;
        }
        //找到插入的位置   插入
        cur = new Node(key, value);
        cur->_parent = parent;

        if (parent->_key > key)
            parent->_left = cur;
        else
            parent->_right = cur;

        //调整平衡因子
        while (parent)
        {
            if (cur == parent->_left)
                parent->_bf--;
            else
                parent->_bf++;
            if (parent->_bf == 0)
            {
                break;
            }
            else if (parent->_bf == 1 || parent->_bf == -1)
            {
                cur = parent;
                parent = cur->_parent;
            }
            else   // parent->_bf == 2  /  == -2
            {
                //旋转
                if (parent->_bf == 2)
                {
                    if (cur->_bf == 1)
                    {
                        RotateL(parent);
                    }
                    else
                    {
                        RotateRL(parent);
                    }
                }
                else
                {
                    if (cur->_bf == 1)
                    {
                        RotateLR(parent);
                    }
                    else
                    {
                        RotateR(parent);
                    }
                }
                break;
            }
        }
        return true;
    }



    void InOrder()
    {
        _InOrder(_root);
        cout << endl;
    }

    Node* Find(const K& x)
    {
        return _Find(x);
    }

    bool IsBalance()
    {
        int depth = 0;
        return _IsBalance(_root, depth);
    }

protected:

    bool _IsBalance(Node* root, int& depth)  //注意:depth引用
    {
        if (root == NULL)
        {
            depth = 0;
            return true;
        }
        int leftDepth = 0;
        int rightDepth = 0;
        if (_IsBalance(root->_left, leftDepth) == false)
            return false;

        if (_IsBalance(root->_right, rightDepth) == false)
            return false;

        if ((rightDepth - leftDepth) != root->_bf)
        {
            cout << "bf 异常" << root->_key << endl;
            //return false;
        }

        depth = rightDepth > leftDepth ? rightDepth + 1 : leftDepth + 1;
        return abs(rightDepth - leftDepth) < 2;

    }

    Node* _Find(Node* root, const K& x)
    {
        while (root)
        {
            if (x > root->_key)
                root = root->_right;
            else if (x < root->_key)
                root = root->_key;
            else
                return root;
        }
        return NULL;
    }

    void _InOrder(Node* root)
    {
        if (root == NULL)
            return;

        _InOrder(root->_left);
        cout << root->_key << " ";
        _InOrder(root->_right);
    }


    void _Delete(Node*& root)
    {
        if (root == NULL)
            return;
        _Delete(root->_left);
        _Delete(root->_right);
        delete root;
        root = NULL;
    }

    int Depth(Node* root)
    {
        if (root == NULL)
            return 0;
        int leftDepth = Depth(root->_left);
        int rightDepth = Depth(root->_right);

        return leftDepth > rightDepth ?leftDepth + 1 : rightDepth + 1;
    }

    void RotateL(Node* parent)
    {
        Node* subR = parent->_right;
        Node* subRL = subR->_left;

        parent->_right = subRL;
        if (subRL)
            subRL->_parent = parent;

        subR->_left = parent;
        Node* pparent = parent->_parent;
        if (pparent)
        {
            parent->_parent = subR;     
            if (pparent->_left == parent)
                pparent->_left = subR;
            else
                pparent->_right = subR;
        }
        else
            _root = subR;

        subR->_parent = pparent;

        subR->_bf = parent->_bf = 0;
    }

    void RotateR(Node* parent)
    {
        Node* subL = parent->_left;
        Node* subLR = subL->_right;

        parent->_left = subLR;
        if (subLR)
            subLR->_parent = parent;

        subL->_right = parent;
        Node* pparent = parent->_parent;
        if (pparent)
        {
            parent->_parent = subL;
            if (pparent->_left == parent)
                pparent->_left = subL;
            else
                pparent->_right = subL;
        }
        else
            _root = subL;

        subL->_parent = pparent;

        subL->_bf = parent->_bf = 0;
    }

    void RotateLR(Node* parent)
    {
        Node* subL = parent->_left;
        Node* subLR = parent->_right;
        int bf = subLR->_bf;

        RotateL(parent->_left);
        RotateR(parent);

        if (bf == 1)
        {
            parent->_bf = 0;
            subL->_bf = -1;
        }
        else if (bf == -1)
        {
            subL->_bf = 0;
            parent->_bf = 1;
        }
        else
        {
            subL->_bf = parent->_bf = 0;
        }

        subLR->_bf = 0;

    }

    void RotateRL(Node* parent)  //先旋转,后调整平衡因子
    {
        Node* subR = parent->_right;
        Node* subRL = subR->_left;
        int bf = subRL->_bf;

        RotateR(parent->_right);
        RotateL(parent);

        if (1 == bf)
        {
            subR->_bf = 0;
            parent->_bf = -1;
        }
        else if (-1 == bf)
        {
            parent->_bf = 0;
            subR->_bf = 1;
        }
        else
        {
            parent->_bf = subR->_bf = 0;
        }    

        subRL->_bf = 0;
    }


private:
    Node* _root;
};

void Test()
{
    AVLTree<int, int> t;
    //int a[] = {16, 3, 7, 11, 9, 26, 18, 14, 15};
    int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
    for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
    {
        t.Insert(a[i], i);
        cout << a[i] << "IsBalance?" << t.IsBalance() << endl;
    }

    t.InOrder();
    cout << "IsBalance?" << t.IsBalance() << endl;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值