(八)算法与数据结构|二叉树|平衡二叉树|二叉查找树|平衡二叉查找树——红黑树

简述

二叉查找树是最常用的一种二叉树,它支持快速插入、删除、查找操作,各个操作的时间复杂度跟树的高度成正比,理想情况下,时间复杂度是 O(logn)。

不过,二叉查找树在频繁的动态更新过程中,可能会出现树的高度远大于 log2n 的情况,从而导致各个操作的效率下降。极端情况下,二叉树会退化为链表,时间复杂度会退化到 O(n)。

要解决这个复杂度退化的问题,我们需要设计一种平衡二叉查找树——红黑树

平衡二叉树

**定义:**二叉树中任意一个节点的左右子树的高度相差不能大于 1。
满二叉树、完全二叉树都是平衡二叉树。

平衡二叉查找树

不仅要满足平衡二叉树的要求,还要满足二叉查找树的要求。
最先被发明的平衡二叉查找树是 AVL树

红黑树不是严格的平衡二叉查找树。(不是严格满足平衡二叉树的要求)

平衡二叉查找树的出现是为了:解决普通二叉查找树在进行数据插入、删除等动态更新操作时出现时间复杂度退化问题。

“红黑树”

红黑树中的节点,一类被标记为黑色,一类被标为红色,同时要求:

  1. 根节点是黑色的
  2. 每个叶子节点都是黑色的空节点null,即叶子节点不存储数据
  3. 任何相连节点不能同时是红色的,即红色节点被黑色节点分隔
  4. 每个节点,从该节点到达其叶子节点的任何路径,包含的黑色节点的数量是相同的

第2点要求是为了简化红黑树代码实现。

“平衡”意味着性能不退化,“近似平衡”意味着性能不会退化太多。

红黑树实现基本思想

红黑树的要求有4点,在插入、删除节点过程中可能打破第3、4点要求,破坏平衡。调整平衡,使之能重新满足第3、4点要求。

左旋(围绕某个节点的左旋)
右旋(围绕某个节点的右旋)
左旋、右旋
插入操作的平衡调整:

红黑树规定:插入的节点必须是红色,且二叉查找树新插入节点都是放在叶子节点。 所以关于红黑树插入有两种特殊情况很好调整:

  • 如果插入节点的父节点是黑色,则什么都不做仍满足红黑树定义
  • 如果插入节点是根节点,则只要直接改变它的颜色为黑色即可

除以上两种情况,其余情况都会违背红黑树定义,需要调整。调整的过程包含两种基本操作:左右旋转改变颜色

红黑树的平衡调整过程是一个迭代的过程。我们把正在处理的节点叫作关注节点。关注节点会随着不停地迭代处理,而不断发生变化。最开始的关注节点就是新插入的节点。 新节点插入之后,如果红黑树的平衡被打破,那一般会有下面三种情况:

  • 情况1:如果关注节点是 a,它的叔叔节点 d 是红色
    依次执行如下操作:
    • 将关注节点 a 的父节点 b、叔叔节点 d 的颜色都设置成黑色
    • 将关注节点 a 的祖父节点 c 的颜色设置成红色
    • 关注节点变成 a 的爷爷节点 c
    • 跳到 情况2 或者 情况3
      情况1
  • 情况2:如果关注节点是 a,它的叔叔节点 d 是黑色,关注节点 a是其父节点 b 的右子节点
    依次执行如下操作:
    • 关注节点变成节点 a 的父节点 b
    • 围绕新的关注节点b 左旋
    • 跳到 情况3
      情况2
  • 情况3:如果关注节点是 a,它的叔叔节点 d 是黑色,关注节点 a 是其父节点 b 的左子节点
    依次执行如下操作:
    • 围绕关注节点 a 的爷爷节点 c 右旋
    • 将关注节点 a 的父节点 b、兄弟节点 c 的颜色互换
    • 调整结束。
      情况3

删除操作的平衡调整:

红黑树删除操作的平衡调整比插入操作的更难。删除操作平衡调整分2步:第一步针对删除节点初步调整, 保证红黑树能满足第4点要求;第二步针对关注节点进行二次调整, 保证红黑树满足第3点要求。

1 针对删除节点的初步调整: 有3种情况
经过初步调整,为了保证红黑树满足第4点要求,有些节点会被标记成2种颜色,“红-黑”或“黑-黑”。若一个节点被标记成“黑-黑”,在计算黑色节点个数时要算成2个黑色节点。
黑-黑图示:
黑-黑
红-黑图示:
红-黑

  • 初步调整情况1:如果删除的节点是a,只有一个子节点b
    • 删除节点a,节点a是黑色,节点b只能是红色,其余情况不符合红黑树定义。此情况下,把节点b改为黑色
    • 调整结束,不需要进入二次调整。
      删除调整情况1
  • 初步调整情况2:若删除节点a有两个非空子节点,且a的后继节点就是它的右子节点c
    • a的后继节点就是其右子节点则a右子节点肯定没有左子树(根据二查找叉树性质可判断)。把a节点删除,且把c节点放在原来a节点位置。 这个操作与普通的二叉查找树的删除操作相同
    • 把c节点颜色该为a节点原来的颜色
    • 若原来c节点是黑色,为了不违背红黑树第4点要求,给c节点的右子节点d多加一个黑色,则d变成了“红-黑”或“黑-黑”
    • 此时,关注节点变成了d节点;第二步调整针对关注节点来进行。
      删除操作初步调整情况2
  • 初步调整情况3:若要删除节点a,a有两个非空子节点,且a的后继节点不是右子节点
    • 找到a的后继节点d并删除d,删除d的过程参照情况1
    • 把a替换成d
    • 把d颜色设置成原来a的颜色
    • 若d是黑色,为了不违背红黑树第4条要求,给d右子节点c多加一个黑色。此时c成了红-黑或黑-黑
    • 关注节点变成c,第二步调整根据关注节点进行。

删除操作初步调整情况3

2 针对关注节点进行二次调整: 有4种情况
二次调整使其满足红黑树第3点要求。
- 二次调整情况1:若关注节点a,它的兄弟节点c是红色
- 围绕a的父节点b左旋
- a此时的父节点b和a此时的爷爷节点c交换颜色
- 关注节点不变
- 继续从四种情况找合适情况进行调整。
删除操作二次调整情况1
- 二次调整情况2:若关注节点a,它的兄弟节点c是黑色,且c的左右子节点d、e都是黑色
- 把a的兄弟节点c变成红色
- 从a种去掉一个黑色,此时a是纯黑或纯红
- 给a的父节点b加一个黑色,此时b变成红-黑或黑-黑
- 关注节点变成b
- 继续从4种情况中选择符合的情况进行调整
删除操作二次调整情况2
- 二次调整情况3:若关注节点a,它的兄弟节点c是黑色,c的左子节点d是红色,c的右子节点e是黑色
- 围绕节点c右旋
- c和d交换颜色
- 关注节点不变
- 跳转到二次调整情况4
删除操作二次调整情况3
- 二次调整情况4:若关注节点a,它的兄弟节点c是黑色,且c的右子节点是红色
- 围绕a的父节点b左旋
- 把c的颜色设置和b相同
- 把b的颜色设置成黑色
- 从a中去掉一个黑色,a变成纯黑或纯红
- 把a的叔叔节点e设置成黑色
- 调整结束。
删除操作二次调整情况4
红黑树更具体可参考此篇博客


END

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值