AVL树

#pragma once

/** note
 * 简称:AVLT
 * AVL树,也叫高度平衡搜索二叉树
 * 
 * 
 * 
 * 命名:两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明解决二叉搜索树退化成单支树的方法
 * -- 所以AVL树以两位俄罗斯数学家的名的开头命名A.V.L.
 * 
 * 解决问题的方法:
 * 当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1
 * (需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。
 * 
 * AVL树的定义
 * 一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:
 * $ 它的左右子树都是AVL树
 * $ 左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)
 * balance factor(平衡因子/平衡系数) -- AVL树不一定有平衡因子(有些算法没有)
 * 
 * ? 为什么高度差不能绝对为0? 因为有些情况高度差绝对不可能为0 -- 如偶数个结点时
 * 
 * 搜索时间复杂度:log2n
 * 
 * AVL树的性能:
 * AVL树是一棵绝对平衡的二叉搜索树,其要求每个节点的左右子树高度差的绝对值都不超过1,这
 * 样可以保证查询时高效的时间复杂度,即log_2 (N)。但是如果要对AVL树做一些结构修改的操
 * 作,性能非常低下,比如:插入时要维护其绝对平衡,旋转的次数比较多,更差的是在删除时,
 * 有可能一直要让旋转持续到根的位置。因此:如果需要一种查询高效且有序的数据结构,而且数
 * 据的个数为静态的(即不会改变),可以考虑AVL树,但一个结构经常修改,就不太适合。
 * -- 纯搜索很强
 * 
 */


//AVL树的旋转
/**
 * 1.右单旋(左左,-2-1):新结点插入在较高左子树的左树 -- (设为该左子树的根为"根",不一定是整棵树的根)
 * $ 插入前,AVL树是平衡的
 * 插入后,以根的父节点为根的这棵子树不平衡 -- 设为"父根"
 * 旋转:将父根取出,根代替父根的位置,而父根取代根的右子树.如果根有右子树,则根的右子树成为父根的左子树
 * 
 * 解释:>
 * $ 根位于父根的左子树,将父根和他的右子树一起取出.左子树(根)与父根断链,且链接上父根的父亲的左子树(如果不是整个树的根的话),替代父根称为新的父根 -- 称为上提
 * $ 由于父根的值是大于根的(搜索树左小右大),所以父根取代的是根的右子树,
 * $ 若之前根有右子树,因为根的原右子树比根大,而父根又比他的左子树大,即比根的原右子树还大,所以根的原右子树插在父根的左树(父根的左树必为空,因为刚与根断链)
 * 
 * $ 如果父根是整棵树的根,则调整完后需要更新根节点
 * 助记:原有位置有子树的,被取代的,按从根开始插入,得到的位置就是新位置
 * 
 * ? 为什么叫右单旋?  可以理解成右下旋  -- 右边高右边旋
 * 
 * 2.左单旋(右右+2+1): 和右单旋一样
 * 
 * $ 单旋:你的右变我的左,我的左变你的右(先断子树后父树)
 * 
 * 
 * 
 * 3.新结点插入较高左子树的右侧(左右) :
 * $ 先左单旋再右单旋(先左子树的子(两个绝对值为1的)树旋,后两个父(两个绝对值为2的)旋)
 * 
 * 4.新结点插入较高右子树的左侧 -- (右左)
 * $: 先右单旋再左单旋
 * 
 * 
 * 
 * 注::::::::::::::::::::::::::::::::::::::::::::
 * $ 在下述例子中,图像只为具象出来写代码,举例用.实际上旋转的多种情况主要是看平衡因子
 * $ 选出四种旋转方式的例子的图并不代表所有的情况都如图,但这四种方式对应的平衡因子是所有情况
 * $ 所以算法没有问题,图要多揣摩一下
 * 
 * 
 * 实际就四种:
 * 1. /       2. \          3.    /               4.   \
 *   /            \               \                    /
 * 右旋         左旋        先左旋后右旋           先右旋后左旋
 * 
 * 
 * 
 */


