红黑树,AVL 树,二分查找树的定义

208 阅读5分钟

二分查找树 Binary Search Tree

  • 若它的左子树不为空,左子树上所有节点的值都小于它的根节点。
  • 若它的右子树不为空,右子树上所有的节点的值都大于它的根节点。
  • 它的左、右子树也都是二分搜索树。

image-20220811220813164

AVL 树 (二叉平衡搜索树)

什么是 AVL 树

AVL 树 得名于它的发明者G. M. Adelson-Velsky

AVL 树: 二叉平衡搜索树

AVL 树 是在 二叉查找树 的 基础上 对 树 进行平衡,使其 二叉树 和 他的子树,都能高效率的检索

如何判断这个树是否平衡

AVL 树是高度平衡的二叉搜索树,其左子树和右子树的高度差不超过1 (树中的左子树和右子树都是AVL树),维持这个高度之差就要控制它的平衡因子。

左子树 ==减== 右子树 = X < 2

或者

右子树 ==减== 左子树 = X < 2

如果左子树 和 右子树的差 大于 1 那么这个树就不平衡

如果是负数怎么办:abs() 取绝对值

如何让树平衡

旋转的条件

LL (右旋)
  • 插入元素在第一个不平衡节点的左侧的左侧
  • image-20220808164109792
  • 如上图所示,根据二叉搜索树的性质他们的大小关系应该是
  • 1 < 2 < 3 < 4 < 5 < 8
  • 此时我们查看这个树已经不是平衡状态,不平衡节点是 3,5,我们需要对第一个不平衡节点进行 右旋 。由于是加入左树节点时,引起的二叉树不平衡,在 右旋 之后,需要检查左树的数据是否符合二叉查找树的规定,如不符合,将进行从新排列组合
  • LL
RR (左旋)
  • 插入元素在第一个不平衡节点的右侧的右侧

  • image-20220809225617180

  • 左旋右旋 相反,因为是插入在 右侧的右侧节点导致树失衡, 失衡节点是 10, 8 此时要进行 左旋左旋 之后同样要对右侧的数据进行从新排列组合

  • RR

LR (左旋 + 右旋)
  • 插入元素在第一个不平衡节点的左侧的右侧

  • image-20220809232621472

  • 此时首先将第一个不平衡节点进行 左旋

  • image-20220809232705818

  • 随后,我们得到 LL 类型的失衡节点,再将第一个失衡节点 右旋

  • image-20220809233058157

RL (右旋 + 左旋)
  • 插入元素在第一个不平衡节点的右侧的左侧
  • image-20220809233701367
  • 不平衡节点 25,20。此时首先将第一个不平衡节点进行 右旋
  • image-20220809235829122
  • 随后,我们得到 RR 类型的失衡节点,再将第一个失衡节点进行 左旋
  • image-20220809235932620

红黑树的定义与性质

红黑树是一种含有红黑节点并且能自平衡的二叉查找树,它满足以下 5 个性质

  • 每个节点要么是黑色,要么是红色
  • 根节点是黑色
  • 每个叶子节点 (NIL)是黑色
  • 每个红色节点的两个子节点一定都是黑色
  • 任意一节点到每个叶子节点的路径都包含数量相同的黑节点

红黑树是 二叉查找树

树和他的子树满足以下约束:左节点小于父节点,右节点大于父节点。(子树也是一样)

image-20220808095410983

红黑树每个节点多了一个颜色标记位,每个节点非黑即红

红黑树的根节点必须是黑色的,这是硬性规定,你无法推算出根节点不能是红色

每个叶子节点 (NIL)都是黑色的虚节点

