树型数据结构

原文:https://www.studytonight.com/advanced-data-structures/avl-tree

AVL 树是另一种特殊的树,它有几个特性使它特别。这些是:

  • 这是一个本质上平衡的 BST。

  • 它是自我平衡的。

  • 它不是完全平衡的。

  • 每个子树也是一个 AVL 树。

AVL 树的图示如下所示:

AVL Tree

当被解释时,我们可以说这是一个高度平衡的二叉查找树。高度平衡表示每个节点的左右子树高度之差不能大于 1(即高度(左)-高度(右)< = 1 )。

AVL Tree with Balance Factor

请注意,上面的 BST 中的每个节点都包含两个值,左值表示该节点的左子树的高度,右值表示该节点的右子树的高度,可以看出,在没有一个节点上,我们的值差大于 1,因此使其成为平衡的 AVL Tree。

一个自平衡树意味着当我们试图在这个 BST 中插入任何元素,如果它违反了任何节点的平衡因子,那么它会相应地动态旋转自己,使自己自平衡。众所周知,AVL 树是第一个被提出的著名的动态平衡树。

它不是完美平衡的,完美平衡意味着每个节点的右子树和左子树之间的高度等于 0

完美平衡自动车辆定位树的图示如下所示:

Perfectly Balanced AVL Tree

上述 AVL 树的所有节点的平衡因子等于 0( 高度(左)-高度(右)= 0 ),使其成为完美的 AVL 树。还需要注意的是,一个完美的 BST 和一个完美的 AVL 树是一样的。如果我们仔细看看上面所有的图形表示,我们可以清楚地看到,AVL 树的每个子树也是一个 AVL 树。

现在我们再来看两个图片,其中一个是 AVL 树,一个不是。

Difference

虽然上面的两棵树都是 BST,但是上面的图中只有左边的 BST 是 AVL 树,因为它高度平衡。在右 BST 中,我们有两个违规节点(即 8 和 10),在这两种情况下,平衡因子都大于 2。需要注意的是,这个树可以通过一定的方式进行旋转,使其成为 AVL 树。

为什么是 AVL 树?

当我们已经有了类似的数据结构(即 BST 的)时,为什么我们还需要它的复杂版本呢?。答案在于,BST 在某些场景中有一些限制,使得搜索、插入等操作成本很高(与O(n)一样高)。

考虑下面两个 BST 的图示:

BST difference

左 BST 的高度为O(logn),右 BST 的高度为O(n),因此左 BST 的搜索操作时间复杂度为O(logn),右偏斜的为O(n),这也是其最坏的情况。因此,如果我们有这样一个倾斜的树,那么使用 BST 就没有任何好处,因为当涉及到时间和空间复杂度时,它就像一个链表。

这就是为什么我们需要一个平衡的 BST,这样所有的基本操作都保证了 O(logN)的时间复杂度。

树旋转

如果 AVL 树遇到任何违反平衡因子的情况,那么它会尝试做一些旋转来使树再次平衡。总共有四次旋转,我们将逐一查看。主要有:

  • 向左旋转

  • 右旋转

  • 左右旋转

  • 左右旋转

1.向左旋转

当违规发生在违规节点的左子节点的左子树中时,将执行此循环。考虑下面一个不平衡的 BST 的图形表示,为了做到这一点,我们将做一些旋转。

Right Skewed AVL

很明显,这不是一个 AVL 树,但是考虑到违规发生的节点,我们把这个节点作为一个枢纽来进行我们的旋转。右边的树很重,导致问题的节点是 17,如果我们移除那个节点,我们将有一个平衡的 BST(即 AVL)。由于它严重向右倾斜,我们将向左旋转以使其平衡。

考虑将上面的右斜树做成 AVL 树的图示。

Left Rotation Explained

2.右旋转

当违规发生在违规节点的右子节点的右子树中时,将执行此循环。考虑下面一个不平衡的 BST 的图形表示,为了做到这一点,我们将做一些旋转。

Left Skewed BST

很明显,这不是一个 AVL 树,但是考虑到违规发生的节点,我们把这个节点作为一个枢纽来进行我们的旋转。树的左边很重,导致问题的节点是 3,如果我们移除那个节点,我们将有一个平衡的 BST(即 AVL)。由于它严重偏左,我们将做一个右旋转,使其平衡。

考虑将上面左倾的树做成 AVL 树的图示。

Explained Difference Right Rotate

3.左右旋转

当违规发生在违规节点的左子节点的右子树中时,将执行此循环。考虑下面一个不平衡的 BST 的图形表示,为了做到这一点,我们将做一些旋转。

Left-Right Rotation

很明显,这不是一个 AVL 树,但是考虑到违规发生的节点,我们把这个节点作为一个枢纽来进行我们的旋转。导致问题的节点是 18,就好像我们去掉那个节点,我们就会有一个平衡的 BST(即 AVL)。因为这个问题是因为左子树的右子树,我们将进行左右旋转,使其平衡。

考虑将上面的树做成 AVL 树的图示。

Explained AVL Difference

4.左右旋转

当违规发生在违规节点的右子节点的左子树中时,将执行此循环。考虑下面一个不平衡的 BST 的图形表示,为了做到这一点,我们将做一些旋转。

Right-Left BST

很明显,这不是一个 AVL 树,但是考虑到违规发生的节点,我们把这个节点作为一个枢纽来进行我们的旋转。导致问题的节点是 7,如果我们移除那个节点,我们将有一个平衡的 BST(即 AVL)。由于问题是由于右子树的左子树,我们将进行左右旋转,使其平衡。

考虑将上面的树做成 AVL 树的图示。

Explained AVL Tree

树插入

让我们取一组数组元素,并构建这些元素的 AVL 树。让,nums = [12 , 3 , 9 , 4 , 6 , 2]

制作 AVL 树(带旋转)的完整步骤如下所示。

Final Image

要点:

  • 具有 N 个节点的 AVL 树的最小楼层高度(logN)可以是 2。

  • 节点数为 N 的 AVL 树的高度不能超过 1.44(logN)基数 2。

  • 高度为 h 的 AVL 树中的最大节点数可以是:2^H+1 - 1

  • AVL 树的高度为 h 的最小节点数可以表示为:N(h) = N(h-1) + N(h-2) + 1,n>2,其中 N(0) = 1,N(1) = 2。

结论

  • 我们了解了什么是 AVL 树以及为什么需要它。
  • 然后,我们学习了 AVL 树中可能的不同类型的旋转,以使其成为一个平衡的旋转。
  • 在旋转之后,我们还在 AVL 树中做了一个插入示例。
  • 最后,我们谈到了我们应该记住的与 AVL 不同的关键点。