AVL树的旋转

···AVL树又称为高度平衡的二叉树。它能保持二叉树的高度平衡,尽量降低二叉树的高度,减少树的平均搜索长度。
···AVL树有以下几条性质:
·····1.左子树和右子树的高度之差的绝对值不超过1
·····2.树中的每个左子树和右子树都是AVL树
·····3.每个节点都有一个平衡因子,任一节点的平衡因子是-1,1,0.(每个节点的平衡因子等于右子树的高度减去左子树的高度)
···AVL树就是在二叉搜索树的基础上实现的,所以这里主要描述AVL树的旋转过程,最后会附上完整的源代码。

AVL树在进行插入时,要不断更新每个节点的平衡因子,如果插入叶子节点后,父节点的平衡因子变为0,则不用调整。如果父节点的平衡因子变为1或-1,需要调整吗?注意这里虽然父节点的平衡因子是1或-1,满足AVL树的性质,但是它可能会影响上一层的节点,画图说明一下。
这里写图片描述
···插入B节点后,图一图二中的A节点平衡因子都变为-1,图一已经是AVL树,但是图二根节点的平衡因子变为-2,所有插入节点后,如果父节点的平衡 因子变成1或-1,需要继续向上调整。
如果插入节点后父节点的平衡因子变为2或-2,需要立即旋转来调整平衡因子。
右单旋
这里写图片描述
··· 在判断旋转的方式时,最好先标出每个节点的平衡因子(三角形节点是叶节点),这种情况下就要进行右单旋了,我在记忆右单旋的时候就将其理解为:将要旋转的节点变成它左孩子节点的右子树,在此图中,就是把30这个节点变成20的右子树,那么20已经有右孩子了,怎么办呢?很简单,依据二叉搜索树的性质,所有节点都遵循左孩子值比它小,右孩子值比它大这一原则,所以f节点的值大于20,而f的值一定小于30,所以就把f作为30的左子树,然后将30作为20的右子树,就完成右单旋了。
这里写图片描述
这就是旋转后的AVL树。
左单旋
这里写图片描述
和右单旋一样,先标记平衡因子
再把10这个节点转到20的左边就行了
这里写图片描述
左右双旋
什么时候需要进行左右双旋呢?
这里写图片描述
同样的,我们需要先标记平衡因子,当parent和subl的平衡因子分别为-2和1时,就要进行左右双旋了。
双旋需要考虑三种情况(sublr的平衡因子调整前分别为0,-1,1时),如下图
1.这里写图片描述
第一种情况最简单,先让sublr的左孩子指向subl,再让parent变成sublr的右孩子即可。旋转后的三个节点平衡因子都是0.(左右双旋第一步应该先左旋subl,再右旋parent)这里写图片描述
上图就是旋转过程。
2.这里写图片描述
这种情况下调整前sublr的平衡因子为-1,调整后,parent,subl,sublr的平衡因子分别为1, 0, 0.
这里写图片描述
图为调整后的AVL树
3.这里写图片描述
这种情况下调整前sublr的平衡因子是1,调整后parent,subl,sublr的平衡因子分别为0,-1,0。
右左双旋
与左右双旋相对应,当parent和subr的平衡因子分别为2,-1时进行右左双旋
这里写图片描述
右左双旋的步骤是先对subr进行右旋,再对parent进行左旋。
同样分为三种情况:
1.这里写图片描述
这种情况调整前subrl的平衡因子为0,调整后,parent,subr,subrl的平衡因子都是0
调整后如图
这里写图片描述
2.第二种情况调整前subrl的平衡因子是1,调整后parent,subr,subrl分别是-1,0,0
这里写图片描述
调整后:这里写图片描述
3.第三钟情况:调整前subrl的平衡因子是-1,调整后parent,subr,subrl分别是0,1,0
这里写图片描述
调整后:
这里写图片描述
源代码:

#pragma once
#include<iostream>
#include<cstdlib>
#include <algorithm>
#include<cassert>

using namespace std;

template<typename K, typename V>
struct AVLTreeNode
{
    typedef AVLTreeNode<K, V> Node;
    AVLTreeNode(const K& key, const V& value)
        : _left(NULL)
        , _right(NULL)
        , _parent(NULL)
        , _key(key)
        , _value(value)
        , _bf(0)
    {}
    Node* _left;
    Node* _right;
    Node* _parent;

    int _bf;
    K _key;
    V _value;
};

template<typename K, typename V>
class AVLTree
{
public:
    typedef AVLTreeNode<K, V> Node;

    //构造
    AVLTree()
        :_root(NULL)
    {}
    //析构
    ~AVLTree()
    {
        _Destroy(_root);
    }
    //插入节点
    bool Insert(const K& key, const V& value)
    {
        if (_root == NULL)
        {
            _root = new Node(key, value);
            return true;
        }

        Node* parent = NULL;
        Node* cur = _root;

        while (NULL != cur)
        {
            parent = cur;
            if (key > cur->_key)
            {
                cur = cur->_right;
            }
            else if(key < cur->_key)
            {
                cur = cur->_left;
            }
            else          //因为搜索树不存在相同的值,所以返回错误
            {
                return false;
            }
        }
        cur = new Node(key, value);
        if (cur->_key > parent->_key)
        {
            parent->_right = cur;
            cur->_parent = parent;
        }
        else
        {
            parent->_left = cur;
            cur->_parent = parent;
        }
        //插入完成,更新平衡因子
        while (parent)
        {
            if (parent->_left == cur)
            {
                parent->_bf--;
            }
            else
            {
                parent->_bf++;
            }
            if (parent->_bf == 0)
            {
                break;//
            }
            else if (parent->_bf == 1 || parent->_bf == -1)
            {
                cur = parent;
                parent = parent->_parent;
            }//向上调整平衡因子
            else if (parent->_bf == 2 || parent->_bf == -2)
            {
                if (parent->_bf == 2)
                {
                    if (cur->_bf == 1)  //左单旋
                    {
                        _RotateL(parent);
                    }
                    else                //右左旋转
                    {
                        _RotateRL(parent);
                    }
                }
                if(parent->_bf == -2)
                {
                    if (cur->_bf == 1)  //左右旋转
                    {
                        _RotateLR(parent);
                    }
                    else                //右单旋
                    {
                        _RotateR(parent);
                    }
                }
                break;//
            }
        }
    }