//模拟实现AVL -- map底层
/**
 * 
 * 
 * insert插入
 * 1.三叉链链接到位(链接上插入的结点,新结点也要链接上父亲)
 * 2.更新平衡因子
 * $ 如果更新后所有的平衡因子都为-1,0,1其中一个,则不需要调整平衡树
 * $ 如果更新后有平衡因子的绝对值>1,则需要调整平衡树
 * 3.调整平衡树
 * 
 * note:
 * $ 新增的结点,只会影响到他祖先的这一路径的结点
 * $ 往上更新爷爷结点取决于parent的高度是否发生变化.变了则往上更新(前提是平衡状态),不变则不再更新.
 *   parent._bf如果更新后为0,说明结点插在矮树这边,使左右子树平衡,即高度不变
 *   parent._bf如果更行后为-1或1,说明左子树高或右子树高了,高度变了
 * $ 如果parent-_bf为2,则需要先处理,不能再继续更新(不再平衡)
 * 
 */
#include<assert.h>
#include<iostream>
using std::cout;
using std::endl;
using std::cin;
using std::pair;

namespace test
{


    template<class K, class V>
    struct AVLTreeNode
    {
        //三叉链: left right parent
        AVLTreeNode* _left;
        AVLTreeNode* _right;
        AVLTreeNode* _parent;
        std::pair<K, V> _kv;     //键值对
        int _bf;            //balance factor -- 平衡因子 :默认规定为右子树高度减去左子树高度

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

    template<class K, class V>
    class AVLTree
    {
    public:
        typedef AVLTreeNode<K, V> node;
    private:
        node* _root = nullptr;
    public:
        bool insert(const std::pair<K, V>& kv)
        {
            if (!_root)
            {
                _root = new node(kv);
                return true;
            }
            node* cur = _root;
            node* parent = nullptr;
            while (cur)
            {
                if (kv.first > cur->_kv.first)
                {
                    parent = cur;
                    cur = cur->_right;
                }
                else if (kv.first < cur->_kv.first)
                {
                    parent = cur;
                    cur = cur->_left;
                }
                else
                {
                    return false;
                }
            }
            cur = new node(kv);
            if (kv.first>parent->_kv.first)
            {
                parent->_right = cur;

            }
            else
            {
                parent->_left = cur;
            }
            cur->_parent = parent;
            //cur->_bf = 0;
            //cout << "插入后父亲的平衡因子:>"<<parent->_bf << " ";
            while (parent)
            {
                if (cur == parent->_left)
                {
                    --(parent->_bf);
                    //cout << "更新后父亲的平衡因子:>"<<parent->_bf << " ";
                }
                else 
                {
                    ++(parent->_bf);
                    //cout << "更新后父亲的平衡因子:>" << parent->_bf << " ";
                }

                if (parent->_bf == 0)
                {
                    break;
                }
                else if (parent->_bf == 1 || parent->_bf == -1)
                {
                    parent = parent->_parent;
                    cur = cur->_parent;
                }
                else if (parent->_bf == 2 || parent->_bf == -2)
                {
                    //
                    if (parent->_bf == 2 && cur->_bf == 1)
                    {
                        //cout << "RotateL" << " ";
                        RotateL(parent);
                    }
                    else if (parent->_bf == -2 && cur->_bf == -1)
                    {
                        //cout << "RotateR" << " ";
                        RotateR(parent);
                    }
                    else if (parent->_bf == -2 && cur->_bf == 1)
                    {
                        //cout << "RotateLR" << " ";
                        RotateLR(parent);
                    }
                    else if (parent->_bf == 2 && cur->_bf == -1)
                    {
                        //cout << "RotateRL" << " ";
                        RotateRL(parent);
                    }
                    else
                    {
                        cout << " 错误的结点的父 " << parent->_kv.first << " 错误的结点的子 " << cur->_kv.first << " ";
                        assert(false);
                    }
                    break;
                }
                else
                {
                    assert(false);
                }

            }
            //cout << endl;
            return true;
        }
    public:
        void InOrderTraversal()
        {
            _InOrderTraversal(_root);
        }

        bool isBalanceTree()
        {
            return _isBalanceTree(_root);
        }

        int Height()
        {
            return _Height(_root);
        }

    private:

        bool _isBalanceTree(node* root)
        {
            if (!root)
            {
                return true;
            }
            //左右子树高度差的模或bf的模是否小于2
            int leftH = _Height(root->_left);
            int rightH = _Height(root->_right);
            int diff = rightH - leftH;
            int Hdiff_abs = abs(rightH - leftH);
            //if (abs(root->_bf) >2 || Hdiff_abs > 2)
            //{
            //    cout << "左右子树高度差的模或bf的模大于2,key为:>" << root->_kv.first << endl;
            //    return false;
            //}

            ////左右子树的高度差的模是否为bf
            //if (diff != root->_bf)
            //{
            //    cout << "左右子树的高度差的模不等于平衡因子,key为:>"<<root->_kv.first <<" 平衡因子为: "<< root->_bf << endl;
            //    //return false;

            //}

            return abs(root->_bf) < 2
                && Hdiff_abs < 2
                && diff == root->_bf
                && _isBalanceTree(root->_left)
                && _isBalanceTree(root->_right);

        }

        int _Height(node* root)
        {
            if (!root)
            {
                return 0;
            }
            int leftH = _Height(root->_left);
            int rightH = _Height(root->_right);

            return leftH > rightH ? leftH + 1 : rightH + 1;
        }

        void _InOrderTraversal(node* root)
        {
            if (root == nullptr)
            {
                return;
            }
            _InOrderTraversal(root->_left);
            cout << "key:> " << root->_kv.first << " " << "bf:> " << root->_bf << endl;
            _InOrderTraversal(root->_right);
        }


        
        /**左单旋
         * 设x 为   x           y为   y        z为 z
         *        1   1             1                 1
         * 
         * 
         * a,b,c一定是是x,y,z三种情况之一  
         * 
         * 当c为x情况下,在经过祖先c插入的一定是符合左单旋 -- 右右(右右分别为1,c)
         * 
         *           p(parent)
         *       a        sR(subR)
         *              b(subRL)  c
         * 
         * 左单旋操作
         * 1.旋转
         * $.将b链接到p的左边 然后更新b的_parent , _parent=p(前提是b不为空)
         * $.将p链接到sR,然后更新p的_parent , _parent=sR
         * 2.更新根
         * $.如果是根(pparent==nullptr),则更新_root , _root=subR 
         * $.如果不是根,判断是祖先结点的左还是右,然后再链接上,最后记得更新_parent
         * 3.更新parent和subR的平衡因子_bf, 旋转后平衡因子都为0 
         * 
         */
        void RotateL(node* parent)//左单旋 -- parent是bf为2的结点
        {
            node* subR = parent->_right;//sR
            node* subRL = subR->_left; //b
            
            //1.将b链接到p的右边 然后更新b的parent=p(前提是b不为空)
            parent->_right = subRL;
            if (subRL)
            {
                subRL->_parent = parent;
            }

            node* pparent = parent->_parent;

            //2.将p链接到sR,然后更新p的parent=sR
            subR->_left = parent;
            parent->_parent = subR;


            //3.更新根
            if (!pparent)
            {
                _root = subR;
                _root->_parent = nullptr;
            }
            else
            {
                if (pparent->_left == parent)
                {
                    pparent->_left = subR;
                }
                else
                {
                    pparent->_right = subR;
                }
                    subR->_parent = pparent;
            }
            parent->_bf = subR->_bf = 0;

        }

        /**
         * 
         *            p(parent)
         *        sL(subL)      c  
         *       a   b(subLR)  
         * 
         */
        void RotateR(node* parent)//右单旋 -- parent是bf为-2的结点
        {
            node* subL = parent->_left;//sR    
            node* subLR = subL->_right; //b

            //1.将b链接到p的左边 然后更新b的parent=p(前提是b不为空)
            parent->_left = subLR;
            if (subLR)
            {
                subLR->_parent = parent;
            }

            node* pparent = parent->_parent;

            //2.将p链接到sL,然后更新p的parent=sL
            subL->_right = parent;
            parent->_parent = subL;


            //3.更新根
            if (parent == _root)
            {
                _root = subL;
                _root->_parent = nullptr;
            }
            else
            {
                if (pparent->_left == parent)
                {
                    pparent->_left = subL;
                }
                else
                {
                    pparent->_right = subL;
                }
                subL->_parent = pparent;
            }
            parent->_bf = subL->_bf = 0;

        }

