红黑树:自平衡二叉查找树
性质1. 节点是红色或黑色。
性质2. 根节点是黑色。
性质3 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
性质4. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
旋转
左旋:
private void rotateLeft(Entry<K,V> p) {
if (p != null) { // 判断旋转节点 p(如图的A) 是否为空
Entry<K,V> r = p.right; // 新建 r 变量为 p 的右孩子(如图的C)
p.right = r.left; // 设置旋转节点 p(A)的新右孩子为旧右孩子(C)的右孩子(C2)
if (r.left != null) // 判断 C1 是否为空
r.left.parent = p; // 设置C1的父亲为旋转节点 p(A)
r.parent = p.parent; // 设置 C 的父亲为A的父亲
if (p.parent == null) // 判断旋转节点的父亲是否为空
root = r; // 如果旋转节点的父亲为空,设置红黑树的根节点为 C
else if (p.parent.left == p) //如果旋转节点的父亲不为空
p.parent.left = r; // 1.旋转节点为其父亲的左孩子,设置新的左孩子为C
else // 2.旋转节点为其父亲的右孩子,设置新的右孩子为C
p.parent.right = r;
r.left = p; // 设置C的新左孩子为旋转节点(A)
p.parent = r; // 设置旋转节点的父亲为 C
}
}
右旋:(同理如上)
private void rotateRight(Entry<K,V> p) {
if (p != null) {
Entry<K,V> l = p.left;
p.left = l.right;
if (l.right != null) l.right.parent = p;
l.parent = p.parent;
if (p.parent == null)
root = l;
else if (p.parent.right == p)
p.parent.right = l;
else p.parent.left = l;
l.right = p;
p.parent = l;
}
}
情况一
情况二
情况三
//插入-----树如何保持平衡
//根据 Comparator(默认<左小右大>或自定义 Comparator )
//插入完成后调用 fixAfterInsertion 方法:
private void fixAfterInsertion(Entry<K,V> x) {
x.color = RED; // 默认插入的新节点为红色
while (x != null && x != root && x.parent.color == RED) { // 1.如果父亲节点为黑色不进行平衡
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 (爷爷节点的父亲节点为黑色,调整结束)
x = parentOf(parentOf(x));
} else {
if (x == rightOf(parentOf(x))) { // 第二种情况(这情况必定是叔叔节点为黑色,可能第一种情况得出):
x = parentOf(x); // 将调整节点 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;
}