    void _RotateL(Node* parent)
    {
        assert(parent);
        Node* ppNode = parent->_parent;
        Node* prNode = parent->_right;
        Node* prlNode = prNode->_left;

        parent->_right = prlNode;      //***
        if (prlNode)
        {
            prlNode->_parent = parent;
        }
        prNode->_left = parent;
        parent->_parent = prNode;
        if (ppNode == NULL)
        {
            _root = prNode;
            prNode->_parent = NULL;
        }
        else
        {
            if (parent == ppNode->_left)
            {
                ppNode->_left = prNode;
            }
            else
            {
                ppNode->_right = prNode;
            }
            prNode->_parent = ppNode;
        }
        parent->_bf = prNode->_bf = 0;
    }

    void _RotateR(Node* parent)
    {
        assert(parent);
        Node* ppNode = parent->_parent;
        Node* plNode = parent->_left;
        Node* plrNode = plNode->_right;

        parent->_left = plrNode;
        if (plrNode)
        {
            plrNode->_parent = parent;
        }
        plNode->_right = parent;
        parent->_parent = plNode;
        if (ppNode == NULL)
        {
            _root = plNode;
            plNode->_parent = NULL;
        }
        else
        {
            if (parent == ppNode->_left)
            {
                plNode = ppNode->_left;
            }
            else
            {
                plNode = ppNode->_right;
            }
            plNode->_parent = ppNode;
        }
        parent->_bf = plNode->_bf = 0;
    }

    void _RotateLR(Node *parent)
    {
        Node* SubL = parent->_left;
        Node* SubLR = SubL->_right;
        int bf = SubLR->_bf;

        _RotateL(SubL);
        _RotateR(parent);
        //如果bf为0,代表插入点就是这个节点,这个时候所有旋转后的bf皆为0
        if (bf == 0)
        {
            SubL->_bf = parent->_bf = 0;
        }
        //当bf为1时,这个时候相当于是给sublr的右树插入
        else if (bf == 1)
        {
            SubL->_bf = -1;
            parent->_bf = 0;
        }
        //bf是-1时,相当于给sublr的左树插入
        else
        {
            SubL->_bf = 0;
            parent->_bf = 1;
        }
        SubLR->_bf = 0;
    }

    void _RotateRL(Node *parent)
    {
        Node* SubR = parent->_right;
        Node* SubRL = SubR->_left;

        int bf = SubRL->_bf;
        _RotateR(SubR);
        _RotateL(parent);

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

    bool _Find(const K& key)
    {
        if (_root == NULL)
            return false;
        Node* cur = _root;
        while (cur)
        {
            if (key > cur->_key)
            {
                cur = cur->_right;
            }
            else if (key > cur->_key)
            {
                cur = cur->_left;
            }
            else
            {
                return true;
            }
        }
        return false;
    }

    int _Height(Node* root)
    {
        if (root == NULL)
        {
            return 0;
        }
        int LeftLen = _Height(root->_left);
        int RightLen = _Height(root->_right);
        return LeftLen > RightLen ? LeftLen + 1 : RightLen + 1;
    }
    O(N^2)
    //bool  _IsBalance(Node* root)
    //{
    //  if (root == NULL)
    //  {
    //      return true;
    //  }
    //  int left = _Height(root->_left);
    //  int right = _Height(root->_right);
    //  int diff = left - right;
    //  if (diff > 1 || diff < -1)
    //  {
    //      return false;
    //  }
    //  return _IsBalance(root->_left) && _IsBalance(root->_right);
    //}

    bool _IsBalance2(Node* root, int &height)
    {
        if (root == NULL)
        {
            height = 0;
            return true;
        }
        int leftHeight = 0, rightHeight = 0;
        bool leftRet = _IsBalance2(root->_left, leftHeight);
        bool rightRet = _IsBalance2(root->_right, rightHeight);

        height = max(leftHeight, rightHeight) + 1;
        if (abs(leftHeight - rightHeight) > 1)
        {
            return false;
        }
        return leftRet && rightRet;
    }

    bool IsBalance()
    {
        int height = 0;
        return _IsBalance2(_root, height);
    }

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

    void _InOrder(Node* root)
    {
        if (root == NULL)
        {
            return;
        }
        _InOrder(root->_left);
        cout << root->_key<< "->" << endl;
        _InOrder(root->_right);
    }

    void InOrder()
    {
        _InOrder(_root);
    }

private:
    Node * _root;
    //拷贝构造
    AVLTree(const AVLTree<K, V> & a);
    //赋值
    AVLTree<K, V>& operator=(const AVLTree<K, V> & a);
};


void test()
{
    AVLTree<int, int> AVLtree;
    int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
    for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
    {
        AVLtree.Insert(a[i], a[i]);
    }
    AVLtree.InOrder();
    bool ret =  AVLtree.IsBalance();
    if (ret)
    {
        cout << "yes" << endl;
    }
    else
    {
        cout << "no" << endl;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值