平衡二叉树

介绍:
AVL树也就是平衡二叉树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。

平衡因子:
节点的平衡因子是它的右子树的高度减去它的左子树的高度(有时相反)。带有平衡因子1、0或 -1的节点被认为是平衡的。带有平衡因子 -2或2的节点被认为是不平衡的,并需要重新平衡这个树。平衡因子可以直接存储在每个节点中,或从可能存储在节点中的子树高度计算出来。

操作:
AVL树的基本操作一般涉及运作同在不平衡的二叉查找树所运作的同样的算法。但是要进行预先或随后做一次或多次所谓的”AVL旋转”。

实现描述:
假设平衡因子是右子树的高度减去左子树的高度所得到的值,又假设由于在二叉排序树上插入节点而失去平衡的最小子树根节点的指针为a(即a是离插入点最近,且平衡因子绝对值超过1的祖先节点),则失去平衡后进行的规律可归纳为下列四种情况:

单向右旋平衡处理LL:由于在*a的左子树根节点的左子树上插入节点,*a的平衡因子由1增至2,致使以*a为根的子树失去平衡,则需进行一次右旋转操作;
单向左旋平衡处理RR:由于在*a的右子树根节点的右子树上插入节点,*a的平衡因子由-1变为-2,致使以*a为根的子树失去平衡,则需进行一次左旋转操作;
双向旋转(先左后右)平衡处理LR:由于在*a的左子树根节点的右子树上插入节点,*a的平衡因子由1增至2,致使以*a为根的子树失去平衡,则需进行两次旋转(先左旋后右旋)操作。
双向旋转(先右后左)平衡处理RL:由于在*a的右子树根节点的左子树上插入节点,*a的平衡因子由-1变为-2,致使以*a为根的子树失去平衡,则需进行两次旋转(先右旋后左旋)操作

下面以插入一组数为例做详细介绍:
如插入数据{16, 3, 7, 11, 9, 26, 18, 14, 15}
平衡之后的图为:
这里写图片描述

先插入16和3,插入之后为:
这里写图片描述

插入7:

插入没调节如下图:
这里写图片描述
此时已经不满足平衡:
调节之后为:
这里写图片描述

插入11:
这里写图片描述
此时平衡不需要调节

插入9:
这里写图片描述
可以看出此时已经不平衡,需要调节
右旋调节之后为:
这里写图片描述
可以看出平衡了

插入26:
这里写图片描述
此时不平衡。
需要左旋:
调节之后为:
这里写图片描述

插入18:
这里写图片描述
此时不平衡。

调节之后为:
这里写图片描述

插入14:
这里写图片描述
平衡,不用调节。

插入15:
这里写图片描述
此时不平衡。

调节之后为:
这里写图片描述

代码:

#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
template<class K,class V>
struct AVLTreeNode
{
    K _key;
    V _value;
    AVLTreeNode<K, V>* _left;
    AVLTreeNode<K, V>* _right;
    AVLTreeNode<K, V>* _parent;
    int _bf;  //平衡因子 可以是 0 1 -1
    AVLTreeNode(const K& key, const V& value)
        :_key(key),
        _value(value),
        _left(NULL),
        _right(NULL),
        _parent(NULL),
        _bf(0)
    {}
};

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

    bool Insert(const K& key, const V& value)
    {
        if (_root == NULL)
        {
            _root = new Node(key, value);
            return true;
        }
        Node* cur = _root;
        Node* parent = NULL;
        /*查找插入的位置*/
        while (cur)
        {
            if (cur->_key > key)
            {
                parent = cur;
                cur = cur->_left;
            }
            else if (cur->_key < key)
            {
                parent = cur;
                cur = cur->_right;
            }
            else
            {
                return false;
            }
        }
        Node* tmp = new Node(key, value);  //插入数据
        if (parent->_key > key)
        {
            parent->_left = tmp;
            tmp->_parent = parent;
        }
        else
        {
            parent->_right = tmp;
            tmp->_parent = parent;
        }
        //调节平衡因子
        cur = tmp;
        bool isRotate = false;
        /*查看需不需要调节*/
        while (parent)
        {
            /*变换parent的平衡因子*/
            if (parent->_left == cur)
            {
                parent->_bf--;
            }
            else
            {
                parent->_bf++;
            }
            if (parent->_bf == 0)//一定是由1或-1变得,不会影响上层
            {
                break;
            }
            else if (parent->_bf == 1 || parent->_bf == -1) //继续上调
            {
                cur = parent;
                parent=cur->_parent;
            }

            /*进行旋转*/
            else//已经不平衡了
            {
                if (parent->_bf == 2)
                {
                    if (cur->_bf == 1)
                    {
                        _RotateL(parent);
                    }
                    else // -1
                    {
                        _RotateRL(parent);
                    }
                }
                else // -2
                {
                    if (cur->_bf == -1)
                    {
                        _RotateR(parent);
                    }
                    else // 1
                    {
                        _RotateLR(parent);
                    }
                }

                isRotate = true;
                break;
            }
        }
        if (isRotate)
        {
            Node* ppNode = parent->_parent;
            if (ppNode == NULL)
                _root = parent;
            else if (ppNode->_key > parent->_key)
                ppNode->_left = parent;
            else
                ppNode->_right = parent;
        }

        return true;
    }

    void InOrder()
    {
        _InOrder(_root);
    }

    bool IsBlance()
    {
        return _IsBlance(_root);
    }

