当前位置: 首页 > news >正文

平衡的二叉搜索树 —— AVL树

AVL树的引入 :

在二叉搜索树插入的数据有序时,二叉搜索树会退化为单链,这时效率就由 (O(logN),降为了 O(N)),为了保证效率。

G.M. Adelson-Velsky和E.M. Landis在1962年发明,通过把树旋转使得二叉搜索树每个左右子树高度差不超过1 , 就平衡了树的高度保证了O(logN)的效率

AVL树的性质 : 

1.  AVL树每个左右子树高度差不超过1 

2. 每个节点都有一个平衡因子,该平衡因子定义为左子树高度减去右子树高度。对于AVL树中的每一个节点,其平衡因子只能是-1, 0, 或者 1。


3. 自平衡机制:当向AVL树中插入或删除节点后,如果树失去了平衡,即某个节点的平衡因子不再是-1, 0, 或1,则通过一系列旋转操作来恢复平衡。

AVL树的旋转介绍(主要以插入为例):

                      

我们引入平衡因子,和三叉链(作用是维护平衡因子)去实现 AVL树

AVLTree的insert:

                           前面的步骤跟二叉搜索树的插入没啥区别(就是双指针法),主要是如何更新平衡因子

                           如果平衡因子等于2,则要开始旋转树了

 更新平衡因子 :

                         因为平衡因子是右子树高度减去左子树高度,所以有一个非常重要的规则

                         1. 插入的是右边,那么右子树高度+1,平衡因子+1

                         2. 插入的是左边,那么左子树高度+1,平衡因子 - 1

                        如图,插入在8的左边,所以 8 的平衡因子 = 1 - 1 = 0          

插入在9的右边,所以9的平衡因子 = 0 + 1 = 1;

在插入后,改节点的1因子有 3 种情况 即   = 0 , = +-1 ,= +-2;

分类讨论了 :

 1 . 插入后等于0,说明整棵树的高度没有变化,这次的插入就是补了同高度一个的空位

      插入成功

2.插入后等于 +-1 , 说明整棵树的高度变化了,要算祖先的平衡因子(插入只影响祖先的平衡因子)

这时,9的平衡因子等于 1 , 我们去判断 8的平衡因子, 发现9是8的右孩子

                         1. 插入的是右边,那么右子树高度+1,平衡因子+1

                         2. 插入的是左边,那么左子树高度+1,平衡因子 - 1

 )

这时 8 的平衡因子更新为 1 + 1 = 2 ;

这就不满足平衡搜索树了,开始旋转调整该树

     

左右旋转( 要会画图 ) :

                需要调整的为直线形时(一边高),就单旋转就可解决问题

               一边高对于60来说是左边高,对于30来说是也是左边高。

 

               通过左右旋转可以使这颗树的高度平衡

               旋转的要求 :

                                   1. 保证旋转后还是一颗二叉搜索树

                                   2. 平衡因子为2的节点要变为平衡

               1.左单旋 :

                            

                 如图,subR大于parent ,   大于b,所以他有资格当该子树的新根

                 parent旋转下来连接到subR的右边,b链到parent的右边,subR做这颗子树的新根

                 这就实现了同时满足两个条件

 

                 2.右单旋 :  与左单转同理

                    

                   如图 : 30 小于b,小于60,有资格当他们的新根

                               把60旋转下来链接到30的右边,b链接60的左边,30作为这颗子树的新根

 

 两次旋转 :

                当需要旋转的是折线形(不是一边高的情况),先要旋转一次让树达到一边高,然后就返回

                上面笔记的情况。

               对于90,是左边高,对于30是右边高,先左单旋到直线形(一边高),后右单旋

                  对于另一种方向同理解决   , 先右单旋,后左单旋       

 

平衡因子的调节:    因为单次旋转都能复用上面的,而插入在b或c最后的平衡因子结果是不一样的,

                              

 

 

易错点 :

         

          1.这是3叉链,旋转时忘记调整父节点的关系

             答: 没有调整父节点之间的关系

             在旋转中,  b,parent,subR的父亲都变了

 

            2.忘记了subR要顶替parent新子树的根

                  1. 如果 parent本来就是该树的根 ,那就让subR当新大根

                  2. 如果 parent本身是一颗子树的根,那么让subR当新的子树根

                   第一种情况就是 if语句里面的 

                   第二种情况就是 else 语句里面的 (ppNode 是 parent的父亲)

                  关键就是看ppNode到底存不存在

AVL树的应用 :

AVL树是绝对平衡,如果经常插入经常要进行旋转,旋转是有消耗的 ,所以STL  map和set的底层其实是相对平衡的红黑树,红黑树我们会在后面介绍

由于AVL树要保证绝对平衡,所以在实际应用中,如果只是侧重查找可以用AVL树,如果要经常的增删,那么用相对平衡的空黑树

AVL树的实现代码(C++):

1.  树节点的成员 

     使用三叉链 , 维护左右孩子和父亲 ,_bf 维护平衡因子

2 . 右单旋转

注意好好维护平衡因子和parent

3. 左单旋转 

     注意好好维护平衡因子和parent

4 . 先左后右双旋 

双旋可以复用单旋 ,一定要注意维护好平衡因子

4. 先右后左双旋

双旋可以复用单旋 ,一定要注意维护好平衡因子


http://www.mrgr.cn/news/66652.html

相关文章:

  • 【数据结构与算法】第9课—数据结构之二叉树(链式结构)
  • Web Broker(Web服务应用程序)入门教程(1)
  • QML----复制指定下标的ListModel数据
  • Redis学习:BigKey、缓存双写一致性更新策略和案例
  • strncpy_s
  • 叉车智能管理系统,简化现场管理!
  • 基于java+SpringBoot+Vue的旅游管理系统设计与实现
  • 小菜家教平台(二):基于SpringBoot+Vue打造一站式学习管理系统
  • 【JAVA】Java基础—基础语法:控制结构(条件语句、循环结构)
  • 省级-财政分权数据(2000-2022年)
  • redis学习万字详解(一)
  • 鸿蒙跳转商店应用页面(给我评分功能)
  • 跳表原理-课堂笔记
  • 职业院校关于大数据、云计算和物联网传感器技术的结合与应用探讨
  • TensorRT-LLM的k8s弹性伸缩部署方案
  • 用 Python 自动检测交易图形态的实用指南请查收
  • 【Rust Crate之Actix Web(一)】
  • i2c-tools 4.3 for Android 9.0
  • Redis完全指南:从基础功能到缓存管理与高可用性设计
  • 解决SRS推送webrtc流卡顿问题
  • Java多线程的几种常见写法
  • w023基于web学生宿舍管理系统的设计与开发
  • 谈谈“项目复盘会议”怎么组织
  • 空间解析几何6:空间圆柱体的离散化表示【附MATLAB代码】
  • GB/T 28046.3-2011 道路车辆 电气及电子设备的环境条件和试验 第3部分:机械负荷(10)
  • 独孤思维:图书电商远程诊断,差点晕倒