红黑树(英语:Red–black tree)是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型用途是实现关联数组。它在1972年由鲁道夫·贝尔发明,被称为"对称二叉B树",它现代的名字源于Leo J. Guibas和Robert Sedgewick于1978年写的一篇论文。红黑树的结构复杂,但它的操作有着良好的最坏情况运行时间,并且在实践中高效
定义
- 节点是红色或黑色
- 根是黑色
- 所有叶子都是黑色(叶子是NIL节点)
- 每个红色节点必须有两个黑色的子节点(从每个叶子到根的所有路径上不能有两个连续的红色节点)
- 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点
自平衡操作
- 变色:节点的颜色由红变黑或者由黑变红
左旋:以某个节点为旋转节点,其右子节点变为旋转节点的父节点,右子节点的左子节点变为旋转节点的右子节点,左子节点保持不变
右旋:以某个节点为旋转节点,其左子节点变为旋转节点的父节点,左子节点的右子节点变为旋转节点的左子节点,右子节点保持不变
插入操作的平衡调整
红黑树规定,插入的节点必须是红色的。关于插入操作的平衡调整,有两种特殊情况,非常好处理:
-
如果插入节点的父节点是黑色的,那我们什么都不用做,它仍然满足红黑树的定义。
-
如果插入的节点是根节点,那我们直接改变它的颜色,把它变成黑色就可以了。
除此之外,其他情况会违背红黑树的性质,于是需要进行调整。新节点插入之后,如果红黑树的平衡被打破了,那一般会有下面3种情况:
正在处理的节点为X丶父节点为P丶叔叔节点为S丶祖父节点为G丶Hx代表其子树的BH(黑高,如H2,即黑高为2)
CASE1:如果正在处理的节点是X,它的叔叔节点Y是红色
- 将父节点P丶叔叔节点Y的颜色都设置为黑色
- 将祖父节点G的颜色设置成红色
- 正在处理的节点X回溯至祖父节点G(正在处理的节点就是G了,继续调整)
分析:G为红色,可能违背红黑树的性质,需要继续调整(如果G为根节点,则把G的颜色设置为黑色,即满足红黑树的性质,调整结束,此时整个红黑树的BH增加1,这是唯一增加整个红黑树的BH的情形)
CASE2:如果正在处理的节点是X,它的叔叔节点Y是黑色,X是其父节点P的右子节点
- 围绕父节点P左旋
- 把X指向P(即P变成了正在处理的节点)
- 跳到CASE3
分析:P丶X的关系仍然违背了红黑树的性质,需要继续调整
CASE3:如果正在处理的节点是X,它的叔叔节点Y是黑色,X是其父节点P的左子节点
- 将父节点P的颜色设置为黑色,祖父节点G的颜色设置为红色
- 围绕祖父节点右旋
- 调整结束
分析:最后满足红黑树的性质,调整结束
删除操作的平衡调整
红黑树的删除操作的平衡调整要比插入的相对难点。不过原理类似,我们仍然根据正在处理的节点与周围的节点分布特点,来进行一定规则的调整。
正在处理的节点为X丶父节点P丶兄弟节点S丶左侄LN丶右侄RN丶Hx代表其子树的BH
下面正在处理的节点X均为父节点P的左孩子,如果是右孩子,则为镜像操作
CASE1:如果正在处理的节点是X,它的兄弟节点S是红色
- 将兄弟节点的颜色设置为黑色
- 将父节点的颜色色泽为红色
- 围绕父节点P左旋,操作后LN变成新的兄弟节点
分析:X的BH比LN的BH少1,即违背了红黑树的性质,继续调整
CASE2:如果正在处理的节点是X,它的兄弟节点S丶兄弟节点的左右子节点均为黑色
2-1:父节点P是黑色
- 将兄弟节点S的颜色设置为红色
- 正在处理的节点X回溯至父节点P(正在处理的节点就是P了,继续调整)
分析:调整后P的黑高减少了1,即会整个红黑树的的每个节点到达其可达叶子节点的所有路径,包含的黑色节点的数目不同,这违背了红黑树的性质,需要继续调整(若P为根节点的,则执行该步骤会引起BH的减少,这是唯一减小整个红黑树的BH)
2-2:父节点P是红色
- 将兄弟节点S的颜色设置为红色
- 将父节点P的颜色设置为黑色
分析:在父节点没有变色前,其分析和case 2-1是一致的,父节点变色之后,P减少的BH就补回来了,即满足所有性质,调整结束
CASE3:如果正在处理的节点是X,它的兄弟节点S是黑色,S的左子节点LN为红色,右子节点RN为黑色
- 将左侄节点LN的颜色设置为黑色
- 将兄弟节点S的颜色设置为红色
- 围绕兄弟节点S右旋
- S指向LN
- 跳到CASE4
分析:X的BH仍然比LN的BH少1,即继续调整
CASE4:如果正在处理的节点是X,它的兄弟节点S是黑色,父节点P可红可黑,S的右子节点RN为黑色
4-1:LN为红色
- 将兄弟节点S的颜色设置为与父节点P的颜色相同
- 将父节点P的颜色设置为黑色
- 将S的右子节点RN的颜色设置为黑
- 围绕父节点P左旋
- X指向根节点
分析:调整后满足红黑树的性质,调整结束
4-2:LN为黑色
- 将兄弟节点S的颜色设置为与父节点P的颜色相同
- 将父节点P的颜色设置为黑色
- 将S的右子节点RN的颜色设置为黑
- 围绕父节点P左旋
- X指向根节点
分析:调整后满足红黑树的性质,调整结束