AVL树的基本概念

  AVL树是一种高度平衡的(height balanced)二叉搜索树:对每一个结点x,x的左子树与右子树的高度差(平衡因子)至多为1。

  有人也许要问:为什么要有AVL树呢?它有什么作用呢?

  我们先来看看二叉搜索树吧(因为AVL树本质上是一棵二叉搜索树),假设有这么一种极端的情况:二叉搜索树结点的插入顺序为1,2,3,4,5,也就是:

                  

 

  显而易见,这棵二叉搜索树已经其退化成一个链表了,也就是说,它在查找上的优势已经全无了—— 在这种情况下,查找一个结点的时间复杂度是O(n)!

  如果这棵二叉搜索树是AVL树,在插入顺序仍为1,2,3,4,5的情况下,树的形状如下图:

                  

  可以看出,AVL树基本操作的最坏时间复杂度要比普通的二叉搜索树低—— 除去可能的插入操作外(我们将假设懒惰删除),它是O(logn)。

  而插入操作隐含着困难的原因在于,插入一个节点可能破坏AVL树的性质(例如,将6插入到上图的AVL树中会破坏根节点2的平衡条件),如果发生这种情况,就要在插入操作结束之前恢复平衡的性质。事实上,这总可以通过对树进行简单的修正来做到,我们称其为旋转

  AVL树的旋转

  在AVL树中,假设有一个结点的平衡因子为2(最大就是2,因为结点是一个一个地插入到树中的,一旦出现不平衡的状态就会立即进行调整),我们把这个必须重新平衡的结点叫做被破坏点α。这种不平衡只可能是下面四种情况造成的:

  1. 对α的左儿子的左子树进行了一次插入,即LL情况。
  2. 对α的左儿子的右子树进行了一次插入,即LR情况。
  3. 对α的右儿子的左子树进行了一次插入,即RL情况。
  4. 对α的右儿子的右子树进行了一次插入,即RR情况。

  情形1和4是关于结点α的镜像对称,2和3也是关于结点α的镜像对称。因此,理论上只有两种情况:第一种情况是插入发生在“外边”的情况(即LL情况或RR情况),第二种情况是插入发生在“内部”的情况(即LR情况或RL情况)。

  

  在AVL树中插入结点后,用于保持树的平衡的旋转操作步骤如下:

  步骤一:沿着插入点到根结点的路径检查结点的平衡因子,找到途中第一个不满足AVL树性质的结点,这个结点就是被破坏点α。

  步骤二:从被破坏点α开始沿着该路径向下再标记连续的两个结点β、γ,这三个点就是旋转过程将要涉及的三个点(这些点中不一定包括插入点,旋转会使β或γ成为新的根,另外两个点作为根的左右儿子,其他结点根据AVL树的性质放置即可)。

  步骤三:判断插入点与被破坏点α之间的关系属于上述四种情况中的哪一种:如果是插入发生在“外边”的情况(即LL的情况或RR的情况),只需要以β为新的根结点顶替被破坏点α的位置进行进行一次单旋转即可完成调整;如果是插入发生在“内部”的情形(即LR的情况或RL的情况),只需要以γ为新的根结点顶替被破坏点α的位置进行稍微复杂的双旋转即可完成调整。

          

                        (1) LL基本情况

                    

          

                        (2) RR基本情况

            

                        (3) LR基本情况

          

                        (4) RL基本情况

  实例分析

  下面给出了一个向AVL树中插入关键字的实例,在已给AVL树的基础上插入9(图中虚线表示),沿着插入点9到根节点的路径发现第一个高度不平衡的结点6,即被破坏点;从被破坏点6开始沿着该路径向下标记6,10,7为α,β,γ;插入点9位于被破坏点6的右儿子10的左子树上,所以属于RL状况;以γ结点7为新的根节点顶替被破坏点6的位置,α结点6和β结点10分别为γ结点7的左右儿子,其他结点根据AVL树的性质放置即可得到右侧的AVL树。

  在上面AVL树的基础上继续插入8(图中虚线表示),沿着插入点8到根节点的路径发现第一个高度不平衡的结点为根节点4,即被破坏点;从被破坏点4开始沿着该路径向下标记4,7,10为α,β,γ;插入点8位于被破坏点4的右儿子7的右子树上,所以属于RR状况;以β结点7为新的根节点顶替被破坏点4的位置,α结点4和γ结点10分别为β结点7的左右儿子,其他结点根据AVL树的性质放置即可得到右侧的AVL树。

  

  AVL树是最早的平衡二叉树之一,应用相对其他数据结构较少。Windows对进程地址空间的管理用到了AVL树

  参考资料:   《算法导论第3版》—— 习题 13-3 AVL树

          《数据结构与算法分析—Java语言描述》—— 4.4 AVL树

          http://blog.chinaunix.net/uid-25324849-id-2182877.html

       

高度平衡的二叉搜索树(AVL树)的更多相关文章

  1. 树-二叉搜索树-AVL树

    树-二叉搜索树-AVL树 树 树的基本概念 节点的度:节点的儿子数 树的度:Max{节点的度} 节点的高度:节点到各叶节点的最大路径长度 树的高度:根节点的高度 节点的深度(层数):根节点到该节点的路 ...

  2. lintcode_177_把排序数组转换为高度最小的二叉搜索树

    把排序数组转换为高度最小的二叉搜索树   描述 笔记 数据 评测 给一个排序数组(从小到大),将其转换为一棵高度最小的排序二叉树. 注意事项 There may exist multiple vali ...

  3. lintcode: 把排序数组转换为高度最小的二叉搜索树

    题目: 把排序数组转换为高度最小的二叉搜索树 给一个排序数组(从小到大),将其转换为一棵高度最小的排序二叉树. 样例 给出数组 [1,2,3,4,5,6,7], 返回 4 / \ 2 6 / \ / ...

  4. lintcode.177 把排序数组转换为高度最小的二叉搜索树

    把排序数组转换为高度最小的二叉搜索树    描述 笔记 数据 评测 给一个排序数组(从小到大),将其转换为一棵高度最小的排序二叉树. 注意事项 There may exist multiple val ...

  5. 看动画学算法之:平衡二叉搜索树AVL Tree

    目录 简介 AVL的特性 AVL的构建 AVL的搜索 AVL的插入 AVL的删除 简介 平衡二叉搜索树是一种特殊的二叉搜索树.为什么会有平衡二叉搜索树呢? 考虑一下二叉搜索树的特殊情况,如果一个二叉搜 ...

  6. (4) 二叉平衡树, AVL树

    1.为什么要有平衡二叉树? 上一节我们讲了一般的二叉查找树, 其期望深度为O(log2n), 其各操作的时间复杂度O(log2n)同时也是由此决定的.但是在某些情况下(如在插入的序列是有序的时候), ...

  7. HDU 3179 二叉搜索树(树的建立)

    二叉搜索树 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  8. 平衡二叉搜索树AVL

    package com.sunshine.AlgorithmTemplate; import com.sunshine.OFFER66_SECOND.BalanceTreeNode; import c ...

  9. 平衡二叉搜索树/AVL二叉树 C实现

    //AVTree.h #ifndef MY_AVLTREE_H #define MY_AVLTREE_H typedef int ElementType; struct TreeNode { Elem ...

随机推荐

  1. SQL Server显式事务与隐式事务

    事务是单个的工作单元.如果某一事务成功,则在该事务中进行的所有数据修改均会提交,成为数据库中的永久组成部分.如果事务遇到错误且必须取消或回滚,则所有数据库修改均被清除. SQL Server中有一下几 ...

  2. jquery的colorbox关闭并传递数据到父窗

    function closebox(para1, para2) { var k = parent;// 父窗口对象 k.document.getElementById("para1" ...

  3. CentOS PPTP配置FreeRADIUS+DaloRADIUS实现高级用户控制+流量控制

    前提条件 阅读本文前,您需要搭建好PPTP,如果仍未搭建,可以参考:http://www.xj123.info/2301.html 如果您需要配置DaloRADIUS,那么您还需要安装LAMP,可以参 ...

  4. python 多线程和多核

    昨天在一个群里面遇到的,使用py做计算,只有1个CPU在跑任务,其它的怠工. 在py3以后,提供了:concurrent.futures mark 如下; 官方文档: 16.6. multiproce ...

  5. “LC.exe”已退出,代码为 -1

    造成这个问题的原因一般是引入了第三方插件,自己遇到的问题是引入了devexpress...... 1.找到Properties文件夹licenses.licx文件,然后右键选择删除就可以了,调试运行正 ...

  6. 解决Linux下Tomcat日志目录下的catalina.log日志文件过大的问题

    本文摘自:(http://blog.csdn.net/stevencn76/article/details/6246162) 分类: Java技术专区2011-03-13 12:25 5017人阅读  ...

  7. 注册Github

    注册Github 1.打开Github网页 2.设置用户名.邮箱.密码(右侧会显示是否可以使用),点击注册 3.此时邮箱会发来来自Github的注册消息,进入邮箱,点连接,完成注册 4.注册成功

  8. bzoj 2761: [JLOI2011]不重复数字

    #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #d ...

  9. qq快速聊天

    和女朋友聊天的时候,每次发完消息我都习惯性把聊天界面关了,或者我想找女朋友聊天了,又要打开主界面再打开聊天窗口 每次感觉特别麻烦.所以我在想有没有一个好的办法直接打开聊天窗口的.刚好这两天又在写jav ...

  10. 设计模式之二:MVC

    模型(Model) 视图(View) 控制器(Controller) (MVC) 是 Cocoa 中的一种行为模块,并且也是所有 Cocoa 设计模式中使用最多的.在程序中按照它们的角色来分类这些对象 ...