AVL树平衡旋转详解

概述

AVL树又叫做平衡二叉树。前言部分我也有说到,AVL树的前提是二叉排序树(BST或叫做二叉查找树)。由于在生成BST树的过程中可能会出现线型树结构,比如插入的顺序是:1, 2, 3, 4, 5, 6, 7..., n。在BST树中,比较理想的状况是每个子树的左子树和右子树的高度相等,此时搜索的时间复杂度是log(N)。可是,一旦这棵树演化成了线型树的时候,这个理想的情况就不存在了,此时搜索的时间复杂度是O(N),在数据量很大的情况下,我们并不愿意看到这样的结果。

现在我们要做的事就是让BST在创建的过程中不要向线型树发展。方法就是让其在添加新节点的时候,不断调整树的平衡状态。

定义:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

AVL树实现

1.节点失衡

我们对于节点平衡有这样的定义:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。而这里提到的高度差,就是我们下面会引入的平衡因子:BF(balance factor)。

因为AVL树说到底还是一个二叉树,只有两个子节点。而且节点失衡的发生,是因为有一个新节点的插入,这个新插入的节点导致了某些节点左右子节点高度的不一致。所以我们可以枚举出以下4种情况的失衡状态。

(1)在一个节点的左子树的左子树上插入一个新节点。即LL。在这种情况下,我们可以通过将节点右旋使其平衡。如图-2所示

图-2 LL单右旋操作

原A的左孩子B变为父结点,A变为其右孩子,而原B的右子树变为A的左子树,注意旋转之后Brh是A的左子树。

(2)在一个节点的右子树的右子树上插入一个新节点。即RR。在这种情况下,我们可以通过将节点左旋使其平衡。如图-3所示;

图-3 RR单左旋操作

这时只需要把树向左旋转一次即可,如图所示,原A右孩子B变为父结点,A变为其左孩子,而原B的左子树Blh将变为A的右子树。

(3)在一个节点的左子树的右子树上插入一个新节点。即LR。在这种情况下,我们不能直接通过将节点左旋或右来使其平衡了。这里需要两步来完成,先让树中高度较低的进行一次左旋(RR型),这个时候就变成了LL了。再进行一次单右旋操作即可。如图-4所示;

图-4 LR先左旋再右旋操作

这时需要旋转两次,仅一次的旋转是不能够使二叉树再次平衡。如图所示,在B节点按照RR型向左旋转一次之后,二叉树在A节点仍然不能保持平衡,这时还需要再向右旋转一次。

(4)在一个节点的右子树的左子树上插入一个新节点。即RL。在这种情况下,我们不能直接通过将节点左旋或右来使其平衡了。这里需要两步来完成,先让树中高度较低的进行一次右旋,这个时候就变成了RR了。再进行一次单左旋操作即可。如图-5所示;

图-5 RL先右旋再左旋操作

平衡二叉树某一节点的右孩子的左子树上插入一个新的节点,使得该节点不再平衡。同样,这时需要旋转两次,旋转方向刚好同LR型相反。

从上面对节点失衡的说明,以及图解。我想你已经对旋转的操作有了一个大概地认识了吧。从图中我们也可以看出,LL型和RR型、LR型和RL型是两个行为很相似地操作。其实他们互为对称。

代码见这里

