数据结构------红黑树

什么是红黑树

红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构。红黑树和AVL树类似,都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。它虽然是复杂的,但它的最坏情况运行时间也是非常良好的,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。

红黑树的性质

  • 性质1:每个节点要么是黑色,要么是红色。
  • 性质2:根节点是黑色。
  • 性质3:每个叶子节点(NIL)是黑色。
  • 性质4:每个红色结点的两个子结点一定都是黑色。
  • 性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。

由性质4可以得出------在红黑树中不存在两个连续的红色节点

举例,下图为数字0-10所组成的一个红黑树,该红黑树满足上面五个性质要求

在这里插入图片描述

树的左旋与右旋

左旋

左旋:以某个结点作为支点(旋转结点),其右子结点变为旋转结点的父结点,右子结点的左子树变为旋转结点的右子树,左子树保持不变。示意图如下:

在这里插入图片描述

右旋

右旋:以某个结点作为支点(旋转结点),其左子结点变为旋转结点的父结点,左子结点的右子树变为旋转结点的左子树,右子树保持不变。示意图如下

在这里插入图片描述

树的查找

树的查找流程如下图所示:

在这里插入图片描述

红黑树的插入

红黑树的插入步骤

红黑树的插入操作分为两个步骤:

  1. 先将要插入的节点放到红黑树的正确位置上
  2. 通过自平衡操作修复红黑树,使其满足上述的5条性质

因为在插入元素之前这个树是满足红黑树性质要求的,所以插入之后生成的树也要满足红黑树的性质。

插入的新节点默认都是红色的

如果插入的新节点的颜色默认是黑色的话,根据红黑树的性质5,则无论在什么位置插入都会破坏红黑树的性质。但如果默认是红色的话,至少在父节点是黑色节点的情况下,红色节点可以直接插入,无需进行自平衡操作。

红黑树的插入分为以下几种情况:

约定:要插入的位置称为当前节点

情况1:当前树是空树

​ 这时直接将当前节点插入到树的根节点处,并将当前节点的颜色改为黑色即可

情况2:当前节点的父节点是黑色节点

​ 则直接将当前节点插入到正确的位置即可,因为红色节点不影响树的平衡,所以本次插入没有破坏红黑树的平衡,故无需做自平衡操作。

情况3、如果当前节点的父节点是红色

​ 因为当前节点和当前节点的父节点都是红色,则根据性质4可知,当前节点的爷爷节点一定存在,并且颜色一定为黑色,否则在插入之前就已经不是一颗红黑树了。这时将当前节点插入后将会破坏红黑树的性质4,即出现了两个连续的红色节点。这时就需要对红黑树进行自平衡操作。而此时又分为以下几种情况:

情况3.1、当前节点为红色,当前节点的父节点为红色,当前节点的叔叔节点也是红色,且当前节点是父节点的左子节点

针对这种情况的自平衡操作是,将当前节点的父节点和叔叔节点染成黑色,并将当前节点的爷爷节点染 成红色,再以爷爷节点为当前节点递归向上做自平衡操作,直到红黑树达到平衡。

情况3.1的自平衡操作示意图如下:

假设当前要将节点9插入到最左侧的红黑树中,插入后破坏了红黑树的性质4,其余条件符合情况3.1,通过自平衡将其修正为一棵红黑树。修正后发现节点15和节点19又不符合红黑树的性质,则以节点15为基础递归向上进行自平衡操作,直到将整棵树修正为一棵红黑树为止。

在这里插入图片描述

情况3.2、当前节点为红色,当前节点的父节点为红色,当前节点的叔叔节点是黑色,且当前节点是父节点的左子节点

​ 这种场景可能是通过情况3.1的自平衡操作后得到的结果,此时虽然满足性质5,但是不满足性质4。

针对这种情况自平衡的操作是,先以当前节点的爷爷节点为支点进行右旋,右旋之后再将当前节点的父节点染成黑色,当前节点的兄弟节点染成红色

情况3.2的自平衡操作示意图如下:
在这里插入图片描述

情况3.3、当前节点为红色,当前节点的父节点为红色,当前节点的叔叔节点是黑色,且当前节点是父节点的右子节点

针对这种情况自平衡的操作是,先对当前节点进行左旋操作,转换成情况3.2,接着按照情况3.2的方案做自平衡。

情况3.3的自平衡操作示意图如下:

在这里插入图片描述

