当前位置:   article > 正文

AVL树(高度平衡的二叉搜索树)平衡因子的调节和旋转_avl可以不调整最小因子吗

avl可以不调整最小因子吗

1.什么叫AVL树

                   AVL树又称为高度平衡的二叉搜索树,它能保持二叉树的高度平衡,尽量降低二叉树的高度,减少树的平均搜索长度(尽量使这棵树保持为完全二叉树,这样就能提高搜索效率)。

2.AVL树的性质

       (1)左子树和右子树的高度之差的绝对值不超过1

          (2) 树中的每个左子树和右子树都是AVL树  

          (3) 每个节点都有一个平衡因子(balance factor--bf),任一节点的平衡因子是-1,0,1。(每个节点的平衡因子等于右子树的高度减去左子  树的高度)


3.AVL树节点的定义
  1. template <typename K,typename V>
  2. struct AVLTreeNode
  3. {
  4. K _key;
  5. V _value;
  6. int _bf; //平衡因子,只能取值为-1,1,0
  7. AVLTreeNode<K, V>* _left;
  8. AVLTreeNode<K, V>* _right;
  9. AVLTreeNode<K, V>* _parent;
  10. AVLTreeNode(const K& key, const V& value)
  11. :_key(key)
  12. , _value(value)
  13. , _bf(0)
  14. , _left(NULL)
  15. , _right(NULL)
  16. , _parent(NULL)
  17. {}
  18. };



4.AVL树左单旋的情况



对应代码实现:

  1. void _RotateL(Node* &parent)
  2. {
  3. //1.将要修改的结点标记起来
  4. Node* SubR = parent->_right;
  5. Node* SubRL = SubR->_left;
  6. Node* pparent = parent->_parent;
  7. //2.重新链上SubR结点
  8. SubR->_left = parent;
  9. SubR->_parent = pparent;
  10. SubR->_bf = 0;
  11. //4.重新链上parent结点
  12. parent->_right = SubRL;
  13. parent->_parent = SubR;
  14. parent->_bf = 0;
  15. //5.改变pparent的指向结点
  16. if (pparent == NULL)
  17. _root = SubR;
  18. else if (pparent->_left == parent)
  19. pparent->_left = SubR;
  20. else
  21. pparent->_right = SubR;
  22. //4.重新链上SubRL结点
  23. if (SubRL != NULL)
  24. SubRL->_parent = parent;
  25. }



5.AVL树右单旋的情况


对应的代码实现:

  1. void _RotateR(Node* &parent)
  2. {
  3. //1.将要修改的结点标记起来
  4. Node* SubL = parent->_left;
  5. Node* SubLR = SubL->_right;
  6. Node* pparent = parent->_parent;
  7. //2.重新链上SubL结点
  8. SubL->_right = parent;
  9. SubL->_parent = parent->_parent;
  10. SubL->_bf = 0;
  11. //3.重新链上parent结点
  12. parent->_left = SubLR;
  13. parent->_parent = SubL;
  14. parent->_bf = 0;
  15. //4.改变pparent的指向结点
  16. if (pparent == NULL)
  17. _root = SubL;
  18. else if (pparent->_left == parent)
  19. pparent->_left = SubL;
  20. else
  21. pparent->_right = SubL;
  22. //5.重新链上SubRL结点
  23. if (SubLR != NULL)
  24. SubLR->_parent = parent;
  25. }


6.AVL树平衡因子的调节

     (1)插入的数据只能影响祖先结点的平衡因子;
    
     (2)当某个平衡因子从0变成1或者-1,需要继续调整祖先结点的平衡因子,直到根节点;
     
     (3)当某个平衡因子从-1或者1变成0,则不需要调整祖先的平衡因子了,因为平衡因子在插入数据之后变成0,证明整棵树的高度没有发生变化;


     (4)当平衡因子在插入数据之后变成-2或者2,需要通过旋转来降低它的高度,使它继续保持AVL树的性质

7.AVL树进行左右双旋的情况(注意平衡因子的调节




代码实现:

  1. void _RotateLR(Node* &parent)
  2. {
  3. //双旋的时候在某些情况下会导致bf发生异常
  4. Node* SubL = parent->_left;
  5. Node* SubLR = SubL->_right;
  6. int bf = SubLR->_bf;
  7. _RotateL(parent->_left);
  8. _RotateR(parent);
  9. if (bf == -1)
  10. {
  11. parent->_bf = 1;
  12. SubL->_bf = 0;
  13. }
  14. else if (bf == 1)
  15. {
  16. parent->_bf = 0;
  17. SubL->_bf = -1;
  18. }
  19. else
  20. {
  21. SubL->_bf = parent->_bf = 0;
  22. }
  23. SubLR->_bf = 0;
  24. }

8.同样的方法可以得到右左双旋时平衡因子的变化


                  (1)SubRL->_bf==0   parent->_bf=SubR->_bf=0;

  (2)SubRL->_bf==-1  parent->_bf=0  SubR->_bf=1;

  (3)SubRL->_bf==1   parent->_bf=-1 SubR->_bf=0;

代码实现:
  1. void _RotateRL(Node* &parent)
  2. {
  3. Node* SubR = parent->_right;
  4. Node* SubRL = SubR->_left;
  5. int bf = SubRL->_bf;
  6. _RotateR(parent->_right);
  7. _RotateL(parent);
  8. if (bf == 1)
  9. {
  10. parent->_bf = -1;
  11. SubR->_bf = 0;
  12. }
  13. else if (bf == -1)
  14. {
  15. parent->_bf = 0;
  16. SubR->_bf = 1;
  17. }
  18. else
  19. {
  20. SubR->_bf = parent->_bf = 0;
  21. }
  22. SubRL->_bf = 0;
  23. }






声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/246170
推荐阅读
相关标签
  

闽ICP备14008679号