        /**
         * 
         *                       p
         *       sL                           |d--高度h
         * |a|--高度h    sLR                   d 
         *  a          b      c--高度h-1       d
         *  a          b      c                         
         * 
         * 
         * 
         * 
         * 
         *  $ 在sLR处插入都会引发旋转,因为d矮了
         *  
         * 旋转:先左旋,后右旋
         * 
         * 1.先左旋sL结点,后右旋p结点
         * 2.更新根
         * 3.更新平衡因子
         * $.插在右边,sL为-1
         * $.插在左边,p为-1
         * $,如果插入后sLR为0(刚好sLR是新插入的),即h=0,整棵树就3结点,平衡后都是0
         *
         * 
         * 
         * 
         */
        void RotateLR(node*parent) //左右
        {
            node* subL = parent->_left;
            node* subLR = subL->_right;
            int bf = subLR->_bf;
            RotateL(parent->_left);
            RotateR(parent);
            if (bf == 1)
            {
                parent->_bf = 0;//虽然左旋和右旋已经置零,但是以防万一,安全一点,再次置零
                subLR->_bf = 0;//虽然左旋和右旋已经置零,但是以防万一,安全一点,再次置零
                subL->_bf = -1;//必须手动置零
            }
            else if (bf == -1)
            {
                parent->_bf = 1;//必须手动置零
                subLR->_bf = 0;//虽然左旋和右旋已经置零,但是以防万一,安全一点,再次置零
                subL->_bf = 0;//虽然左旋和右旋已经置零,但是以防万一,安全一点,再次置零
            }
            else if (bf == 0)
            {
                parent->_bf = 0;
                subLR->_bf = 0;
                subL->_bf = 0;
            }
            else//以防万一,安全一点
            {
                assert(false);
            }
        }

        /**
         * 
         *                       p
         *    |a--高度h                  sR                          
         *     a              sRL                 |d|--高度h  
         *     a            b      c--高度h-1      d          
         *                  b      c               d                     
         * 
         */
        void RotateRL(node* parent) //右左
        {
            node* subR = parent->_right;
            node* subRL = subR->_left;
            int bf = subRL->_bf;
            RotateR(parent->_right);
            RotateL(parent);
            if (bf == 1) //插在右边,右边平衡,左边不平衡
            {
                subR->_bf = 0;
                parent->_bf = -1;
                subRL->_bf = 0;
            }
            else if (bf == -1) //插在左边,左边平衡,右边不平衡
            {
                subR->_bf = 1;
                parent->_bf = 0;
                subRL->_bf = 0;
            }
            else if (bf == 0)
            {
                subR->_bf = 0;
                parent->_bf = 0;
                subRL->_bf = 0;
            }
            else//以防万一,安全一点
            {
                assert(false);
            }
        }


    
    };

