AVL树

记得上次的博客中说到了二叉所搜树,也说到了他还说一种有欠缺的二叉树,当输入单调递增或单调递减的数据后,他会退化成链表,这样会严重影响效率,所以AVL树就被引出来了,下面就开始简单介绍AVL树吧。
首先AVL树是一种严格的平衡二叉树,他要求所有节点所在的二叉树都满足一个条件:平衡因子不大于2,搜索二叉树也就接近满二叉树了,这个时候搜索的效率就比较高了,但是它也因此付出了很高的代价,那就是他会不断的旋转,下面我们就开始AVL树的旋转吧!
我们来分析AVL树不平衡的时候旋转的情况吧,我总结了一下,大概如下几种情况吧:



以上就是几种情况的分析,为什么在左右双旋的时候或者右左双旋的时候我要画出两种插入节点的位置呢?不是无聊,而是在双旋的时候插入位置对平衡因子有影响,这个问题在单旋中是不存在的,下面就来看看吧:

1.右左单旋

   也就是上面第三幅图,我们可以推理得出:

(1).当插入节点10的时候,10最终会被分配到左子树中,具体位置是在8右边,节点


(2).当插入节点13的时候


右左单旋和这个刚好对称,情况相似,所以就不举例说明了,下面给出代码吧,代码针对AVL树插入节点的四种情况进行了分析:

#pragma once  
#include <iostream>  
using namespace std;  
  
template<class K,class V>  
struct AVLTreeNode  
{  
    typedef AVLTreeNode<K, V> Node;  
  
    AVLTreeNode<K, V> *_left;  
    AVLTreeNode<K, V> *_right;  
    AVLTreeNode<K, V> *_parent;  
  
    K   _key;  
    V   _val;  
    int _bf;  
      
    AVLTreeNode(const K &key = K(), const V &val = V())  
        : _key(key)  
        , _val(val)  
        , _bf(0)  
        , _left(NULL)  
        , _right(NULL)  
        , _parent(NULL)  
    {}  
};  
  
template<class K,class V>  
class AVLTree  
{  
    typedef AVLTreeNode<K, V> Node;  
public:  
    AVLTree()  
        : _root(NULL)  
    {}  
  
    bool Insert(const K key, const V val)  
    {  
        if (_root == NULL)  
        {  
            _root = new Node(key, val);  
            return true;  
        }  
  
        Node* parent = NULL;  
        Node* cur = _root;  
        while (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, val);  
        cur->_parent = parent;  
        if (key < parent->_key)  
        {  
            parent->_left = cur;  
        }  
        else  
        {  
            parent->_right = cur;  
        }  
  
        while (parent)  
        {  
            if (parent->_left == cur)  
            {  
                --parent->_bf;  
            }  
            else  
            {  
                ++parent->_bf;  
            }  
  
            if (parent->_bf == 0)  
            { //平衡  
                return true;  
            }  
            else if (abs(parent->_bf) < 2)  
            { //继续上调  
                cur = parent;  
                parent = parent->_parent;  
            }  
            else  
            { //不平衡,分四种情况讨论               
                if (cur->_bf > 0 && parent->_bf > 0)  
                {   //情况1 左单旋  
                    _RotateL(parent, cur);                    
                    return true;  
                }  
                else if (parent->_bf < 0 && cur < 0)  
                {   //情况2 右单旋  
                    _RotateR(parent, cur);  
                    return true;  
                }                                 
                else if (parent->_bf < 0 && cur->_bf > 0)  
                {   //情况3 左右单旋  
                    Node* pSubL = parent->_left;  
                    Node* pSubLR = pSubL->_right;  
                    int bf = pSubLR->_bf;  
                    // bf = -1 , 0 , 1 产生的影响  
                      
                    _RotateL(pSubL, pSubLR);  
                    _RotateR(parent, pSubLR); //此处千万不要传递(parent,parent->_left)因为两者都是parent的引用  
                    if (bf == -1)  
                    { //  
                        //cur->_bf = 0;  
                        parent->_bf = 1;  
                    }  
                    else if (bf == 1)  
                    {  
                        cur->_bf = -1;  
                        //parent->_bf = 0;  
                    }  
                    else  
                    {}  
                      
                    return true;  
                }  
                else //parent->_bf > 0 && cur->_bf < 0  
                {   //情况4 右左单旋  
                    Node* pSubR = parent->_right;  
                    Node* pSubRL = pSubR->_left;  
                    int bf = pSubRL->_bf;  
                    // bf = -1 , 0 , 1 产生不同的影响  
                    _RotateR(pSubR, pSubRL);  
                    _RotateL(parent, pSubRL);  
  
                    if (bf == -1)  
                    {  
                        cur->_bf = 1;  
                        //parent->_bf = 0;  
                    }  
                    else if (bf == 1)  
                    {  
                        parent->_bf = -1;  
                        //cur->_bf = 0;  
                    }  
                    else  
                    {}  
  
                    return true;  
                }  
            }  
        }  
    }  
  
