二叉搜索树只有保持平衡时其查找效率才会高。

要保持二叉搜索树的平衡不是一件易事。不过还是有一些非常经典的办法可以做到,其中最好的方法就是将二叉搜索树实现为AVL树

AVL树得名于它的发明者 G.M. Adelson-Velsky 和 E.M. Landis,他们在 1962 年的论文 "An algorithm for the organization of information" 中发表了它。AVL树是一种特殊类型的二叉树,它的每个结点都保存一份额外的信息:结点的平衡因子

结点的平衡因子 = 左子树的高度 - 右子树的高度

插入和删除操作都会导致AVL树的自我调整(自我平衡),使得所有结点的平衡因子保持为+1、-1或0。

当子树的根结点的平衡因子为+1时,它是左倾斜的(left-heavy)。

当子树的根结点的平衡因子为 -1时,它是右倾斜的(right-heavy)。

一颗子树的根结点的平衡因子就代表该子树的平衡性

保持所有子树几乎都处于平衡状态,AVL树在总体上就能够基本保持平衡

AVL树的基本查找、插入结点的操作和二叉树的操作一样。但是,当向AVL树中插入一个结点后,还有一些额外的工作要做。首先,必须计算因插入操作对平衡因子带来的改变。其次,如果任何平衡因子变成了+/-2,就必须从这个结点开始往下重新平衡这颗树,这个重新平衡的过程就称为旋转

AVL树的旋转

旋转操作用来重新平衡树的某个部分。通过重新安排结点 ,使结点之间的关系始终保持左子结点小于父结点,父结点小于右子结点。使得该树仍然是一颗二叉搜索树。旋转过后,旋转子树中的所有结点的平衡因子都为+1、-1或0

AVL树的旋转类型有4种, 分别是LL(left-left)旋转、LR(left-right)旋转、RR(right-right)旋转和RL(right-left)旋转。

为方便理解在何时执行哪一种旋转,设x代表刚插入AVL树中的结点,设A为离x最近且平衡因子更改为2的绝对值的祖先。可以归纳为下面4种处理情况:

LL旋转

如下图所示,当x位于A的左子树的左子树上时,执行LL旋转

设left为A的左子树,要执行LL旋转,将A的左指针指向left的右子结点,left的右指针指向A,将原来指向A的指针指向left

旋转过后,将A和left的平衡因子都改为0。所有其他结点的平衡因子没有发生变化。

LR旋转

当x位于A的左子树的右子树上时,执行LR旋转。

设left是A的左子结点,并设A的子孙结点grandchild为left的右子结点。

要执行LR旋转,将left的右子结点指向grandchild的左子结点grandchild的左子结点指向leftA的左子结点指向grandchild的右子结点再将grandchild的右子结点指向A最后将原来指向A的指针指向grandchild

执行LR旋转之后,调整结点的平衡因子取决于旋转前grandchild结点的原平衡因子值

如果grandchild结点的原始平衡因子为+1,就将A的平衡因子设为-1,将left的平衡因子设为0。

如果grandchild结点的原始平衡因子为0,就将A和left的平衡因子都设置为0。

如果grandchild结点的原始平衡因子为-1,就将A的平衡因子设置为0,将left的平衡因子设置为+1。

在所有的情况下,grandchild的新平衡因子都是0。所有其他结点的平衡因子都没有改变。

RR旋转

当x位于A的左子树的右子树上时,执行RR旋转。

RR旋转与LL旋转是对称的关系。

设A的右子结点为Right。要执行RR旋转,将A的右指针指向right的左子结点,right的左指针指向A,原来指向A的指针修改为指向right

完成旋转以后,将A和left的平衡因子都修改为0。所有其他结点的平衡因子都没有改变。

RL旋转

当x位于A的右子树的左子树上时,执行RL旋转

RL旋转与LR旋转是对称的关系。

设A的右子结点为right,right的左子结点为grandchild。要执行RL旋转,将right结点的左子结点指向grandchild的右子结点,将grandchild的右子结点指向right,将A的右子结点指向grandchild的左子结点,将grandchild的左子结点指向A,最后将原来指向A的指针指向grandchild。

执行RL旋转以后,调整结点的平衡因子取决于旋转前grandchild结点的原平衡因子。这里也有三种情况需要考虑:

如果grandchild的原始平衡因子值为+1,将A的平衡因子更新为0,right的更新为-1;

如果grandchild的原始平衡因子值为  0,将A和right的平衡因子都更新为0;

如果grandchild的原始平衡因子值为-1,将A的平衡因子更新为+1,right的更新为0;

在所有情况中,都将grandchild的新平衡因子设置为0。所有其他结点的平衡因子不发生改变。