到目前为止,讨论的所有插入情况都是假设当前节点的父节点是当前节点爷爷节点的左子节点的情况,对应的还有父节点是爷爷节点的右子节点的情况,其自平衡操作流程是上面三种情况的镜像。

红黑树的删除

一个红黑树的节点可以从两个维度去描述,即节点的颜色以及子节点的个数

节点可能有两种颜色,即红色和黑色。

节点的子节点个数可能有三种情况,即0个子节点,1个子节点,2个子节点。

颜色和节点个数结合起来总共有6种情况,接下来对这6种情况逐一分析。

对于红黑树删除过程中各个节点的命名规则如下图所示:
在这里插入图片描述

情况1:被删除节点有0个子节点,且被删除节点是黑色

1.1待删除节点为黑色节点,且待删除节点的远侄子节点(待删除节点兄弟节点的右子节点)为红色

观察下图可以发现,待删除节点X被删除后,左子树的黑色节点的个数将少于右子树,而右子树中有一个红色节点刚好可以通过变色后来填补空缺。所以便通过左旋操作调整树的结构后,再重新染色即可达到平衡

示意图如下:

在这里插入图片描述

1.2待删除节点为黑色节点,且待删除节点的近侄子节点(待删除节点兄弟节点的右子节点)为红色

此时和上面的情况相似,只不过比上面的情况多了一次旋转和着色的操作

在这里插入图片描述

1.3待删除节点为黑色节点,待删除节点的兄弟节点没有子节点,且父节点为红色

直接调整颜色即可达到平衡,示意图如下,节点3位待删除的节点

在这里插入图片描述

1.4待删除节点为黑色节点,待删除节点的兄弟节点没有子节点,且父节点为黑色

如下图,节点0为待删除节点,将节点0删除后将会导致节点1左子树这条路径的黑色节点个数变少,所以需要通过旋转来调节树的平衡,具体流程如下图所示。

在这里插入图片描述

1.5待删除节点为黑色节点,待删除节点的兄弟节点为红色

如下图所示,要删除的节点是节点5,删除后节点8的左子树黑色节点个数减一,所以也需要通过旋转来调节树的平衡

在这里插入图片描述

情况1总结:当前要删除的节点是黑色节点且没有子节点,假设要删除的节点为节点X,删除后对于所有经过节点X的路径的黑色节点数量都会减一。因为当前节点X没有子节点所以需要判断节点X的兄弟节点及其子节点是否有红色节点,如果有,则通过树的旋转和变色操作后一定能够使树达到平衡。如果兄弟节点也没有红色节点,则需要继续向上判断,最终总能找到一个节点,通过树的旋转和节点着色使得红黑树重新平衡。

情况2:被删除节点有0个子节点,且被删除节点是红色

​ 因为红色节点不影响红黑树的平衡性质,所以这种情况可以直接删除,不用做任何自平衡操作。

情况3:被删除节点有1个子节点,且被删除的节点是红色节点

​ 当被删除节点X是红色节点,根据红黑树的性质4可知,他的唯一子节点S一定是黑色节点,此时违反了红黑树的性质5,故这种情况是不存在的。

情况4:被删除节点有1个子节点,且被删除的节点是黑色节点

​ 假设被删除节点X是黑色节点,那么根据红黑树的性质5可知,该节点的子节点S一定是红色节点。

自平衡方案:用S节点替换X节点,并将并将S节点的颜色染成黑色

在这里插入图片描述

情况5:被删除节点有2个子节点,且被删节点是黑色或红色

​ 当被删除节点X有两个字节点时,首先要先找到节点X的后继节点successor,然后用successor替换节点X的位置,同时颜色也染成节点X的颜色。此时将问题转换成删除successor节点的问题。因为successor节点最多只有一个子节点,所以总是可以将其转换成上面的情况1、情况2和情况4。所以找到节点X的后继节点是删除操作的第一步。

节点X的后继节点可能有如下两种情况:

  • 被删除节点X的RS节点无左子节点
  • 被删除节点X的RS节点有左子节点RS-LS

示意图如下:

在这里插入图片描述

若是(a)的情形,用successor代替X后,相当于successor被删,若successor为红色,则变成了情况2;若successor为黑色,则变成了情况1或4。

若是(b)的情形,用successor代替X后,相当于successor被删,若successor为红色,则变成了情况2 ;若successor为黑色,则变成了情况1或4。

对应的示意图如下所示:

橙色节点表示颜色随意,可以为红色也可以为黑色

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值