image-20220808101904761

  • 为什么要有 NIL(叶子) 节点 ,它的作用是什么
    • NIL 节点有利于平衡黑色高度,给树一个完美黑平衡
  • 什么是树平衡,为什么要刻意的让树平衡
    • 因为红黑树是一个二叉查找树,二叉树查找的特点 O(log n ), 即只查找一部分,如果查询的 value 比 根节点大,就去右边找,相反则去左边找,这大大降低了检索的速度。
    • 为什么要让这个二叉树平衡,如果不让这个树平衡,而是倾向于左侧,或是 右侧,那这个 二叉树 就会失去平衡,让检索效率降低
      • 失去平衡的树image-20220808103733450
    • 为什么检索的效率会降低
      • 此时如果 在上面这个二叉树中查找 一个值 比如 103 ,103 比 根节点大所以在右边的树检索,需要一个一个去对比。那这不就是链表吗?
  • 什么是链表,链表的规则是什么
    • 链表是一种特殊的存储结构,它是有序的,它的特点在于在 元素中不仅会存储数据,还会存储下一个元素的地址
    • image-20220808110058675
    • 它的缺点就是查找比较麻烦,如果链表中存储的数据比较多,它要在链表中 一个一个元素的去对比,当前元素是不是要查找的元素

如何判断红黑树是否平衡

  • 满足以上 五个 条件

如何让红黑树平衡

在插入和删除时,判断节点是否需要变色,或是 旋转(左旋,右旋)

举例:

image-20220810223201589

image-20220810234127337

  1. 插入 12 根节点为黑色

  2. 插入 左子节点 1 ,默认为红色

  3. 插入 9 默认为红色,此时违反两个 规定

    1. 违反红黑树定义规则 每个红色节点的两个子节点一定都是黑色
    2. 违反 AVL 树 不平衡
  4. 参考 AVL 树的 LR 插入元素在第一个不平衡节点的左侧的右侧

    1. 首先左旋第一个不平衡节点,得到 图4
    2. 左旋之后还是不平衡,需要再向右旋转,得到 图5
  5. 由于节点 9 默认是红色,旋转后违反了 红黑树的定义 根节点是黑色,此时将 9 设为黑色

  6. 插入节点 2 默认红色

  7. 违反红黑树定义规则 每个红色节点的两个子节点一定都是黑色

    1. 依次向上变色,如果父节点和叔叔节点为红色就变成黑色,如果是黑色就变成红色,依次向上,直至根节点
  8. 根节点 9 变色后违反了 红黑树定义 根节点是黑色, 所以根节点必须是黑色

解释:

  • 红黑树的变色遵循红黑树的定义规则
  • 红黑树的旋转遵循 AVL 树的平衡规则

红黑树 和 AVL 树的区别

AVL树的特点
  1. 和红黑树相比,AVL 树是高度平衡的二叉搜索树,其左子树和右子树的高度差不超过1 (树中的左子树和右子树都是AVL树),无论是执行 插入 还是 删除 操作,只要不满足 AVL 树的高度差 <=1 , 就要通过 旋转 来保持平衡,而旋转操作是比较耗时的,由此得知 AVL 树适合插入 和 删除 比较少,==查询== 比较多的情况。
  2. AVL 树追求绝对平衡,条件比较苛刻,实现起来比较麻烦,每次插入新节点之后需要旋转的次数不能预知。
  3. 由于 AVL 树的维护成本比较高,故而实际应用的不多,大多数场景下仅仅是追求局部平衡,并不是完美平衡。
  4. 相对于 红黑树 ,AVL 树的查找性能更快
红黑树的特点
  1. 红黑树放弃了完美平衡,而是追求了完美黑平衡(黑色节点是平衡的),相对于 AVL 树来说,红黑树插入最多两次旋转,删除最多三次旋转。红黑树的旋转次数要少,对于 ==插入==,==删除== 比较多的情况下,选择红黑树。
  2. 红黑树在插入和删除上,优于 AVL 树,AVL 树每次插入,删除都会进行大量的平衡计算,而红黑树为了维持红黑性质所做的红黑节点变色和旋转开销,相对于 AVL 树为了维持平衡度的开销要小。

文章的最后: