# 红黑树

红黑树是平衡二叉树的一种实现方式, 相比AVL树要求的结点的高度差不能大于1, 红黑树更加宽松一些, 也因此对于红黑二叉树的平衡次数和旋转次数会更少, 因此应用的更加广泛.

# 红黑树的平衡的五条特性

当满足一下的条件时, 说明这是一颗平衡的红黑树.

  1. 任意一个结点的颜色只能是黑色或者红色
  2. 根节点是黑色
  3. 任何为NULL的结点视为黑色
  4. 红色的结点不会相邻, 也就是说红色结点的孩子节点不能是红色
  5. 从根节点出发,达到任意一个叶子结点的路径上, 黑色节点数量必须相同.

# 添加新节点时对应的4种情况

两种简单情况:

  1. 根节点为null, 则添加节点就是添加一个根节点,我们添加节点后,将节点的颜色设置为黑色即可
  2. 父节点的颜色为黑色, 对于这种情况,我们添加节点后,不需要进行任何的平衡,因为父节点为黑色的结点添加节点不会影响平衡.(新添加节点的颜色为红色)

情况3: 父节点为红色,并且叔叔节点为红色. img

情况4:父节点为红色,并且叔叔节点为黑色. img

# 红红相邻情况导致失衡调整

在线的演示网站 (opens new window) 对于失衡情况, 我们有两种调整方式.

  1. 变色
  2. 旋转

# 情况3的调整

步骤
以该图为例子: img 因为插入节点后, 新节点与父节点与红色结点相邻, 因此出现红红相邻的情况.

最先想到的调整方式就是将父节点变成黑色, 但是这时就会导致到达新节点的路径上黑色节点数量多于 叔叔路径中叶子节点的路径上的黑色节点, 违反了特性5. img

此时我们想到将叔叔节点也变为黑色, 但是此时又会导致祖先结点的父节点(5)的另一个分支中的黑色节点数量小于左边分支, 因此我们又想将祖先结点变为红色,此时 如果祖先节点的父节点不是红色,那么此时的红黑树就平衡了,否则还需要处理红红相邻的情况.

总结 父节点为红色, 叔叔节点为红色, 此时将父节点和叔叔节点都变为黑色, 然后将祖先结点变为红色, 判断祖先结点与它的父节点是否产生了红红相邻的情况.如果是,则对祖先节点进行调整.

# 情况4的调整

父节点为红色, 叔叔节点为黑色, 我们有4种调整方案

  1. 父节点是左孩子, 新插入的结点为左孩子, 此时是LL不平衡
  2. 父节点是左孩子, 新插入的结点为右孩子, 此时是LR不平衡
  3. 父节点是右孩子, 新插入的结点为左孩子, 此时是RL不平衡.
  4. 父节点是右孩子, 新插入的结点为右孩子, 此时是RR不平衡.

LL的不平衡, 我们需要对父节点进行一次右旋.
对父节点进行一次右旋, 然后将父节点变为黑色,将祖父节点变为红色.

LR的不平衡, 我们需要进行父节点一次左旋,新的父节点再一次右旋
img 先对父节点2进行一次左旋, 将2旋转成3的左孩子, 3变成新的父节点,此时 又是红红相邻,但此时是LL的情况, 进行一次右旋. img 右旋后, 父节点变为黑色, 祖父节点变为红色 img RR的不平衡, 我们需要对父节点进行一次左旋.
对父节点进行一次左旋, 然后将父节点变为黑色,将祖父节点变为红色. 失衡: img

调整后: img

对于RL的不平衡,我们需要对父节点进行一次右旋,然后对新的右节点进行一次左旋. 调整前: img 先对父节点进行一次右旋,然后出现了RR的情况, 然后我们对其进行一次左旋. 然后将祖父节点变为红色, 父亲节点变为黑色.

# 删除节点时,对应的情况

  1. 被删除节点是根节点. (case 1)

    • 被删除节点没有孩子.
    • 被删除节点只有一个孩子.
    • 被删除节点有两个孩子.
  2. 被删除节点不是根节点.

    • 被删除节点有两个孩子 (case 0)
    • 被删除节点没有孩子
      • 被删除节点是红色(直接删除,不影响平衡)
      • 被删除节点是黑色(进行黑黑平衡)
    • 被删除节点有一个孩子
      • 被删除节点是红色(将孩子替换自己的位置, 并且将颜色设置为红色.)
      • 被删除节点是黑色
        • 如果该节点只有一个红色孩子,则将红色孩子替代自己的位置,并且将颜色设置为黑色

img

更新时间: 2024年5月26日星期日下午4点47分