先了解下红黑树的特性:
- 每个节点或者是黑色,或者是红色。
- 根节点是黑色。
- 每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]
- 如果一个节点是红色的,则它的子节点必须是黑色的。
- 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。
java中TreeMap数据结构采用红黑树实现;put方法每次新加元素后,都要调用fixAfterInsertion重新维持红黑树的平衡.
贴源码:
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) {
setColor(parentOf(x), BLACK);
setColor(y, BLACK);
setColor(parentOf(parentOf(x)), RED);
x = parentOf(parentOf(x));
} else {
if (x == rightOf(parentOf(x))) {
x = parentOf(x);
rotateLeft(x);
}
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
rotateRight(parentOf(parentOf(x)));
}
} else {
Entry<K,V> y = leftOf(parentOf(parentOf(x)));
if (colorOf(y) == RED) {
setColor(parentOf(x), BLACK);
setColor(y, BLACK);
setColor(parentOf(parentOf(x)), RED);
x = parentOf(parentOf(x));
} else {
if (x == leftOf(parentOf(x))) {
x = parentOf(x);
rotateRight(x);
}
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
rotateLeft(parentOf(parentOf(x)));
}
}
}
root.color = BLACK;
}
新插入节点为红色
一、父节点是黑色,直接插入不需要重构
二、父节点是红色 (基准节点不是根节点)
1、父亲是祖父的左儿子
①叔叔(右)节点是红色:表示祖父节点必然是黑色。直接开始变色(父亲和叔叔变黑,祖父变红。把基准节点定位到祖父节点,重复这步操作)
②叔叔(右)节点是黑色:
check:该节点是父亲的右儿子,则执行左旋操作(该节点变为父亲,原父亲节点变为左儿子);此时基准节点变为他的原父亲节点,也就是左旋后新的左儿子(最左儿子)
父亲变黑,祖父变红;此时的情况是父亲黑、叔叔黑、祖父红。导致从祖父到叔叔的路径黑色节点变少1个,以祖父节点为基点来一个右旋
2、父亲是祖父的右儿子
①叔叔(左)节点是红色:表示祖父节点必然是黑色。职介开始变色(父亲和叔叔变黑,祖父变红。把基准节点定位到祖父节点,重复这步操作)
②叔叔(左)节点是黑色:
check: 该节点是父亲的左儿子,则执行右旋操作(该节点变为父亲,原父亲节点变为右儿子);此时基准节点变为他的原父亲节点,也就是右旋后新的右儿子(最右儿子)
父亲变黑,祖父变红;此时的情况是父亲黑,叔叔黑,祖父红。导致从祖父到叔叔的路径黑色节点少了1个,以祖父节点为基准来一个左旋