在Java中实现红黑树的旋转和重新着色操作是红黑树维护平衡的关键部分。红黑树通过左旋(left rotate)、右旋(right rotate)以及重新着色(recoloring)等操作来保持树的平衡性。下面我将简要介绍这些操作的基本思想,并提供Java代码示例。
1. 旋转操作
左旋(Left Rotate)
左旋是将一个节点以其右孩子为轴进行顺时针旋转的操作。旋转后,原右孩子成为新的根节点,原节点成为新根节点的左孩子,原右孩子的左孩子(如果有)成为原节点的右孩子。
private void leftRotate(RedBlackTreeNode<T> x) {
RedBlackTreeNode<T> y = x.right;
x.right = y.left;
if (y.left != null) {
y.left.parent = x;
}
y.parent = x.parent;
if (x.parent == null) {
this.root = y;
} else if (x == x.parent.left) {
x.parent.left = y;
} else {
x.parent.right = y;
}
y.left = x;
x.parent = y;
}
右旋(Right Rotate)
右旋是将一个节点以其左孩子为轴进行逆时针旋转的操作。旋转后,原左孩子成为新的根节点,原节点成为新根节点的右孩子,原左孩子的右孩子(如果有)成为原节点的左孩子。
private void rightRotate(RedBlackTreeNode<T> x) {
RedBlackTreeNode<T> y = x.left;
x.left = y.right;
if (y.right != null) {
y.right.parent = x;
}
y.parent = x.parent;
if (x.parent == null) {
this.root = y;
} else if (x == x.parent.right) {
x.parent.right = y;
} else {
x.parent.left = y;
}
y.right = x;
x.parent = y;
}
2. 重新着色
重新着色主要是将节点的颜色从红色改为黑色,或从黑色改为红色,以维持红黑树的性质。这通常与旋转操作一起使用,以确保在插入或删除节点后,树仍然保持平衡。
示例:插入节点后的修复
当在红黑树中插入一个新节点时,该节点被着色为红色。如果这违反了红黑树的性质,则需要进行一系列的旋转和重新着色操作来恢复平衡。
private void fixAfterInsertion(RedBlackTreeNode<T> z) {
RedBlackTreeNode<T> y;
while (z != root && z.parent.color == Color.RED) {
if (z.parent == z.parent.parent.left) {
y = z.parent.parent.right;
if (y != null && y.color == Color.RED) {
// Case 1: z的叔父节点y也是红色的
z.parent.color = Color.BLACK;
y.color = Color.BLACK;
z.parent.parent.color = Color.RED;
z = z.parent.parent;
} else {
if (z == z.parent.right) {
// Case 2: z是右孩子
z = z.parent;
leftRotate(z);
}
// Case 3: z是左孩子,且z的叔父节点是黑色的
z.parent.color = Color.BLACK;
z.parent.parent.color = Color.RED;
rightRotate(z.parent.parent);
}
} else {
// 与上面类似,但处理的是z是左孩子的情况
// ...(省略,与右子树情况镜像)
}
}
root.color = Color.BLACK;
}