AVL树平衡旋转详解的更多相关文章

  1. 数据结构-AVL树的旋转

    http://blog.csdn.net/GabrieL1026/article/details/6311339 平衡二叉树在进行插入操作的时候可能出现不平衡的情况,AVL树即是一种自平衡的二叉树,它 ...

  2. AVL树的JAVA实现及AVL树的旋转算法

    1,AVL树又称平衡二叉树,它首先是一颗二叉查找树,但在二叉查找树中,某个结点的左右子树高度之差的绝对值可能会超过1,称之为不平衡.而在平衡二叉树中,任何结点的左右子树高度之差的绝对值会小于等于 1. ...

  3. AVL树的旋转操作详解

    [0]README 0.0) 本文部分idea 转自:http://blog.csdn.net/collonn/article/details/20128205 0.1) 本文仅针对性地分析AVL树的 ...

  4. AVL树的旋转

    平衡二叉树在进行插入操作的时候可能出现不平衡的情况,AVL树即是一种自平衡的二叉树,它通过旋转不平衡的节点来使二叉树重新保持平衡,并且查找.插入和删除操作在平均和最坏情况下时间复杂度都是O(log n ...

  5. AVL树的旋转实现

    AVL树:带有平衡条件的二叉查找树,即一棵AVL树是其每个节点的左子树和右子树的高度最多相差1的二叉查找树.一般通过Single Rotate和Double Rotate来保持AVL树的平衡.AVL树 ...

  6. B树与B+详解

    承接上篇SQLite采用B树结构使得SQLite内存占用资源较少,本篇将讲述B树的具体操作(建树,插入,删除等操作).在看博客时,建议拿支笔和纸,一点一点操作,毕竟知识是自己的,自己也要消化的.本篇通 ...

  7. P3384 【模板】树链剖分 题解&&树链剖分详解

    题外话: 一道至今为止做题时间最长的题: begin at 8.30A.M 然后求助_yjk dalao后 最后一次搞取模: awsl. 正解开始: 题目链接. 树链剖分,指的是将一棵树通过两次遍历后 ...

  8. BIT 树状数组 详解 及 例题

    (一)树状数组的概念 如果给定一个数组,要你求里面所有数的和,一般都会想到累加.但是当那个数组很大的时候,累加就显得太耗时了,时间复杂度为O(n),并且采用累加的方法还有一个局限,那就是,当修改掉数组 ...

  9. IOS6屏幕旋转详解(自动旋转、手动旋转、兼容IOS6之前系统)

    转自 http://blog.csdn.net/zzfsuiye/article/details/8251060 概述: 在iOS6之前的版本中,通常使用 shouldAutorotateToInte ...

随机推荐

  1. numpy 广播

    http://blog.csdn.net/hongxingabc/article/details/53149655 https://zhuanlan.zhihu.com/p/20878530

  2. 【linux】crontab失效

    在linux上,crontab任务全部使用完整路径,但是任务无效. 检测crontab 服务是否启动, /etc/init.d/cron status /etc/init.d/cron restart

  3. Jmeter录制浏览器并回放

    确认证书 1.查看证书 进入Jmeter安装目录下的bin,找到ApacheJMeterTemporaryRootCA.crt 证书文件(如jmeter在安装目录中未找到,可尝试先执行下面的开始录制步 ...

  4. python 全栈开发,Day126(创业故事,软件部需求,内容采集,显示内容图文列表,MongoDB数据导入导出JSON)

    作业讲解 下载代码: HBuilder APP和flask后端登录 链接:https://pan.baidu.com/s/1eBwd1sVXTNLdHwKRM2-ytg 密码:4pcw 如何打开APP ...

  5. CenOS下安装 Git,Git的初始设置,添加文件,提交文件

    一.配置DNS 1,配置DNSvi /etc/resolv.conf加入: 代码如下: nameserver 192.168.0.1 nameserver 8.8.8.8 nameserver 8.8 ...

  6. 2018-2019 2 20165203 《网络对抗技术》 Exp4 恶意代码分析

    2018-2019 2 20165203 <网络对抗技术> Exp4 恶意代码分析 实验要求 监控你自己系统的运行状态,看有没有可疑的程序在运行. 分析一个恶意软件,就分析Exp2或Exp ...

  7. ThreadLocal详解,处理成员变量线程不安全的情况

    ThreadLocal翻译成中文比较准确的叫法应该是:线程局部变量. 这个玩意有什么用处,或者说为什么要有这么一个东东?先解释一下,在并发编程的时候,成员变量如果不做任何处理其实是线程不安全的,各个线 ...

  8. JavaScript中利用Ajax 实现客户端与服务器端通信(九)

    一:Ajax (Asynchronous JavaScript and XML)不是一个新的技术,事实上,它是一些旧有的成熟的技术以一种全新的更加强大的方式整合在一起 Ajax的关键技术: 1.使用X ...

  9. Hibernate之关联关系映射(一对多和多对一映射,多对多映射)

    ~~~接着之前的Hibernate框架接着学习(上篇面试过后发现真的需要学习一下框架了,不然又被忽悠让去培训.)~~~ 1:Hibernate的关联映射,存在一对多和多对一映射,多对多映射: 1.1: ...

  10. [转] 通过jQuery Ajax使用FormData对象上传文件

    FormData对象,是可以使用一系列的键值对来模拟一个完整的表单,然后使用XMLHttpRequest发送这个"表单". 在 Mozilla Developer 网站 使用For ...