红黑树的5个特性
1、 每个节点要么是红色,要么是黑色;
2、 根节点为黑色;
3、 所有叶节点(NIL节点)都是黑色;
4、 每个红色节点的子节点一定是黑色;
5、 从任一节点到其子树中的每个叶子节点的路径都包含相同数量的黑色节点。
红黑树插入/删除分为两步:第一步,像二叉排序树的插入/删除一样进行查找、插入/删除;第二步,通过重新着色和旋转调整结构使整个树满足红黑树的状态
插入节点
为了使插入新节点之后的红黑树尽可能多地满足其5个特性,所以新插入的节点都为红色。这样在插入之后,我们只需要关心插入节点的父节点是否为红色。
由于父节点为黑色时并没有破坏红黑树的特性,所以只需考虑父节点为红色的调整情况。由于父节点位于左子树或者右子树的操作是对称的,这里只介绍父节点在左子树的情况。
情况1:父节点与叔叔节点都为红色
假设新插入节点为N,X表示目前需要调整颜色的节点。将X的父节点与叔叔节点置为黑色,同时将其祖父节点G置为红色。这样一来,G又可能破坏红黑树状态,所以X更新为祖父节点,并进行下一次迭代调整。
情况2:父节点为红色,叔叔节点为黑色
如果新插入节点为右子节点,则需要先将父节点左旋。改变父节点和祖父节点的颜色,并将祖父节点右旋即可重新恢复红黑树状态。
TreeMap插入节点后调整的源码
private void fixAfterInsertion(Entry<K,V> x) {
x.color = RED;//新插入节点颜色为红色
while (x != null && x != root && x.parent.color == RED) {
if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
//插入节点的父节点为祖父节点的左孩子
Entry<K,V> y = rightOf(parentOf(parentOf(x)));//插入节点的叔叔父节点
if (colorOf(y) == RED) {
//情况1
setColor(parentOf(x), BLACK);
setColor(y, BLACK);
setColor(parentOf(parentOf(x)), RED);
x = parentOf(parentOf(x));
} else {
//情况2
if (x == rightOf(parentOf(x))) <