数据结构 -AVL树

文章目录

AVL树

AVL 树的意义:是二分查找树 BST 。二分查找树查找某个值时,时间复杂度是 O(h) ,因此,我们让树的尽可能平衡,即最大高度尽可能的小。因此有了 AVL 。

百度百科:在计算机科学中,AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者G. M. Adelson-Velsky和E. M. Landis,他们在1962年的论文《An algorithm for the organization of information》中发表了它。

BST 本质上是维护一个有序序列,AVL 树中的左旋右旋操作,并不会改变树的中序遍历结果。

上图中把 A 右旋是怎么做的呢?把 B 旋转到根节点,然后把 A 变成 B 的右孩子,把 E 补偿给 A 作为 A 的左孩子。

左旋和右旋

对节点 u 右旋:

  • 根 u 的左儿子变成新的根 p
  • 根的左儿子变成新的根 p 原本的右儿子
  • 新的根 p 的右儿子变成了原本的根 u
  • u 和 p 的高度都需要更新
cpp 复制代码
void R(int& u)
{
    int p = l[u];
    l[u] = r[p], r[p] = u;
    update(u), update(p);
    u = p;
}

对节点 u 左旋:

  • 根 u 的右儿子变成新的根 p
  • 根的右儿子变成新的根 p 原本的左儿子
  • 新的根 p 的左儿子变成了原本的根 u
  • u 和 p 的高度都需要更新
cpp 复制代码
void L(int& u)
{
    int p = r[u];
    r[u] = l[p], l[p] = u;
    update(u), update(p);
    u = p;
}

高度更新由左右儿子决定,因为求高度时,默认其两个儿子已经更新完高度了:

cpp 复制代码
void update(int u)
{
    h[u] = max(h[l[u]], h[r[u]]) + 1;
}

插入的四种情况

(一)新数字插到了左子树,导致左子树比右子树高2;左孩子的左子树比其右子树高1

对于四种情况中的①。应该右旋 A 。

实例如上图,右旋 88 即可。

(二)新数字插到了左子树,导致左子树比右子树高2;左孩子的右子树比其左子树高1

对于四种情况中的③。应该左旋 B 再右旋 A 。

对应的情况如如下:

cpp 复制代码
  70
61
  65
// 左旋 61
    70
  65
61
// 右旋 70
  65
61  70
(三)新数字插到了右子树,导致右子树比左子树高2;右孩子的右子树比其左子树高1

对于四种情况中的②。应该左旋 A 。

对应的情况如 88 96 120 ,左旋 88 即可。

(四)新数字插到了右子树,导致右子树比左子树高2;右孩子的左子树比其右子树高1

对于四种情况中的④。应该右旋 B 再左旋 A 。

对应的情况如如下:

cpp 复制代码
  70
96
  88
// 右旋 96
70
  88
    96
// 左旋 70
  96
70  88

插入的代码

cpp 复制代码
void insert(int& u, int w)
{
    if (!u) u = ++ idx, v[u] = w;
    else if (w < v[u])
    {
        insert(l[u], w);
        if (get_balance(u) == 2)
        {
            if (get_balance(l[u]) == 1) R(u);
            else L(l[u]), R(u);
        }
    }
    else
    {
        insert(r[u], w);
        if (get_balance(u) == -2)
        {
            if (get_balance(r[u]) == -1) L(u);
            else R(r[u]), L(u);
        }
    }

    update(u);
}

如上,对于单一动作,总是旋转"发现者";对于组合动作,先旋转"发现者"的子节点,再旋转"发现者"。

例题

  • AVL树的根 1066 Root of AVL Tree (25 point(s))
  • 判断完全 AVL 树 1123 Is It a Complete AVL Tree (30 point(s))
相关推荐
冰糖猕猴桃1 小时前
【Python】进阶 - 数据结构与算法
开发语言·数据结构·python·算法·时间复杂度、空间复杂度·树、二叉树·堆、图
lifallen1 小时前
Paimon vs. HBase:全链路开销对比
java·大数据·数据结构·数据库·算法·flink·hbase
2401_881244402 小时前
Treap树
数据结构·算法
乌萨奇也要立志学C++2 小时前
二叉树OJ题(单值树、相同树、找子树、构建和遍历)
数据结构·算法
hn小菜鸡10 小时前
LeetCode 377.组合总和IV
数据结构·算法·leetcode
亮亮爱刷题10 天前
飞往大厂梦之算法提升-7
数据结构·算法·leetcode·动态规划
_周游10 天前
【数据结构】_二叉树OJ第二弹(返回数组的遍历专题)
数据结构·算法
双叶83610 天前
(C语言)Map数组的实现(数据结构)(链表)(指针)
c语言·数据结构·c++·算法·链表·哈希算法
zmuy10 天前
124. 二叉树中的最大路径和
数据结构·算法·leetcode
转码的小石10 天前
Java面试复习指南:并发编程、JVM、Spring框架、数据结构与算法、Java 8新特性
java·jvm·数据结构·spring·面试·并发编程·java 8