AVL树的全称是平衡搜索二叉树,本质上也是一个二叉搜索树(BST),满足BST树的所有性质。

但是我们在使用二叉搜索树的时候,我们知道通常情况在BST中搜索一个节点的时间复杂度是O(lgn)。

最坏的情况为O(n),这种情况就是出现连续的左子树/右子树,如下图所示:

这种情况其实就已经是链式存储,无法将树的优势体现出来。

为了避免这种情况,我们就要保证这个树随时都是平衡的。当然要求不能那么严格,不需要保证它完全平衡(每个节点的左右子树高度差的绝对值都为0),AVL树就要求的是只要每个节点的左右子树高度差的绝对值不超过1,就可以称作平衡。

我们将“每个节点的左右子树的高度差的绝对值”叫做平衡因子(BF)。

在AVL树中,插入一个节点之后都会判断是否打破了这个平衡。如果打破了,就需要对树进行调整,让它仍然满足平衡的定义,并且不改变中序遍历的正确性。这步操作就叫做旋转。即,是否需要旋转以及具体的旋转实现都要包含在插入函数里。

根据插入的位置不同,旋转的类型也分为4种:LL,LR,RL,RR。

旋转的几种情况:
1.插入点位于x的左孩子的左子树中。  左左LL  右旋。
2.插入点位于x的左孩子的右子树中。  左右LR    较低的先左旋,转换为LL问题,再右旋。
3.插入点位于x的右孩子的左子树中。  右左RL    较低的先右旋,转化为RR问题。再左旋。
4.插入点威武x的右孩子的右子树中。  右右RR    左旋。

接下来我们就用几个简单的例子,来分析旋转操作。

先给出AVL树的定义。

typedef struct AVLTree
{int height;                //当前节点的高度。int data;struct AVLTree* lchild;struct AVLTree* rchild;
}Tree,*pTree
  1. LL & RR

如图所示。

原本的状态是左边图所示,中序遍历为2,3.此时平衡因子分别为1,0.

在插入了一个节点之后(此时我们还没有写带调整的插入函数,可以理解为使用BST树的插入函数),我们可以看到这就成了我们最不想看见的情况——变成了链式存储。此时,我们就需要进行调整了。

情况:导致失衡的节点(1)是节点node(3)的左子树的左孩子,即为LL情况。

具体算法如下:

1.对于节点node(值为3的节点),先取它的左孩子(值为2的节点)作为临时节点temp;

2.将temp的右孩子作为node的左孩子;

3.再将node作为temp的右孩子;

4.更新height

5.node = temp。此时,temp就成为了原来node一样的存在。

下图是调整后的二叉树:

可以看到,此时还是一个BST树且中序遍历的顺序也没有发生改变,还满足了AVL的要求。

具体代码实现:

前置函数:

int GetHeight(pTree tree)            //获取当前节点的高度。
{if(tree == nullptr) return 0;return tree->height;
}bool IsBalanced(pTree tree)            //判断是否平衡。
{int BF = GetHeight(tree->lchild) - GetHeight(tree->rchild);return abs(BF) < 2;
}

LL型旋转函数:

pTree Rotate_LL(pTree tree)
{pTree temp = tree->lchild;tree->lchild = temp->rchild;temp->rchild = tree;//更新高度,先更新node再更新temp。tree->height = max(GetHeight(tree->lchild),GetHeight(tree->rchild))+1;temp->height = max(GetHeight(temp->lchild),GetHeight(temp->rchild))+1;return temp;
}

RR型由于和LL型是对称的,所以只需要将LL中的所有左右互换就可以了。

pTree Rotate_RR(pTree tree)
{pTree temp = tree->rchild;tree->rchild = temp->lchild;temp->lchild = tree;//更新高度,先更新node再更新temp。tree->height = max(GetHeight(tree->lchild),GetHeight(tree->rchild))+1;temp->height = max(GetHeight(temp->lchild),GetHeight(temp->rchild))+1;return temp;
}
  • LR & RL

接下来分析LR型:

即,引起失衡的是node节点的左子树的右孩子。 即如下图的情况:

在节点值为4的节点插入5,是4的右孩子。此时已经失衡。即为LR问题。

LR具体算法:

1.先获取node(值为10的节点)的左孩子节点,记为temp。

2.对temp进行RR。

3.对node进行LL。

代码实现:

pTree Rotate_LR(pTree tree)
{pTree temp = tree->lchild;tree->lchild = Rotate_RR(temp);return Rotate_LL(tree);
}

由于RL和LR是对称的,同样只需将所有的R换成L即可。此处不再赘述。

