红黑树的删除操作比较复杂。首先我们知道,被删除节点y永远只有一个子树(原因是,如果有两个子树的话,我们就会删除它的直接后继,它的直接后继最多有一个子树;如果它没有子树的话,我们就把它的右子树定为nil)。nil是一个用来取代NULL的节点,颜色为黑。
下面我们分情况来讨论:
- 如果y和x在左子树上
- 如果被删除节点y为红色,那么可以直接用它的黑儿子x来取代它。
- 如果被删除的节点y是黑色的话,x是y的儿子,那么就继续分情况讨论。
2.1.若x是红色的话,将x的颜色改为黑色。调整结束。
2.2.如果x是黑色的话。那么为了保证黑高度,x节点的颜色就变为为黑+黑(只是代表,见算法导论)用w指向x的兄弟节点。这违反了或红或黑原则。所以需要调整。下面要继续分情况讨论
2.2.1.如果x是root,那么调整结束。
2.2.2.如果x的兄弟节点w是红色的话
将P变成红色,S变为黑色,然后对P进行左旋操作。这样就可以转化成以下的情况2.2.3.2 2.2.4或者2.2.5来处理。
2.2.3.如果x,w都是黑色的,w的儿子也是黑色的。继续分情况讨论
2.2.3.1.如果x的父亲是黑色的
将S(w)和N(x)都抽出一点黑色,那么N变为黑色,S变为红色,P则变为黑+黑,x指向P。继续调整下去。
2.2.3.2.如果x的父亲是红色的
将S(w)和N(x)都抽出一点黑色,那么N变为黑色,S变为红色,P则变为黑色,调整结束。
2.2.4.如果x,w的颜色都是黑色,w的左儿子是红色,右儿子是黑色。
只对w的子树进行操作,不动x和x的父亲。将S染成红色,然后S右旋。则转化成情况2.2.5.继续调整。
2.2.5.如果x,w的颜色都是黑色,w的右儿子是红色,左儿子不管。
交换P和S的颜色,SR染成黑色,然后对P左旋,调整结束。
- 如果y和x在右子树上,情况与上面极其相似,不再详细介绍。
- 如果被删除节点y为红色,那么可以直接用它的黑儿子x来取代它。
- 如果被删除的节点y是黑色的话,x是y的儿子,那么就继续分情况讨论。
2.1.若x是红色的话,并将x的颜色改为黑色。
2.2.如果x是黑色的话。用w指向x的兄弟节点,用指针x指向该节点,它的颜色为黑+黑。这违反了或红或黑原则。所以需要调整。下面要继续分情况讨论
2.2.1.如果x是root,那么调整结束。
2.2.2.如果x的兄弟节点w是红色的话
2.2.3.如果x,w都是黑色的,w的儿子也是黑色的。继续分情况讨论
2.2.3.1.如果x的父亲是黑色的
2.2.3.2.如果x的父亲是红色的
2.2.4.如果x,w的颜色都是黑色,w的右儿子是红色,左儿子是黑色。
2.2.5.如果x,w的颜色都是黑色,w的左儿子是红色,右儿子不管。
图片来自维基百科。
参考文献: