文章目录
  1. 红黑树的定义
  2. 插入-自底向上调整
  3. 插入-自顶向下调整
  4. 自顶向下删除

红黑树的定义

AVL树的一个流行的变种就是红黑树。红黑树是具有下列着色性质的二叉查找树。

  • 每一节点或着成红色,或着成黑色;
  • 根节点为黑色;
  • 红色节点的子节点必须是黑色;
  • 任一节点到NULL指针的每一条路径必须包含相同数目的黑色节点;

如下图是一个红黑树的示例。

注:红黑树是AVL树的变种,不再严格遵守AVL树的要求;对红黑树的插入即对二叉查找树的插入再加上一定的调整。

插入-自底向上调整

承认一个事实:根据第四条性质,插入的节点必须涂成红色!此时,若父节点就是黑色,则插入完成;否则与第三条性质冲突,必须对该树进行调整,调整包括改色与旋转。

注意到红黑树也是AVL树,在插入的时候也需要进行对应的旋转操作;当插入完成后,还需要进行调整以满足红黑树的性质。记插入的节点为X,(已插入的)X的父节点为P,P的兄弟节点为S。

若S是黑色节点,此时X与S的”搭配”有两种情形(每种都有对称情形)。所做的调整如下。

 

调整之后红黑树的性质满足。

若S为红色节点,再做如上图的调整仍不满足红黑树的性质,只能继续调整。

由于S此时为红色节点,使得新树不满足第三条性质,故需要进行调整;同时,为了保证第四条性质,P-G-S中只能有一个黑色节点,因此只能将P、S涂成红色,G涂成黑色。若P的父节点为黑色节点,则插入完成;

否则,还需要进行调整,记P的父节点为Y,则此时的(P , Y)就是初始时的(X, P),因此对其进行同样的处理,直到某个”父节点”的兄弟节点为黑色节点或到达根节点(根节点为黑色节点,因此递归一定能结束)。

插入-自顶向下调整

插入之后自底向上调整需要一个栈来保存查找路径上的节点;事实上,插入也可以采用自顶向下的方式,在查找的过程中对树进行调整以保证”S”始终为黑色节点!

对遍历的节点X,若X的两个子节点均为红色,由第三条性质,X必为黑色节点,将X与其子节点进行颜色对换,若X的父节点为黑色,则在X处的调整完成;

否则,注意到X的父节点为红色,因此X的父节点的兄弟节点一定不是红色(否则会与它们的父节点进行颜色对换,从而X的父节点不会为红色),因此可使用上图中的旋转进行处理。

查找完成之后,将待插入节点插入路径终点对应子节点。

注:在具体实现中,使用两个标记节点:根与NullNode;根标记将存储关键字$\infty$以及指向真正根的右指针;

自顶向下删除

对于要删除的节点,有以下几种可能:叶节点、双子节点,单支红子黑节点;因为以下四种单支情况不可能出现。

 

对于删除的任意非叶节点X,若它有右子树,则用右子树上的最小值节点将其替换(颜色使用X的颜色),若X无右子树,那么它一定有左子树,则用左子树上的最大值节点将其替换(颜色使用X的颜色),那么删除的节点就变为右子树上的最小值节点;

这个节点最多有一个右子节点(左子节点),如果它有一个右子节点(左子节点),那么将它删除之后使用子节点涂黑补位即可!

否则,删除的就是叶节点,若这个叶节点为红色,直接删除即可!

否则,就是要删除一个黑色叶节点。

综上,所有的情况都能转换成删除一个叶节点,若叶节点为红色,直接删除即可!否则,就是删除一个黑色叶节点。删除黑色叶节点可采用自底向上或自顶向下的方式,自底向上的方式过于复杂,感兴趣可参考July对红黑树的讲解;相比之下,自顶向下的删除有一个自始至终的目标——保证当前节点为红色。

1
2
3
4
5
初始:将根节点涂红; 当前节点记为X, X的兄弟节点记为T, X的父节点记为P

循环:沿根节点至待删除黑色叶节点的路径下降

新状态:新的P即原来的X, 故P为红色节点, X与T为黑色节点

X的子节点均为黑色

(1) T的子节点亦全为黑色;则P、T、X颜色翻转即可;

(2) T有一个红子节点,根据这个红子节点是左或右,进行如下图的旋转;

 

X有红节点

先下降,若X落到红子节点,则继续下降即可;否则,将P、T进行颜色翻转,然后旋转P与T重新进入P红X黑T黑的情形。

 

参考链接

红黑树的删除—自顶向下

红黑树在线演示