红黑树的插入和删除

红黑树的优点:

AVL树是为了解决二叉查找树退化为链表的情况,而红黑树是为了解决平衡树在插入、删除等操作需要频繁调整的情况。
红黑树引入“颜色”的目的在于使得红黑树的平衡条件得以简化,它只要求部分地达到平衡要求,降低了对旋转的要求,从而提高了性能。
红黑树能够以O(log2 n)的时间复杂度进行搜索、插入、删除操作。此外,由于它的设计,任何不平衡都会在三次旋转之内解决。红黑树的算法时间复杂度和AVL相同,但统计性能比AVL树更高,查找时和AVL树相同,插入和删除的平均时间复杂度优于AVL树。

红黑树的性质:

  1. 每个节点或者是红色,或者是黑色;
  2. 根节点是黑色的;
  3. 每个叶子节点(NIL)是黑色的。注意:这里的叶子节点,是指为空的叶子节 点;
  4. 如果一个节点是红色的,则它的子节点必须是黑色的;
  5. 从任意一个节点到其叶子的所有路径中,所包含的黑节点数量是相同的(可知,没有一条路径会比其它路径长出两倍,因而红黑树是接近平衡的二叉树);

红黑树插入

红黑树插入思维导图
在这里插入图片描述
插入情景1:红黑树为空树
最简单的一种情景,直接把插入结点作为根结点就行,但注意,根据红黑树性质2:根节点是黑色。还需要把插入结点设为黑色。
处理:把插入结点作为根结点,并把结点设置为黑色。

插入情景2:插入结点的Key已存在
插入结点的Key已存在,既然红黑树总保持平衡,在插入前红黑树已经是平衡的,那么把插入结点设置为将要替代结点的颜色,再把结点的值更新就完成插入。
处理
I设为当前结点的颜色
更新当前结点的值为插入结点的值

插入情景3:插入结点的父结点为黑结点
由于插入的结点是红色的,当插入结点的黑色时,并不会影响红黑树的平衡,直接插入即可,无需做自平衡。
处理:直接插入。

插入情景4:插入结点的父结点为红结点
再次回想下红黑树的性质2:根结点是黑色。如果插入的父结点为红结点,那么该父结点不可能为根结点,所以插入结点总是存在祖父结点。这点很重要,因为后续的旋转操作肯定需要祖父结点的参与。

情景4又分为很多子情景:
插入情景4.1:叔叔结点存在并且为红结点
从红黑树性质4可以,祖父结点肯定为黑结点,因为不可以同时存在两个相连的红结点。那么此时该插入子树的红黑层数的情况是:黑红红。显然最简单的处理方式是把其改为:红黑红。如下图所示:
在这里插入图片描述
可以看到,我们把PP结点设为红色了,如果PP的父结点是黑色,那么无需再做任何处理;但如果PP的父结点是红色,根据性质4,此时红黑树已不平衡了,所以还需要把PP当作新的插入结点,继续做插入操作自平衡处理,直到平衡为止。

试想下PP刚好为根结点时,那么根据性质2,我们必须把PP重新设为黑色,那么树的红黑结构变为:黑黑红。换句话说,从根结点到叶子结点的路径中,黑色结点增加了。这也是唯一一种会增加红黑树黑色结点层数的插入情景。

还有另外一种场景,处理过程和上面一样:
在这里插入图片描述

插入情景4.2:叔叔结点不存在或为黑结点,并且插入结点的父亲结点是祖父结点的左子结点
单纯从插入前来看,也即不算情景4.1自底向上处理时的情况,叔叔结点非红即为叶子结点(Nil)。因为如果叔叔结点为黑结点,而父结点为红结点,那么叔叔结点所在的子树的黑色结点就比父结点所在子树的多了,这不满足红黑树的性质5。后续情景同样如此,不再多做说明了。

插入情景4.2.1:插入结点是其父结点的左子结点
处理:

在这里插入图片描述
由上图可得,左边两个红结点,右边不存在,那么一边一个刚刚好,并且因为为红色,肯定不会破坏树的平衡。
插入情景4.2.2:插入结点是其父结点的右子结点
这种情景显然可以转换为情景4.2.1,如下图所示:
在这里插入图片描述
红黑树删除

首先红黑树是二叉排序树,按排序树的方式删除一个结点,有三种情况:
(1)如果待删除的结点是叶子结点,则直接删除即可。
(2)如果待删除的结点只有一个孩子,则将父结点的指针指向它的孩子。
(3)如果待删除的结点有两个孩子,则可以找它的后继,将值覆盖过来,之后情况转变成删除前驱或者后继结点,回到(1)和(2)。
那么再根据颜色的不同,接下来情况就非常多了,这就是红黑树删除操作麻烦的地方,切忌浮躁,务必静下心来仔细分析。

第三种情况:
  此情况因为可以转变成前面两种情况,相当于已经解决了。
第二种情况(一个孩子):
 在这里插入图片描述
根据性质5,可以推断出的是,待删除结点必定是黑色(红色结点不可能只有一个孩子),且唯一的子树一定是一个红色孩子。所以这种情况可以在删除时就处理掉,用红色孩子顶替待删除结点,再将其涂成黑色。
变成:
在这里插入图片描述

第一种情况(叶子)
  首先,如果待删除结点为红色,则直接结束了。
  如果待删除结点为黑色,这种情况下,此条分支不可能通过涂色的方式弥补缺少的黑色,所以要判断其兄弟和侄子的状况,希望通过兄弟那边分支的旋转,来保持黑色的数量:
(1)如果兄弟是黑色。
在这里插入图片描述
这种情况下,一旦deleted被删除,左边就比右边少了一个黑色结点,parent红色或者黑色都有可能,那两个侄子要么为null,要么为红色。

1.1如果两个侄子都为null,parent为红色
在这里插入图片描述
在这里插入图片描述
deleted结点被删除之后 ,此时只要将parent涂黑,brother涂红即可。
在这里插入图片描述
1.2 如果两个侄子都为null,parent为黑色

在这里插入图片描述
deleted结点被删除之后
在这里插入图片描述
在这里插入图片描述
这时,不论如何涂色,都无法让弥补左边缺少的一个黑色,所以只能先把brother涂红,让左右黑色数量相同,但是这样parent这棵树一定会少一个黑色,所以需要对parent进行又一轮的调整。

1.3左侄子为红色
在这里插入图片描述
红色结点是不会影响红黑性质的,所以希望能够利用一下这个红结点。
删除deleted结点之后,经过一系列变换:
在这里插入图片描述
可以看到,左侄子被涂上了parent的颜色,目的是为了能够在后面顶替parent,而parent有自己的任务,就是去弥补左子树缺少的黑色。

1.4右侄子为红色
在这里插入图片描述
brother涂上了parent的颜色为了顶替parent,parent的任务是去弥补左子树缺少的黑色,而右侄子则涂黑保持黑色数量相等。
2.如果兄弟是红色,那么可以先转换成黑兄的情况。
在这里插入图片描述
在这里插入图片描述
可以肯定的是,那两个侄子肯定不为null。
parent左旋一下,然后parent和brother交换颜色,之后brother指向最下面那个结点。这样一来,就变成了上面的黑兄情况,此时只要将parent涂黑,brother涂红即可。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值