zoukankan      html  css  js  c++  java
  • 红黑树

    红黑树 - 一种自平衡的二叉查找树

    性质

    1. 节点是红色黑色
    2. 根节点是黑色
    3. 每个叶子节点都是黑色空节点(NIL节点)
    4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
    5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

    img

    这些规则的限制保证了红黑树自平衡,从根到叶子的最长路径不会超过最短路径的2倍

    插入

    1.向原红黑树插入值为14的新节点

    满足性质不需要调整

    2.向原红黑树插入值为21的新节点

    640?wx_fmt=png

    由于父节点22是红色节点,因此这种情况打破了红黑树的规则4(每个红色节点的两个子节点都是黑色),必须进行调整,使之重新符合红黑树的规则。

    调整

    变色

    为了重新符合红黑树的规则,尝试把红色节点变为黑色,或者把黑色节点变为红色

    1. 下图所表示的是红黑树的一部分,需要注意节点25并非根节点。因为节点21和节点22连续出现了红色,不符合规则4,所以把节点22从红色变成黑色:640?wx_fmt=png
    2. 但这样并不算完,因为凭空多出的黑色节点打破了规则5,所以发生连锁反应,需要继续把节点25从黑色变成红色:640?wx_fmt=png
    3. 此时仍然没有结束,因为节点25和节点27又形成了两个连续的红色节点,需要继续把节点27从红色变成黑色:640?wx_fmt=png

    此时可以说变色才告一段落。

    旋转

    左旋右旋对于学过数据结构平衡二叉树的同学不会感到陌生。

    左旋转

    以某个结点作为支点(旋转结点),其右子结点变为旋转结点的父结点右子结点左子结点变为旋转结点的右子结点,左子结点保持不变。

    逆时针旋转红黑树的两个节点,使得父节点被自己的右孩子取代,而自己成为自己的左孩子。如下图。

    640?wx_fmt=png

    上图中,身为右孩子的Y取代了X的位置,而X变成了自己的左孩子。此为左旋转。

    右旋转

    以某个结点作为支点(旋转结点),其左子结点变为旋转结点的父结点,左子结点的右子结点变为旋转结点的左子结点,右子结点保持不变。

    顺时针旋转红黑树的两个节点,使得父节点被自己的左孩子取代,而自己成为自己的右孩子。

    640?wx_fmt=png

    上图中,身为左孩子的Y取代了X的位置,而X变成了自己的右孩子。

    变色与旋转要根据插入和删除时的具体情况具体分析,以上述插入21节点为例

    以插入21节点为例

    640?wx_fmt=png

    第一步

    变色,把节点25及其下方的节点变色:

    640?wx_fmt=png

    此时节点17和节点25是连续的两个红色节点,那么把节点17变成黑色节点?

    恐怕不合适。这样一来不但打破了规则4,而且根据规则2(根节点是黑色),也不可能把节点13变成红色节点。

    第二步

    变色已无法解决问题,我们把节点13看做X,把节点17看做Y,像刚才的示意图那样进行左旋转

    640?wx_fmt=png

    640?wx_fmt=png

    左旋转为下图

    640?wx_fmt=png

    由于根节点必须是黑色节点,所以需要变色。

    第三步

    640?wx_fmt=png

    这样并没有结束,因为其中两条路径(17 -> 8 -> 6 -> NIL)的黑色节点个数是4,其他路径的黑色节点个数是3,不符合规则5

    这时候我们需要把节点13看做X,节点8看做Y,进行右旋转

    第四步

    640?wx_fmt=png

    ​ ↓

    640?wx_fmt=png

    ​ ↓

    640?wx_fmt=png

    最后根据规则变色

    第五步

    640?wx_fmt=png

    至此便完成了插入操作,本插入过程属于复杂的一种情况,其他情况需要具体分析。

    删除

    红黑树的删除有许多种情况需要根据不同规则进行操作,下面举出部分例子。

    情形分析

    一、从树中删除节点X(以寻找后继节点的方式进行删除

    • 情况①:如果X没有孩子,且如果X是红色,直接删除X;如果X是黑色,则以X为当前节点进行旋转调色,最后删掉X
    • 情况②:如果X只有一个孩子C,交换X和C的数值,再对新X进行删除。根据红黑树特性,此时X不可能为红色,因为红色节点要么没有孩子,要么有两个黑孩子。此时以新X为当前节点进行情况①的判断
    • 情况③:如果X有两个孩子,则从后继中找到最小节点D,交换X和D的数值,再对新X进行删除。此时以新X为当前节点进行情况①或②的判断

    二、旋转调色

    N=旋转调色的当前节点[等于情况①中的X],P=N的父亲,W=N的兄弟,Nf=N的远侄子,Nn=N的近侄子)

    • 情况1:N是根或者N是红色,则:直接将N设为黑色
    • 情况2:N不是根且N是黑色,且W为红色,则:将W设为黑色,P设为红色,对P进行旋转(N为P的左子时进行左旋,N为P的右子时进行右旋),将情况转化为情况1、2、3、4、5
    • 情况3:N不是根且N是黑色,且W为黑色,且W的左右子均为黑色,则:将W设为红色,将P设为当前节点进行旋转调色,将情况转化为情况1、2、3、4、5
    • 情况4:N不是根且N是黑色,且W为黑色,且Nf为黑色,Nn为红色,则:交换W与Nn的颜色,并对W进行旋转(N为P的左子进行右旋,N为P的右子进行左旋),旋转后N的新兄弟W有一个红色WR,则转换为情况5
    • 情况5:N不是根且N是黑色,且W为黑色,且Nf为红色,Nn为黑色,则:将W设为P的颜色,P和Nf设为黑色,并对P进行旋转(N为P的左子进行左旋,N为P的右子进行右旋),N设为根

    删除示例

    (1)删除12

    img

    (2)删除1

    img

    (3)删除9

    img

    (4)删除2

    img

    (5)删除0

    img

    (6)删除11

    img

    (7)删除7

    img

    (8)删除19

    img

    (9)删除4

    img

    (10)删除15

    img

    (11)删除18

    img

    (12)删除5

    img

    (13)删除14

    img

    (14)删除13

    img

    (15)删除10

    img

    (16)删除16

    img

    (17)删除6

    img

    (18)删除3

    img

    (19)删除8

    img

  • 相关阅读:
    lyft amundsen简单试用
    Prisma 2 is Coming Soon
    amundsen 来自lyft 的开源数据发现平台
    packr 方便的潜入静态资源文件到golang 二进制文件中
    hasura skor 构建安装
    Oracle中删除用户下所有对象的多种方法
    负载均衡----实现配置篇(Nginx)
    【nginx】配置Nginx实现负载均衡
    Vmware ESXi添加共享磁盘
    从Oracle迁移到MySQL的各种坑及自救方案
  • 原文地址:https://www.cnblogs.com/coderzjz/p/15323408.html
Copyright © 2011-2022 走看看