说说平衡二阶树|平衡二阶树(AVL树)是如何实现自平衡的

997 阅读5分钟

这是我参与更文挑战的第4天,活动详情查看: 更文挑战

hello 艾瑞巴得,坚持四篇啦!!!这篇文章的代价是一把头发,这把头发小编先掉为敬!

秃顶.gif

前言:

在数据结构中树、图是数据结构标志性产物,我们今天讲的二叉树是一种比较有用的折中方案。数组的搜索比较方便,可以直接用下标,但删除或者插入某些元素就比较麻烦。链表与之相反,删除和插入元素很快,但查找很慢。二叉树就既有链表的好处,也有数组的好处。在处理大批量的动态的数据是比较有用。在某种场景下,使用树结构会更加方便因为树结构是非线性,可以表示一对多,比如文件的目录结构等;

我们都知道对于二叉查找树和二叉树的各种遍历,但是其查找效率不稳定会出现“斜树”的情况,这个时候二叉平衡树就应运而生了,二叉平衡树的用途更多,查找相比之下也更稳定;这个大家可以想象一下Mysql的搜索引擎:MyISAMInnoDB

平衡二叉树

平衡二叉树条件:

二叉树的每一个节点的左右子树的深度差不超过1

平衡二叉树如何实现自平衡:

然而当出现“斜树”的情况的时候,平衡二叉树会通过通过旋转,来保持树的平衡,旋转分为以下四种类型:

以下图片:由 A、B、C、E、F表示树的节点,节点旁边的数字表示当前节点左右子树的深度,图画的比较潦草,给大家详细的介绍一下,大家可以跟着我的思路走一遍,相信大家就能理解了

  1. LL型(右旋):在左子树的左孩子上添加新的节点

图片.png 从左向右

  1. 图1当前树结构是平衡的,他的每一个节点的左右子树深度,最大为1,满足平衡树条件
  2. 图2向左树的左孩节点添加一个新的节点F这个时候可以看到,我们的跟节点的左右子树的深度为2,这个时候不满足平衡树条件了,这么办呢?我们的重点出来了,接着向下看👇
  3. 图3是我们经过右旋的之后的实现平衡的二叉树,我们可以看到原来的子节点B向右旋转成为跟节点,A节点也向右旋转成为B节点的子节点,原来B节点的右子节点也向右旋转成为A节点的左子节点,这个时候完成旋转,可以看到这次每个节点左右子树的深度最大为C节点为1,满足条件,实现自平衡;

给大家网上找了一个生动的 右旋 动图,可以看着理解一下 a128dcef81954e7847bf5073c76fd42f.gif

2、RR型(左旋):在右子树的右孩子上添加新的节点

图片.png 从左向右

  1. 图1当前树结构是平衡的,他的每一个节点的左右子树深度,最大为1,满足平衡树条件
  2. 图2向右树的右孩节点添加一个新的节点F这个时候可以看到,我们的跟节点的左右子树的深度为2,这个时候便不满足平衡树条件了;
  3. 图3是我们经过左旋的之后的实现平衡的二叉树,卖个关子,大家可以自己思考一下,通过是这么通过左旋实现的,想到了可以写到评论区哦!哈哈哈~嗝~ 让大家体验一下社会的险恶😁

3、LR型(先左旋(失衡子树)再右旋):在左子树的右孩子上添加新节点

图片.png 从左向右

  1. 图1当前树结构是平衡的,他的每一个节点的左右子树深度,最大为1,满足平衡树条件
  2. 图2向左树的右孩节点添加一个新的节点F这个时候可以看到,我们的跟节点的左右子树的深度为2,这个时候便不满足平衡树条件了;
  3. 图3是我们图里画圈的那个局部的树结构经过左旋的之后的形成一个LL形的树结构;
  4. 图4是我们进过初步左旋得到的LL形树结构 在通过一次 右旋(同上面第一个例子),从而实现自平衡;

4、RL型(先右旋(失衡子树)再左旋):在右子树的左孩子上添加新节点

图片.png 从左向右

  1. 图1当前树结构是平衡的,他的每一个节点的左右子树深度,最大为1,满足平衡树条件
  2. 图2向右树的左孩节点添加一个新的节点F这个时候可以看到,我们的跟节点的左右子树的深度为2,这个时候便不满足平衡树条件了;
  3. 图3是我们图里画圈的那个局部的树结构经过右旋的之后的形成一个LL形的树结构;
  4. 图4是我们进过初步右旋得到的LL形树结构 在通过一次 左旋(同上面第二个例子),从而实现自平衡;

当然,除了插入,AVL还有删除等其他操作,(原理相似。删除后平衡)有兴趣可以一起研究

AVL树:

AVL树是带有平衡条件的二叉查找树,左右子树树高不超过1,AVL树是严格的平衡二叉树,平衡条件必须满足(所有节点的左右子树高度差不超过1)。因此它也被称为高度平衡树。

ok!文章到此就结束了,AVL的理解需要时间,当然笔者的AVL自己写的可能有些疏漏,希望可以对大家有帮助,让大家少走一些弯路,有不对的地方希望大家可以提出来的,共同成长;

细节之中只有天地,整洁成就卓越代码