数据结构:AVL树的平衡调整——LL,LR,RL,RR相关推荐

  1. 2021-10-11 ! AVL树 及其平衡调整 四种情况 恋上数据结构笔记 (考过)

    b站有个up讲的很详细 https://www.bilibili.com/video/BV1xE411h7dd?from=search&seid=11383601726930144190&am ...

  2. 2021- 10 -13 AVL树的平衡调整(有parent指针) 代码逻辑

    AVL平衡调整步骤: 代码写的十分潦草而且没经过测试,看个乐,我认为应该重点看一下没有parent指针的版本,以及我认为这里重点在于理解过程. 插入结点 找到 插入节点的 的第一个 不平衡的 非父祖先 ...

  3. 数据结构-----AVL树的旋转操作

    本文主要讲解AVL的旋转操作,供自己复习用,如有不对之处请指出.另外图片是从链接处的大神那复制的,感觉文章写的很好,可以去学习. http://www.cnblogs.com/QG-whz/p/516 ...

  4. python数据结构 树_Python数据结构——AVL树的实现

    既然,我们已经证明,保持 AVL 树的平衡将会使性能得到很大的提升,那我们看看如何在程序中向树插入一个新的键值.因为所有的新键是作为叶节点插入树的,而新叶子的平衡因子为零,所以我们对新插入的节点不作调 ...

  5. 数据结构---AVL树调整方法(详)

    AVL树的调整整体分为两种: 单旋转 左单旋 右单旋 双旋转 先左单旋,再右单旋 先右单旋,再左单旋 例如:上图想要将值为40的结点插入到AVL树中,只能将其插入到值为50的左孩子结点. 这里的平衡因 ...

  6. 数据结构--Avl树的创建,插入的递归版本和非递归版本,删除等操作

    AVL树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树. 2.带有平衡条件:每个结点的左右子树的高度之差的绝对值最多为1(空树的高度为-1). 也就是说,AVL树,本质上是带了平 ...

  7. 如何构造平衡二叉树(AVL树)(LL、LR、RL、RR)

    定义:平衡二叉树是一棵二叉排序树,或者为空,或者满足以下条件: 1)左右子树高度差的绝对值不大于1: 2)左右子树都是平衡二叉树. 平衡因子:左子树的高度减去右子树的高度,显然,在平衡二叉树中,每个结 ...

  8. 数据结构-----AVL树的插入删除操作

    对于AVL的插入和删除,主要利用的就是上篇文章所述的四种旋转操作,根据插入后不同的结构选用不同的方式复原平衡. 再次声明一下,http://www.cnblogs.com/QG-whz/p/51672 ...

  9. 3. 数据结构--二叉树 BST AVL树 Huffman

    数据结构–二叉树 KEY:(不敢相信没有堆-) 二叉树的定义及其主要特征 ☑️ 二叉树的顺序存储结构和链式存储结构实现 二叉树的遍历及应用 二叉排序(查找.检索)树 (BST) 平衡的二叉检索树- A ...

最新文章

  1. android+ip+rule+策略路由,策略路由以及使用 ip route , ip rule , iptables 配置策略路由实例...
  2. DRCNN超分辨重建2016年
  3. mysql核心数据库_从MySQL基础进军MySQL核心架构 178集MySQL数据库核心基础视频教程 MySQL基础案例教程...
  4. Qt加载本地字体 .ttc或.ttf
  5. .net 面试题系列文章五(附答案)
  6. linux-关机与重启命令
  7. 可怕!中国博士留学生在美国遭枪击身亡,北大毕业,已经读到了博士第四年...
  8. spss和python stata matlab_毕业季:计量经济学实证研究中,哪款软件好(SPSS,Eviews,Matlab,stata,SAS)...
  9. mysql error 1114_ERROR 1114 (HY000): The table 'test1' is full 的解决
  10. ASP.NET Web——GridView完整增删改查示例(全篇幅包含sql脚本)大二结业考试必备技能
  11. 最近爆火的电子血氧仪是什么原理?测的准吗?
  12. form的submit与onsubmit的用法与区别
  13. 12.8 创建空白图片
  14. java 测试网速_java心跳测网速Demo
  15. nacl溶解度_氯化钠溶解度4 氯化钠溶解度不同温度的
  16. 充电计划 -- 浏览器工作流程、渲染流程
  17. 谷歌浏览器chrom兼容问题
  18. 读取sd卡里的jar包
  19. mpirun 遇到 forrtl: severe (174): SIGSEGV, segmentation fault occurred
  20. 淘宝高转化主图怎么做?大神导航,一个神奇的网站,从此开启大神之路!

热门文章

  1. Matlab2020——polyspace
  2. 复杂句变简单句 java_英语简单句变复杂句的精华!
  3. 实战:直指人心的恐惧营销应如何运用
  4. 易语言调用c 自定义数据类型,跟我入门易语言 14 自定义数据类型
  5. Cytoskeleton丨艾美捷 微管/微管蛋白体内分析生化试剂盒
  6. Comprehensive comparison of Pacific Biosciences and Oxford Nanopore Technologies and their applicati
  7. 如何将MySQL卸载干干净净
  8. 全文文字识别OCRSDK
  9. 什么是动静分离,为什么要动静分离
  10. Java将扑克牌花色和数字组合成52张扑克牌集合 并完成在牌堆中抽牌的操作