protected:
    int _Height(Node* root)
    {
        if (root == NULL)
        {
            return 0;
        }
        int left=_Height(root->_left);
        int right=_Height(root->_right);
        return left > right ? left + 1 : right + 1;
    }
    bool _IsBlance(Node* root)
    {
        if (root == NULL)
        {
            return true;
        }
        int bf = _Height(root->_right) - _Height(root->_left);
        //assert(bf == root->_bf);

        if (bf != root->_bf)
        {
            cout << "平衡因子异常:" << root->_key << endl;
        }

        return bf == root->_bf && abs(bf) < 2;

    }
    void _InOrder(Node* root)
    {
        if (root == NULL)
        {
            return;
        }
        _InOrder(root->_left);
        cout << root->_key << " ";
        _InOrder(root->_right);
    }
    void _RotateL(Node*& parent)
    {
        Node* subR = parent->_right;
        Node* subRL = subR->_left;
        parent->_right = subRL;
        if (subRL)
        {
            subRL->_parent = parent;
        }
        subR->_left = parent;
        subR->_parent = parent->_parent;
        parent->_parent = subR;
        parent->_bf = subR->_bf = 0;
        parent = subR;
    }

    void _RotateR(Node*& parent)
    {
        Node* subL = parent->_left;
        Node* subLR = subL->_right;
        parent->_left = subLR;
        if (subLR)
        {
            subLR->_parent = parent;
        }
        subL->_right = parent;
        subL->_parent = parent->_parent;
        parent->_parent = subL;
        parent->_bf = subL->_bf = 0;
        parent = subL;
    }

    void _RotateLR(Node* parent)
    {
        Node* pNode = parent;
        Node* subL = parent->_left;
        Node* subLR = subL->_right;
        int bf = subLR->_bf;
        _RotateL(parent->_left);
        _RotateR(parent);

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

        subLR->_bf = 0;
    }



    void _RotateRL(Node*& parent)
    {
        Node* pNode = parent;
        Node* subRNode = parent->_right;
        Node* subRLNode = subRNode->_left;
        int bf = subRLNode->_bf;

        _RotateR(parent->_right);
        _RotateL(parent);

        if (bf == 1)
        {
            subRNode->_bf = 0;
            pNode->_bf = -1;
        }
        else if (bf == -1)
        {
            subRNode->_bf = 1;
            pNode->_bf = 0;
        }
        else
        {
            subRNode->_bf = 0;
            pNode->_bf = 0;
        }

        subRLNode->_bf = 0;
    }
private:
    Node* _root;
};


void test()
{
    AVLTree<int ,int> t;
    t.Insert(1, 1);
    t.Insert(2, 1);
    t.Insert(3, 1);
    t.Insert(4, 1);
    t.Insert(5, 1);
    t.InOrder();
    bool ret=t.IsBlance();
    cout << ret << endl;
}

int main()
{
    test();
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值