    bool Isbalance()  
    {  
        return _Isbalance(_root);  
    }  
  
    int Height(Node* root)  
    {  
        return _Height(root);  
    }  
    ~AVLTree()  
    {  
        //_Destroy();  
    }  
  
protected:  
    int _Height(Node *root)  
    {  
        if (root == NULL)  
            return 0;  
        int left = 1 + _Height(root->_left);  
        int right = 1 + _Height(root->_right);  
  
        return left > right ? left : right;  
    }  
  
    bool _Isbalance(Node *root)  
    {  
        if (root == NULL)  
        {  
            return true;  
        }  
  
        int bf = _Height(root->_right) - _Height(root->_left);  
        if ( root->_bf != bf )  
        {  
            cout << "is unbalance:" << root->_key << endl;  
            return false;  
        }  
          
        return _Isbalance(root->_left);  
        return _Isbalance(root->_right);  
    }  
  
    void _RotateL(Node*& parent,Node*& cur)  
    {  
        cur->_parent = parent->_parent;  
        if (parent->_parent)  
        { //parent 还有父节点  
            if (parent == parent->_parent->_left)  
                parent->_parent->_left = cur;  
            else  
                parent->_parent->_right = cur;  
        }  
        else  
        { //parent为根节点  
            _root = cur;  
        }  
  
        parent->_parent = cur;  
        if (cur->_left)  
            cur->_left->_parent = parent;  
        parent->_right = cur->_left;        
        cur->_left = parent;  
          
        //平衡因子置为 0  
        parent->_bf = 0;  
        cur->_bf = 0;  
    }  
      
    void _RotateR(Node*& parent, Node*& cur)  
    {  
        cur->_parent = parent->_parent;  
        if (parent->_parent)  
        { //parent 还有父节点  
            if (parent == parent->_parent->_left)  
                parent->_parent->_left = cur;  
            else  
                parent->_parent->_right = cur;  
        }  
        else  
        { //parent为根节点  
            _root = cur;  
        }  
  
        //Node* pNode = cur;  
        parent->_parent = cur;  
          
        if (cur->_right != NULL)  
            cur->_right->_parent = parent;  
        parent->_left = cur->_right;  
        //pNode->_right = parent;  
        cur->_right = parent;  
          
        //平衡因子  
        parent->_bf = 0;  
        cur->_bf = 0;  
    }  
    void _RotateLR()  
    {}  
    void _RotateRL()  
    {}  
  
protected:  
    Node    *_root;  
};  
  