来源:https://www.cnblogs.com/idreamo/p/8308336.html

二叉搜索树的平衡--AVL树和树的旋转的更多相关文章

  1. 二叉搜索树的平衡--AVL树和树的旋转(图解)

    二叉搜索树只有保持平衡时其查找效率才会高. 要保持二叉搜索树的平衡不是一件易事.不过还是有一些非常经典的办法可以做到,其中最好的方法就是将二叉搜索树实现为AVL树. AVL树得名于它的发明者 G.M. ...

  2. 把二叉搜索树转化成更大的树 · Convert BST to Greater Tree

    [抄题]: 给定二叉搜索树(BST),将其转换为更大的树,使原始BST上每个节点的值都更改为在原始树中大于等于该节点值的节点值之和(包括该节点). Given a binary search Tree ...

  3. LIntcode---将二叉搜索树转成较大的树

    Given a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original B ...

  4. [LC]235题 二叉搜索树的最近公共祖先 (树)(递归)

    ①题目 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 x 是 p.q 的祖先 ...

  5. Java实现 LeetCode 530 二叉搜索树的最小绝对差(遍历树)

    530. 二叉搜索树的最小绝对差 给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值. 示例: 输入: 1 \ 3 / 2 输出: 1 解释: 最小绝对差为 1,其中 2 ...

  6. 动态平衡二叉搜索树的简易实现,Treap 树

    http://blog.csdn.net/qichi_bj/article/details/8232048

  7. 算法二叉搜索树之AVL树

    最近学习了二叉搜索树中的AVL树,特在此写一篇博客小结. 1.引言 对于二叉搜索树而言,其插入查找删除等性能直接和树的高度有关,因此我们发明了平衡二叉搜索树.在计算机科学中,AVL树是最先发明的自平衡 ...

  8. 数据结构之二叉搜索树、AVL自平衡树

    前言 最近在帮公司校招~~ 所以来整理一些数据结构方面的知识,这些知识呢,光看一遍理解还是很浅的,看过跟动手做过一遍的同学还是很容易分辨的哟~ 一直觉得数据结构跟算法,就好比金庸小说里的<九阳神 ...

  9. 二叉树、二叉搜索树、平衡二叉树、B树、B+树的精确定义和区别探究

    概述 关于树的概念很多,B树,B+树,红黑树等等. 但是你去翻翻百度百科,或者用百度或者谷歌搜索一下中文的树结构的介绍,全都是狗屁.没有哪个中文网站是真正精确解释树的定义的,尤其是百度百科. 下面我要 ...

随机推荐

  1. hitTest,UIWindow sendEvent ,touchbegan, 响应链

    https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/using_responders_and_th ...

  2. Generalizations

    Generalizations Congratulations! You've learned five commands commonly used to navigate the filesyst ...

  3. java中封装类(一)

    java中封装类共九个,分别是Boolean,Byte,Short,Integer,Long,Float,Double,Character,Void 其中Void对于使用者并无多大意义,也不可以构造任 ...

  4. ReactiveX 学习笔记(23)RxCpp

    RxCpp RxCpp 是 ReactiveX 的 C++ 语言实现. 下载 RxCpp $ git clone --recursive https://github.com/ReactiveX/Rx ...

  5. jQuery formValidator API

    jQuery formValidator插件的API帮助 目前支持5种大的校验方式,分别是:inputValidator(针对input.textarea.select控件的字符长度.值范围.选择个数 ...

  6. MySQL的安装流程与入门

    MySQl是一种关系型数据库,存放的是文字数据,它是以“表”的形式进行存储的.由于MySQl的实用性和不收费,它在世界上是应用最多的数据库,但是,它不支持大量数据写入.接下来,我将为大家分享一下我学习 ...

  7. SpringJDBC中jdbcTemplate 的使用

    一:定义 SpringJDBC是spring官方提供的一个持久层框架,对JDBC进行了封装,提供了一个JDBCTemplated对象简化JDBC的开发.但Spring本身不是一个orm框架,与hibe ...

  8. 【JAVA】杨辉三角

    ソース public Yanghui3jiao() { List<String[]> rowList = new ArrayList<String[]>(); List< ...

  9. Flask最强攻略 - 跟DragonFire学Flask - 第九篇 Flask 中的蓝图(BluePrint)

    蓝图,听起来就是一个很宏伟的东西 在Flask中的蓝图 blueprint 也是非常宏伟的 它的作用就是将 功能 与 主服务 分开怎么理解呢? 比如说,你有一个客户管理系统,最开始的时候,只有一个查看 ...

  10. linux查询公网ip

    查询公网ip[出口IP] 1.curl icanhazip.com 2.curl ipecho.net/plain 3.curl www.trackip.net/i