    void test_AVL1()
    {
        int arr[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 }; //结点7:左右 结点9:右 结点26:左 结点18:右左 结点15:左右
        //int arr[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 }; //只有一个右左,结点6
        test::AVLTree<int, int> t;
        for (auto i : arr)
        {
            cout << "i:>" << i << "\t";
            t.insert(std::make_pair(i,i));
            cout << endl;
        }
        t.InOrderTraversal();
        cout << "是否为AVL树? " << t.isBalanceTree() << endl;
    }

#include<time.h>
    void test_AVL2()
    {
        srand((size_t)time(0));
        const size_t N = 5000000;
        test::AVLTree<int, int> t;
        for (size_t i = 0; i < N; ++i)
        {
            size_t x = rand() + i;
            //size_t x = rand() * i - rand();
            //cout << "x:>" << x << "\t";
            t.insert(std::make_pair(x, x));
        }
        //cout << t.isBalanceTree()<<endl;
        cout << "AVLT高度:>" << t.Height() << endl;
    }
}

 

#pragma once
/** note * 简称:AVLT * AVL树,也叫高度平衡搜索二叉树 *  *  *  * 命名:两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明解决二叉搜索树退化成单支树的方法 * -- 所以AVL树以两位俄罗斯数学家的名的开头命名A.V.L. *  * 解决问题的方法: * 当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1 * (需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。 *  * AVL树的定义 * 一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树: * $ 它的左右子树都是AVL树 * $ 左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1) * balance factor(平衡因子/平衡系数) -- AVL树不一定有平衡因子(有些算法没有) *  * ? 为什么高度差不能绝对为0? 因为有些情况高度差绝对不可能为0 -- 如偶数个结点时 *  * 搜索时间复杂度:log2n *  * AVL树的性能: * AVL树是一棵绝对平衡的二叉搜索树,其要求每个节点的左右子树高度差的绝对值都不超过1,这 * 样可以保证查询时高效的时间复杂度,即log_2 (N)。但是如果要对AVL树做一些结构修改的操 * 作,性能非常低下,比如:插入时要维护其绝对平衡,旋转的次数比较多,更差的是在删除时, * 有可能一直要让旋转持续到根的位置。因此:如果需要一种查询高效且有序的数据结构,而且数 * 据的个数为静态的(即不会改变),可以考虑AVL树,但一个结构经常修改,就不太适合。 * -- 纯搜索很强 *  */

//AVL树的旋转/** * 1.右单旋(左左,-2-1):新结点插入在较高左子树的左树 -- (设为该左子树的根为"根",不一定是整棵树的根) * $ 插入前,AVL树是平衡的 * 插入后,以根的父节点为根的这棵子树不平衡 -- 设为"父根" * 旋转:将父根取出,根代替父根的位置,而父根取代根的右子树.如果根有右子树,则根的右子树成为父根的左子树 *  * 解释:> * $ 根位于父根的左子树,将父根和他的右子树一起取出.左子树(根)与父根断链,且链接上父根的父亲的左子树(如果不是整个树的根的话),替代父根称为新的父根 -- 称为上提 * $ 由于父根的值是大于根的(搜索树左小右大),所以父根取代的是根的右子树, * $ 若之前根有右子树,因为根的原右子树比根大,而父根又比他的左子树大,即比根的原右子树还大,所以根的原右子树插在父根的左树(父根的左树必为空,因为刚与根断链) *  * $ 如果父根是整棵树的根,则调整完后需要更新根节点 * 助记:原有位置有子树的,被取代的,按从根开始插入,得到的位置就是新位置 *  * ? 为什么叫右单旋?  可以理解成右下旋  -- 右边高右边旋 *  * 2.左单旋(右右+2+1): 和右单旋一样 *  * $ 单旋:你的右变我的左,我的左变你的右(先断子树后父树) *  *  *  * 3.新结点插入较高左子树的右侧(左右) : * $ 先左单旋再右单旋(先左子树的子(两个绝对值为1的)树旋,后两个父(两个绝对值为2的)旋) *  * 4.新结点插入较高右子树的左侧 -- (右左) * $: 先右单旋再左单旋 *  *  *  * 注:::::::::::::::::::::::::::::::::::::::::::: * $ 在下述例子中,图像只为具象出来写代码,举例用.实际上旋转的多种情况主要是看平衡因子 * $ 选出四种旋转方式的例子的图并不代表所有的情况都如图,但这四种方式对应的平衡因子是所有情况 * $ 所以算法没有问题,图要多揣摩一下 *  *  * 实际就四种: * 1. /       2. \          3.    /               4.   \ *   /            \               \                    / * 右旋         左旋        先左旋后右旋           先右旋后左旋 *  *  *  */

//模拟实现AVL -- map底层/** *  *  * insert插入 * 1.三叉链链接到位(链接上插入的结点,新结点也要链接上父亲) * 2.更新平衡因子 * $ 如果更新后所有的平衡因子都为-1,0,1其中一个,则不需要调整平衡树 * $ 如果更新后有平衡因子的绝对值>1,则需要调整平衡树 * 3.调整平衡树 *  * note: * $ 新增的结点,只会影响到他祖先的这一路径的结点 * $ 往上更新爷爷结点取决于parent的高度是否发生变化.变了则往上更新(前提是平衡状态),不变则不再更新. *   parent._bf如果更新后为0,说明结点插在矮树这边,使左右子树平衡,即高度不变 *   parent._bf如果更行后为-1或1,说明左子树高或右子树高了,高度变了 * $ 如果parent-_bf为2,则需要先处理,不能再继续更新(不再平衡) *  */#include<assert.h>#include<iostream>using std::cout;using std::endl;using std::cin;using std::pair;
namespace test{

template<class K, class V>struct AVLTreeNode{//三叉链: left right parentAVLTreeNode* _left;AVLTreeNode* _right;AVLTreeNode* _parent;std::pair<K, V> _kv;     //键值对int _bf;            //balance factor -- 平衡因子 :默认规定为右子树高度减去左子树高度
AVLTreeNode(const std::pair<K, V>& kv):_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), _bf(0){}};
template<class K, class V>class AVLTree{public:typedef AVLTreeNode<K, V> node;private:node* _root = nullptr;public:bool insert(const std::pair<K, V>& kv){if (!_root){_root = new node(kv);return true;}node* cur = _root;node* parent = nullptr;while (cur){if (kv.first > cur->_kv.first){parent = cur;cur = cur->_right;}else if (kv.first < cur->_kv.first){parent = cur;cur = cur->_left;}else{return false;}}cur = new node(kv);if (kv.first>parent->_kv.first){parent->_right = cur;
}else{parent->_left = cur;}cur->_parent = parent;//cur->_bf = 0;//cout << "插入后父亲的平衡因子:>"<<parent->_bf << " ";while (parent){if (cur == parent->_left){--(parent->_bf);//cout << "更新后父亲的平衡因子:>"<<parent->_bf << " ";}else {++(parent->_bf);//cout << "更新后父亲的平衡因子:>" << parent->_bf << " ";}
if (parent->_bf == 0){break;}else if (parent->_bf == 1 || parent->_bf == -1){parent = parent->_parent;cur = cur->_parent;}else if (parent->_bf == 2 || parent->_bf == -2){//if (parent->_bf == 2 && cur->_bf == 1){//cout << "RotateL" << " ";RotateL(parent);}else if (parent->_bf == -2 && cur->_bf == -1){//cout << "RotateR" << " ";RotateR(parent);}else if (parent->_bf == -2 && cur->_bf == 1){//cout << "RotateLR" << " ";RotateLR(parent);}else if (parent->_bf == 2 && cur->_bf == -1){//cout << "RotateRL" << " ";RotateRL(parent);}else{cout << " 错误的结点的父 " << parent->_kv.first << " 错误的结点的子 " << cur->_kv.first << " ";assert(false);}break;}else{assert(false);}
}//cout << endl;return true;}public:void InOrderTraversal(){_InOrderTraversal(_root);}
bool isBalanceTree(){return _isBalanceTree(_root);}
int Height(){return _Height(_root);}
private:
bool _isBalanceTree(node* root){if (!root){return true;}//左右子树高度差的模或bf的模是否小于2int leftH = _Height(root->_left);int rightH = _Height(root->_right);int diff = rightH - leftH;int Hdiff_abs = abs(rightH - leftH);//if (abs(root->_bf) >2 || Hdiff_abs > 2)//{//cout << "左右子树高度差的模或bf的模大于2,key为:>" << root->_kv.first << endl;//return false;//}
////左右子树的高度差的模是否为bf//if (diff != root->_bf)//{//cout << "左右子树的高度差的模不等于平衡因子,key为:>"<<root->_kv.first <<" 平衡因子为: "<< root->_bf << endl;////return false;
//}
return abs(root->_bf) < 2&& Hdiff_abs < 2&& diff == root->_bf&& _isBalanceTree(root->_left)&& _isBalanceTree(root->_right);
}
int _Height(node* root){if (!root){return 0;}int leftH = _Height(root->_left);int rightH = _Height(root->_right);
return leftH > rightH ? leftH + 1 : rightH + 1;}
void _InOrderTraversal(node* root){if (root == nullptr){return;}_InOrderTraversal(root->_left);cout << "key:> " << root->_kv.first << " " << "bf:> " << root->_bf << endl;_InOrderTraversal(root->_right);}

/**左单旋 * 设x 为   x           y为   y        z为 z *        1   1             1                 1 * a,b,c一定是是x,y,z三种情况之一   * 当c为x情况下,在经过祖先c插入的一定是符合左单旋 -- 右右(右右分别为1,c) *           p(parent) *       a        sR(subR) *              b(subRL)  c * 左单旋操作 * 1.旋转 * $.将b链接到p的左边 然后更新b的_parent , _parent=p(前提是b不为空) * $.将p链接到sR,然后更新p的_parent , _parent=sR * 2.更新根 * $.如果是根(pparent==nullptr),则更新_root , _root=subR  * $.如果不是根,判断是祖先结点的左还是右,然后再链接上,最后记得更新_parent * 3.更新parent和subR的平衡因子_bf, 旋转后平衡因子都为0  */void RotateL(node* parent)//左单旋 -- parent是bf为2的结点{node* subR = parent->_right;//sRnode* subRL = subR->_left; //b//1.将b链接到p的右边 然后更新b的parent=p(前提是b不为空)parent->_right = subRL;if (subRL){subRL->_parent = parent;}
node* pparent = parent->_parent;
//2.将p链接到sR,然后更新p的parent=sRsubR->_left = parent;parent->_parent = subR;

//3.更新根if (!pparent){_root = subR;_root->_parent = nullptr;}else{if (pparent->_left == parent){pparent->_left = subR;}else{pparent->_right = subR;}subR->_parent = pparent;}parent->_bf = subR->_bf = 0;
}
/** *            p(parent) *        sL(subL)      c   *       a   b(subLR)   */void RotateR(node* parent)//右单旋 -- parent是bf为-2的结点{node* subL = parent->_left;//sRnode* subLR = subL->_right; //b
//1.将b链接到p的左边 然后更新b的parent=p(前提是b不为空)parent->_left = subLR;if (subLR){subLR->_parent = parent;}
node* pparent = parent->_parent;
//2.将p链接到sL,然后更新p的parent=sLsubL->_right = parent;parent->_parent = subL;

//3.更新根if (parent == _root){_root = subL;_root->_parent = nullptr;}else{if (pparent->_left == parent){pparent->_left = subL;}else{pparent->_right = subL;}subL->_parent = pparent;}parent->_bf = subL->_bf = 0;
}
/** *                       p *       sL                           |d--高度h * |a|--高度h    sLR                   d  *  a          b      c--高度h-1       d *  a          b      c                          *  $ 在sLR处插入都会引发旋转,因为d矮了 *   * 旋转:先左旋,后右旋 * 1.先左旋sL结点,后右旋p结点 * 2.更新根 * 3.更新平衡因子 * $.插在右边,sL为-1 * $.插在左边,p为-1 * $,如果插入后sLR为0(刚好sLR是新插入的),即h=0,整棵树就3结点,平衡后都是0 * */void RotateLR(node*parent) //左右{node* subL = parent->_left;node* subLR = subL->_right;int bf = subLR->_bf;RotateL(parent->_left);RotateR(parent);if (bf == 1){parent->_bf = 0;//虽然左旋和右旋已经置零,但是以防万一,安全一点,再次置零subLR->_bf = 0;//虽然左旋和右旋已经置零,但是以防万一,安全一点,再次置零subL->_bf = -1;//必须手动置零}else if (bf == -1){parent->_bf = 1;//必须手动置零subLR->_bf = 0;//虽然左旋和右旋已经置零,但是以防万一,安全一点,再次置零subL->_bf = 0;//虽然左旋和右旋已经置零,但是以防万一,安全一点,再次置零}else if (bf == 0){parent->_bf = 0;subLR->_bf = 0;subL->_bf = 0;}else//以防万一,安全一点{assert(false);}}
/** *                       p *    |a--高度h                  sR                           *     a              sRL                 |d|--高度h   *     a            b      c--高度h-1      d           *                  b      c               d                      */void RotateRL(node* parent) //右左{node* subR = parent->_right;node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);if (bf == 1) //插在右边,右边平衡,左边不平衡{subR->_bf = 0;parent->_bf = -1;subRL->_bf = 0;}else if (bf == -1) //插在左边,左边平衡,右边不平衡{subR->_bf = 1;parent->_bf = 0;subRL->_bf = 0;}else if (bf == 0){subR->_bf = 0;parent->_bf = 0;subRL->_bf = 0;}else//以防万一,安全一点{assert(false);}}

};
void test_AVL1(){int arr[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 }; //结点7:左右 结点9:右 结点26:左 结点18:右左 结点15:左右//int arr[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 }; //只有一个右左,结点6test::AVLTree<int, int> t;for (auto i : arr){cout << "i:>" << i << "\t";t.insert(std::make_pair(i,i));cout << endl;}t.InOrderTraversal();cout << "是否为AVL树? " << t.isBalanceTree() << endl;}
#include<time.h>void test_AVL2(){srand((size_t)time(0));const size_t N = 5000000;test::AVLTree<int, int> t;for (size_t i = 0; i < N; ++i){size_t x = rand() + i;//size_t x = rand() * i - rand();//cout << "x:>" << x << "\t";t.insert(std::make_pair(x, x));}//cout << t.isBalanceTree()<<endl;cout << "AVLT高度:>" << t.Height() << endl;}}
posted @ 2024-02-27 22:38  HJfjfK  阅读(25)  评论(0编辑  收藏  举报