void TestAVLTree()  
{  
    AVLTree<int, int> At;  
    //At.Insert(10, 1);  
    //At.Insert(15, 1);  
    //At.Insert(20, 1);  
    //At.Insert(8, 1);  
    //At.Insert(12, 1);  
    ////左右双旋  
    ////At.Insert(13, 1);  //影响平衡因子  
    ////At.Insert(11, 1);  //影响平衡因子  
    /************************************************/  
    At.Insert(10, 1);  
    At.Insert(15, 1);  
    At.Insert(20, 1);  
    At.Insert(18,1);  
    At.Insert(25, 1);  
    //右左双旋  
    //At.Insert(17, 1);   //影响平衡因子  
    //At.Insert(19, 1);   //影响平衡因子   
      
      
    At.Isbalance();  
}  
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
#pragma once  
#include <iostream>  
using namespace std;  
  
template<class K,class V>  
struct AVLTreeNode  
{  
    typedef AVLTreeNode<K, V> Node;  
  
    AVLTreeNode<K, V> *_left;  
    AVLTreeNode<K, V> *_right;  
    AVLTreeNode<K, V> *_parent;  
  
    K   _key;  
    V   _val;  
    int _bf;  
      
    AVLTreeNode(const K &key = K(), const V &val = V())  
        : _key(key)  
        , _val(val)  
        , _bf(0)  
        , _left(NULL)  
        , _right(NULL)  
        , _parent(NULL)  
    {}  
};  
  
template<class K,class V>  
class AVLTree  
{  
    typedef AVLTreeNode<K, V> Node;  
public:  
    AVLTree()  
        : _root(NULL)  
    {}  
  
    bool Insert(const K key, const V val)  
    {  
        if (_root == NULL)  
        {  
            _root = new Node(key, val);  
            return true;  
        }  
  
        Node* parent = NULL;  
        Node* cur = _root;  
        while (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, val);  
        cur->_parent = parent;  
        if (key < parent->_key)  
        {  
            parent->_left = cur;  
        }  
        else  
        {  
            parent->_right = cur;  
        }  
  
        while (parent)  
        {  
            if (parent->_left == cur)  
            {  
                --parent->_bf;  
            }  
            else  
            {  
                ++parent->_bf;  
            }  
  
            if (parent->_bf == 0)  
            { //平衡  
                return true;  
            }  
            else if (abs(parent->_bf) < 2)  
            { //继续上调  
                cur = parent;  
                parent = parent->_parent;  
            }  
            else  
            { //不平衡,分四种情况讨论               
                if (cur->_bf > 0 && parent->_bf > 0)  
                {   //情况1 左单旋  
                    _RotateL(parent, cur);                    
                    return true;  
                }  
                else if (parent->_bf < 0 && cur < 0)  
                {   //情况2 右单旋  
                    _RotateR(parent, cur);  
                    return true;  
                }                                 
                else if (parent->_bf < 0 && cur->_bf > 0)  
                {   //情况3 左右单旋  
                    Node* pSubL = parent->_left;  
                    Node* pSubLR = pSubL->_right;  
                    int bf = pSubLR->_bf;  
                    // bf = -1 , 0 , 1 产生的影响  
                      
                    _RotateL(pSubL, pSubLR);  
                    _RotateR(parent, pSubLR); //此处千万不要传递(parent,parent->_left)因为两者都是parent的引用  
                    if (bf == -1)  
                    { //  
                        //cur->_bf = 0;  
                        parent->_bf = 1;  
                    }  
                    else if (bf == 1)  
                    {  
                        cur->_bf = -1;  
                        //parent->_bf = 0;  
                    }  
                    else  
                    {}  
                      
                    return true;  
                }  
                else //parent->_bf > 0 && cur->_bf < 0  
                {   //情况4 右左单旋  
                    Node* pSubR = parent->_right;  
                    Node* pSubRL = pSubR->_left;  
                    int bf = pSubRL->_bf;  
                    // bf = -1 , 0 , 1 产生不同的影响  
                    _RotateR(pSubR, pSubRL);  
                    _RotateL(parent, pSubRL);  
  
                    if (bf == -1)  
                    {  
                        cur->_bf = 1;  
                        //parent->_bf = 0;  
                    }  
                    else if (bf == 1)  
                    {  
                        parent->_bf = -1;  
                        //cur->_bf = 0;  
                    }  
                    else  
                    {}  
  
                    return true;  
                }  
            }  
        }  
    }  
  
