平衡二叉搜索树(AVL)旋转

简介: 平衡二叉搜索树(AVL)旋转

单独开一章节介绍 RotateL 、 RotateR 及更复杂的 LR 和 RL 型旋转,更多是为了红黑树的旋转部分做铺垫;由于 AVL 树和红黑树发生旋转的判断标准不同 —— 分别为平衡因子和节点的颜色,两棵树左旋和右旋的在细节上会有一些差异,但从整体来看,二者的精神一致。


定义节点

    template <class K, class V>
    struct AVLTreeNode
    {
        AVLTreeNode* _left;
        AVLTreeNode* _right;
        pair<K, V> _kv;
        AVLTreeNode* _parent;
        int _bf;

        AVLTreeNode(const pair<K, V>& kv)
            :_left(nullptr)
            ,_right(nullptr)
            ,_kv(kv)
            ,_parent(nullptr)
            ,_bf(0)
        {}
    };

关于如何快速记忆什么时候为左旋、右旋、或左右旋、或右左旋,有一个小技巧:

当左树更高,需要向右调整高度,此时右旋;

当右树更高,需要向左调整高度,此时左旋 … …

一、新节点插入较高左子树的左侧 —— 引发右单旋

  void RotateR(Node* parent)
    {
        Node* ppnode = parent->_parent;
        
        Node* subLeft = parent->_left;
        Node* subLeftR = subLeft->_right;
        
        parent->_left = subLeftR;
        if (subLeftR)
            subLeftR->_parent = parent;
        subLeft->_right = parent;
        parent->_parent = subLeft;
        
        if (ppnode == nullptr)
        {
            _root = subLeft;
            subLeft->_parent = nullptr;
        }
        else 
        {
            subLeft->_parent = ppnode;
        }
        // 调整平衡因子
        parent->_bf = 0;
        subLeft->_bf = 0;
    }
二、新节点插入较高右子树的右侧 —— 引发左单旋

  void RotateL(Node* parent)
    {
        Node* ppnode = parent->_parent;
        
        Node* subRight = parent->_right;
        Node* subRightL = subRight->_left;
        
        parent->_right = subRight;
        if (subRight)
          subRight->_parent = parent;
        subRight->_left = parent;
        parent->_parent = subRight;
        
        if (ppnode == nullptr)
        {
            _root = subRight;
            subRight->_parent = nullptr;
        }
        else 
        {
            subRight->_parent = ppnode;
        }
        
        parent->_bf = 0;
        subRight->_bf = 0;
    }
三、新节点插入较高左子树的右侧 —— 引发左右双旋

根据旋转之前 subLeftR 的平衡因子,来决定旋转后各节点的平衡因子。

  void RotateLR(Node* parent)
    {
        Node* subLeft = parent->_left;
        Node* subLeftR = subLeft->_right;
        int bf = subLeftR->_bf; // 记录旋转前的平衡因子
        
        RotateL(subLeft);
        RotateR(parent);
        
        if (bf == -1)
        {
            parent->_bf = 1;
            subLeft->_bf = subLeftR->_bf = 0;
        }
        else if (bf == 1)
        {
            subLeft->_bf = -1;
            parent->_bf = subLeftR->_bf = 0;
        }
        else 
        {
            parent->_bf = subLeft->_bf = subLeftR->_bf = 0;
        }
    }
四、新节点插入较高右子树的左侧 —— 引发右左双旋

  void RotateRL(Node* parent)
    {
        Node* subRight = parent->_right;
        Node* subRightL = subRight->_left;
        
        int bf = subRightL->_bf;
        
        RotateR(subRight);
        RotateL(parent);
        
        if (bf == 1)
        {
            parent->_bf = -1;
            subRight->_bf = subRightL->_bf = 0;
        }
        else if (bf == -1)
        {
            subRight->_bf = 1;
            parent->_bf = subRightL->_bf = 0;
        }
        else 
        {
            parent->_bf = subRight->_bf = subRightL->_bf = 0;
        }
    }
相关文章
|
6月前
深入解析AVL树:高效实现二叉平衡搜索树(2)
深入解析AVL树:高效实现二叉平衡搜索树
31 1
|
6月前
|
存储
深入解析AVL树:高效实现二叉平衡搜索树
深入解析AVL树:高效实现二叉平衡搜索树
31 1
|
7月前
AVLTree——高度平衡二叉搜索树
AVLTree——高度平衡二叉搜索树
73 0
|
算法 C++
AVL——平衡搜索树
AVL树是对二叉搜索树的严格高度控制,所以AVL树的搜索效率很高,但是这是需要付出很大的代价的,要维护父亲指针,和平衡因子。
|
算法 Java C语言
平衡二分搜索树
大家好,我是王有志。今天我们一起学习更“高级”的二分搜索树--平衡二分搜索树。通过平衡二分搜索树,我们来认识第一个自平衡二分搜索树--AVL树。
80 0
平衡二分搜索树
|
算法
平衡二叉树(AVL树)
平衡二叉树(AVL树)
86 0
学习平衡搜索二叉树(AVL树)【日志】
学习平衡搜索二叉树(AVL树)【日志】
89 0
|
存储
红黑树、平衡二叉查找树
红黑树、平衡二叉查找树 平衡二叉查找树 非常常用的查找结构,各操作的时间复杂度与树的高度成正比
105 0
红黑树、平衡二叉查找树
一棵树,怎么就平衡了(图解AVL+实现)
在树的种类中,通常分成二叉树和多叉树,我们熟悉的二叉树种类有二叉搜索(排序、查找)树、二叉平衡树、伸展树、红黑树等等。而熟悉的多叉树像B树、字典树都是经典多叉树。
113 0
一棵树,怎么就平衡了(图解AVL+实现)