ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

数表查找之平衡二叉树

2021-12-29 14:02:27  阅读:253  来源: 互联网

标签:左子 右子 AVL 平衡 查找 二叉树 数表 节点


文章目录

1.基本概念

平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法),且具有以下性质:

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

1.1.AVL引进

为什么会出现AVL这种树型结构?

img

如上图所示,序列是一个升序树,那么当出现这种情况的时候,二叉查找树就会退化为链表,这样搜索的效率又降低了。为了解决这个问题,引进了AVL树。因为这种数据结构很好的解决了二叉查找树退化成链表的问题,把插入,查找,删除的时间复杂度最好情况和最坏情况都维持在O(logN)。但是频繁旋转会使插入和删除牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了很多。

而**对于二叉搜索树的查找效率取决于树的高度,因此保持树的高度最小,即可保证树的查找效率。**同样的序列 ,将其改为下图的方式存储,查找元素 6 时只需比较 3 次,查找效率提升一倍。

img

可以看出当节点数目一定,保持树的左右两端保持平衡,树的查找效率最高。

这种左右子树的高度相差不超过 1 的树为平衡二叉树。

1.2.AVL定义

平衡二叉查找树:简称平衡二叉树。由前苏联的数学家 Adelse-Velskil 和 Landis 在 1962 年提出的高度平衡的二叉树,根据科学家的英文名也称为 AVL 树。它具有如下几个性质:

  • 可以是空树
  • 假如不是空树,任何一个结点的左子树与右子树都是平衡二叉树,并且高度之差的绝对值不超过 1

平衡之意,如天平,即两边的分量大约相同。

1.3.AVL举例

img

上图肯定不是AVL树,因为节点60和节点66就不满足AVL树的定义。需要注意的是如果节点60不满足AVL树的定义,那么节点66也肯定就不满足AVL树的定义。

img

这个也不是AVL树,,节点66不满足AVL的定义。

img

这个就是AVL树了。

判断一棵树是不是AVL树其实有trick,你直接层序扫描以下就可以了,只要所有左右节点深度之差不大于1,那么就是AVL树了!

2.平衡因子

某节点的左子树与右子树的高度(深度)差即为该节点的平衡因子(BF,Balance Factor),平衡二叉树中不存在平衡因子大于 1 的节点。

在一棵平衡二叉树中,节点的平衡因子只能取 0 、1 、-1 ,分别对应着左右子树等高,左子树比较高,右子树比较高。

img

img

img

3.AVL树插入时失衡与调整

现在的假设是提供一个AVL树

img

然后在上图的基础上插入一个节点元素,我们来看下动图:

img

最小失衡子树:在新插入的结点向上查找,以第一个平衡因子的绝对值超过 1 的结点为根的子树称为最小不平衡子树。也就是说,一棵失衡的树,是有可能有多棵子树同时失衡的。而这个时候,我们只要调整最小的不平衡子树,就能够将不平衡的树调整为平衡的树。

平衡二叉树的失衡调整主要是通过旋转最小失衡子树来实现的。根据旋转的方向有两种处理方式,左旋右旋

旋转的目的就是减少高度,通过降低整棵树的高度来平衡。

3.1.左旋

img

加入新节点 99 后,节点 66 的左子树高度为 1,右子树高度为 3,此时平衡因子为 -2。为保证树的平衡,此时需要对节点 66 做出旋转,因为右子树高度高于左子树,对节点进行左旋操作,流程如下:

  1. 节点的右孩子替代此节点位置
  2. 右孩子的左子树变为该节点的右子树
  3. 节点本身变为右孩子的左子树

整个操作流程如下动图所示。

img

  • 节点的右孩子替代此节点位置 —— 节点 66 的右孩子是节点 77 ,将节点 77 代替节点 66 的位置
  • 右孩子的左子树变为该节点的右子树 —— 节点 77 的左子树为节点 75,将节点 75 挪到节点 66 的右子树位置
  • 节点本身变为右孩子的左子树 —— 节点 66 变为了节点 77 的左子树

3.2.右旋

  1. 节点的左孩子代表此节点
  2. 节点的左孩子的右子树变为节点的左子树
  3. 将此节点作为左孩子节点的右子树。

注意:左旋和右旋是平衡二叉树基本且重要的操作,这个是后面四种插入的基础

4.AVL四种调整方式

大家可以想象以下,如果一颗AVL树由于新插入一个元素导致为一颗不平衡树,情况无非就是四种:

  • 左节点的左子树
  • 左节点的右子树
  • 右节点的左子树
  • 右节点的右子树

4.1.LL型调整

img

LL型调整比较简单,直接右旋即可。目的是将最小失衡子树旋转为数的根结点!

4.2.LR型调整

img

由于插入元素F插入的位置是E的左子树导致A节点失衡,而E节点是A的左节点的右子树。

而我们的目的是使得原来根节点的左孩子的右孩子 E 节点成为了新的根节点

  1. 对节点B进行左旋操作

    img

  2. 对节点A进行右旋操作

img

4.3.RL型调整

由于插入元素F插入的位置是A的右节点的左子树导致A节点失衡,而D节点是A的右节点的左子树。 而我们的目的是使得原来根节点的右孩子的左孩子 D 节点成为了新的根节点

img

  1. 对节点C进行右旋操作

img

注意上面这副图中有问题,F因该为C的左节点而不是D的左节点!

  1. 对节点A进行左旋

img

注意上面这副图中有问题,F因该为C的左节点而不是D的左节点!

4.4.RR型调整

RR型调整比较简单,直接左旋即可。目的是将最小失衡子树旋转为数的根结点!

img

5.调整总结

对于插入导致AVL数不平衡的调整算法,记忆起来也是十分方便!

对于LL,RR型调整,我们的目的是将最小平衡树转为根节点,因此RR就是左旋,LL就是右旋。

对于LR,RL型调整,我们的目的是将插入节点的父节点转为根节点,RL就是先右旋再左旋,LR就是先左旋在右旋。

6.删除节点

AVL树和二叉查找树的删除操作情况一致,像网上有人还把待删除的节点分为什么叶子节点等等,其实这个你在设计算法的时候考虑进去就可以了,特别是根节点的那种情况贼坑,我记得我是用二维指针实现的!

(1条消息) 数表查找之二叉搜索树_非常规自我实现的博客-CSDN博客

删除节点是树中比较难的一个地方,上面是我写的删除节点的算法,非常的巧妙,如果看不懂可以和我交流!

总结

7.参考博客

(1条消息) 平衡二叉树_月雲之霄的博客-CSDN博客_平衡二叉树

这篇博客有AVL数据结构的实现,我就不实现了,原因在于我觉得我已经把二叉搜索树实现了,AVL在它的基础上增加了一些限制而已,并且后面又很多变种树形结构,因此我觉得知道基础实现就可以了,后面的那些知道概念就好

标签:左子,右子,AVL,平衡,查找,二叉树,数表,节点
来源: https://blog.csdn.net/qq_46359697/article/details/122214020

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有