    bool Isbalance()  
    {  
        return _Isbalance(_root);  
    }  
  
    int Height(Node* root)  
    {  
        return _Height(root);  
    }  
    ~AVLTree()  
    {  
        //_Destroy();  
    }  
  
protected:  
    int _Height(Node *root)  
    {  
        if (root == NULL)  
            return 0;  
        int left = 1 + _Height(root->_left);  
        int right = 1 + _Height(root->_right);  
  
        return left > right ? left : right;  
    }  
  
    bool _Isbalance(Node *root)  
    {  
        if (root == NULL)  
        {  
            return true;  
        }  
  
        int bf = _Height(root->_right) - _Height(root->_left);  
        if ( root->_bf != bf )  
        {  
            cout << "is unbalance:" << root->_key << endl;  
            return false;  
        }  
          
        return _Isbalance(root->_left);  
        return _Isbalance(root->_right);  
    }  
  
    void _RotateL(Node*& parent,Node*& cur)  
    {  
        cur->_parent = parent->_parent;  
        if (parent->_parent)  
        { //parent 还有父节点  
            if (parent == parent->_parent->_left)  
                parent->_parent->_left = cur;  
            else  
                parent->_parent->_right = cur;  
        }  
        else  
        { //parent为根节点  
            _root = cur;  
        }  
  
        parent->_parent = cur;  
        if (cur->_left)  
            cur->_left->_parent = parent;  
        parent->_right = cur->_left;        
        cur->_left = parent;  
          
        //平衡因子置为 0  
        parent->_bf = 0;  
        cur->_bf = 0;  
    }  
      
    void _RotateR(Node*& parent, Node*& cur)  
    {  
        cur->_parent = parent->_parent;  
        if (parent->_parent)  
        { //parent 还有父节点  
            if (parent == parent->_parent->_left)  
                parent->_parent->_left = cur;  
            else  
                parent->_parent->_right = cur;  
        }  
        else  
        { //parent为根节点  
            _root = cur;  
        }  
  
        //Node* pNode = cur;  
        parent->_parent = cur;  
          
        if (cur->_right != NULL)  
            cur->_right->_parent = parent;  
        parent->_left = cur->_right;  
        //pNode->_right = parent;  
        cur->_right = parent;  
          
        //平衡因子  
        parent->_bf = 0;  
        cur->_bf = 0;  
    }  
    void _RotateLR()  
    {}  
    void _RotateRL()  
    {}  
  
protected:  
    Node    *_root;  
};  
  
void TestAVLTree()  
{  
    AVLTree<int, int> At;  
    //At.Insert(10, 1);  
    //At.Insert(15, 1);  
    //At.Insert(20, 1);  
    //At.Insert(8, 1);  
    //At.Insert(12, 1);  
    ////左右双旋  
    ////At.Insert(13, 1);  //影响平衡因子  
    ////At.Insert(11, 1);  //影响平衡因子  
    /************************************************/  
    At.Insert(10, 1);  
    At.Insert(15, 1);  
    At.Insert(20, 1);  
    At.Insert(18,1);  
    At.Insert(25, 1);  
    //右左双旋  
    //At.Insert(17, 1);   //影响平衡因子  
    //At.Insert(19, 1);   //影响平衡因子   
      
      
    At.Isbalance();  
}  



AVL是一种自平衡的二叉查找,它确保了的高度始终保持在对数级别,从而保证了查找、插入和删除操作的时间复杂度为O(log n)。这种数据结构以它的发明者G.M. Adelson-Velsky和E.M. Landis的名字命名[^1]。 ### AVL的定义 - **平衡因子**:每个节点都有一个平衡因子,它是该节点左子的高度减去右子的高度。对于AVL来说,所有节点的平衡因子只能是-1, 0或1。 - **空**:如果T是空,则它自然是一个AVL。 - **非空**:若T不是空,则其左右子TL和TR都必须是AVL,并且对于任意节点,|HL - HR| ≤ 1(其中HL和HR分别表示左子和右子的高度)。 ### AVL的操作 当进行插入或删除操作时,可能会破坏AVL的平衡性,这时需要通过旋转来重新恢复平衡: - **单旋转**: - 左单旋(Single Rotate with Left)用于处理左孩子的左子过高。 - 右单旋(Single Rotate with Right)用于处理右孩子的右子过高。 - **双旋转**: - 左右双旋(Double Rotate with Left)用于处理左孩子的右子过高的情况。 - 右左双旋(Double Rotate with Right)用于处理右孩子的左子过高的情况。 这些旋转操作可以保持AVL的性质不变,并且能够快速地调整的结构以维持平衡。 ### AVL的实现 下面是一个简单的C语言代码示例,展示了如何定义AVL的节点以及实现基本的插入操作。这个例子中包含了必要的函数声明和一些核心逻辑。 ```c #include <stdio.h> #include <stdlib.h> // 定义AVL节点结构体 typedef struct AvlNode { int element; struct AvlNode *left; struct AvlNode *right; int height; // 节点的高度 } *AvlTree, *Position; // 获取两个整数中的较大者 int max(int a, int b) { return (a > b) ? a : b; } // 计算给定节点的高度 static int Height(AvlTree T) { if (T == NULL) return -1; // 空节点高度为-1 else return T->height; } // 单旋转 - 左左情况 AvlTree singlerotatewithLeft(AvlTree K2) { Position K1 = K2->left; K2->left = K1->right; K1->right = K2; // 更新节点高度 K2->height = max(Height(K2->left), Height(K2->right)) + 1; K1->height = max(Height(K1->left), K2->height) + 1; return K1; // 新根 } // 单旋转 - 右右情况 AvlTree singlerotatewithRight(AvlTree K2) { Position K1 = K2->right; K2->right = K1->left; K1->left = K2; // 更新节点高度 K2->height = max(Height(K2->left), Height(K2->right)) + 1; K1->height = max(Height(K1->right), K2->height) + 1; return K1; // 新根 } // 双旋转 - 左右情况 AvlTree doublerotatewithLeft(AvlTree K3) { K3->left = singlerotatewithRight(K3->left); return singlerotatewithLeft(K3); } // 双旋转 - 右左情况 AvlTree doublerotatewithRight(AvlTree K3) { K3->right = singlerotatewithLeft(K3->right); return singlerotatewithRight(K3); } // 插入新元素到AVLAvlTree Insert(int x, AvlTree T) { if (T == NULL) { // 如果为空,创建新节点 T = (AvlTree)malloc(sizeof(struct AvlNode)); if (T == NULL) printf("Out of space!!!"); else { T->element = x; T->left = T->right = NULL; T->height = 0; // 新叶节点高度为0 } } else if (x < T->element) { // 向左子插入 T->left = Insert(x, T->left); // 检查并修复平衡 if (Height(T->left) - Height(T->right) == 2) { if (x < T->left->element) T = singlerotatewithLeft(T); // 左左旋转 else T = doublerotatewithLeft(T); // 左右旋转 } } else if (x > T->element) { // 向右子插入 T->right = Insert(x, T->right); // 检查并修复平衡 if (Height(T->right) - Height(T->left) == 2) { if (x > T->right->element) T = singlerotatewithRight(T); // 右右旋转 else T = doublerotatewithRight(T); // 右左旋转 } } // 更新高度 T->height = max(Height(T->left), Height(T->right)) + 1; return T; } ``` 上述代码提供了AVL的基本框架,包括节点定义、插入操作及必要的旋转方法。实际应用中可能还需要添加更多的功能,如删除节点、查找特定值等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值