当我们向红黑树中插入一个新节点时,首先将其插入为一个红色节点,然后通过一系列的旋转和变色操作来调整树的结构,以保持红黑树的性质。
下面是红黑树中插入节点时可能出现的情况以及相应的操作:
当插入的节点是树的根节点时,我们将其标记为黑色,即满足性质2。
当插入的节点的父节点是黑色时,我们无需进行任何调整,因为不会破坏红黑树的性质。
当插入的节点的父节点是红色时,此时可能破坏了性质4,即一个红色节点的子节点不能是红色。为了修复这个问题,我们需要进行一些旋转和变色的操作。
以下是修复红黑树插入节点时破坏性质4的情况和相应的操作:
情况1:叔叔节点是红色(父节点的兄弟节点)
解决方案:将父节点和叔叔节点都变为黑色,将祖父节点变为红色,然后将当前节点指向祖父节点,并以祖父节点为基准进行进一步调整。这样可以保持性质5。
情况2:叔叔节点是黑色,当前节点是父节点的右子节点
解决方案:将当前节点设置为其父节点,并以新的当前节点为基准进行左旋转,转化为情况3。
情况3:叔叔节点是黑色,当前节点是父节点的左子节点
解决方案:将父节点设为黑色,祖父节点设为红色,然后以祖父节点为基准进行右旋转。这样可以保持性质5。
通过以上操作,我们可以保持红黑树的性质,并且在最坏情况下,红黑树的高度仍然保持在O(log n)的范围内,保证了高效的插入和搜索操作。
在给出的JavaScript示例中,我们实现了红黑树的插入操作。首先,我们定义了一个Node类来表示树中的节点,每个节点包含键、值、颜色以及左右子节点和父节点的引用。然后,我们定义了RedBlackTree类,其中包含了插入节点和修复违规的方法。
在插入节点的方法中,我们首先判断树是否为空,如果为空,则将新节点作为根节点。否则,我们调用insertNode方法来递归地插入节点到正确的位置。插入完成后,我们调用fixViolation方法来修复违规,确保红黑树的性质得到保持。
在fixViolation方法中,我们使用while循环来处理可能出现的违规情况。根据当前节点的父节点、祖父节点以及叔叔节点的颜色,我们执行相应的旋转和变色操作来修复违规。
最后,给出了一个使用示例,通过插入一些节点来构建红黑树。你可以根据需要扩展该示例,添加其他方法如删除节点、搜索节点等。
class Node {
constructor(key, value, color) {
this.key = key;
this.value = value;
this.color = color;
this.left = null;
this.right = null;
this.parent = null;
}
}
class RedBlackTree {
constructor() {
this.root = null;
}
insert(key, value) {
const newNode = new Node(key, value, "red");
if (this.root === null) {
this.root = newNode;
} else {
this.insertNode(this.root, newNode);
}
this.fixViolation(newNode);
}
insertNode(root, newNode) {
if (newNode.key < root.key) {
if (root.left === null) {
root.left = newNode;
newNode.parent = root;
} else {
this.insertNode(root.left, newNode);
}
} else if (newNode.key > root.key) {
if (root.right === null) {
root.right = newNode;
newNode.parent = root;
} else {
this.insertNode(root.right, newNode);
}
}
}
fixViolation(node) {
while (
node !== this.root &&
node.color === "red" &&
node.parent.color === "red"
) {
const parent = node.parent;
const grandParent = parent.parent;
if (parent === grandParent.left) {
const uncle = grandParent.right;
if (uncle !== null && uncle.color === "red") {
grandParent.color = "red";
parent.color = "black";
uncle.color = "black";
node = grandParent;
} else {
if (node === parent.right) {
this.rotateLeft(parent);
node = parent;
parent = node.parent;
}
parent.color = "black";
grandParent.color = "red";
this.rotateRight(grandParent);
}
} else {
const uncle = grandParent.left;
if (uncle !== null && uncle.color === "red") {
grandParent.color = "red";
parent.color = "black";
uncle.color = "black";
node = grandParent;
} else {
if (node === parent.left) {
this.rotateRight(parent);
node = parent;
parent = node.parent;
}
parent.color = "black";
grandParent.color = "red";
this.rotateLeft(grandParent);
}
}
}
this.root.color = "black";
}
rotateLeft(node) {
const rightChild = node.right;
node.right = rightChild.left;
if (rightChild.left !== null) {
rightChild.left.parent = node;
}
rightChild.parent = node.parent;
if (node.parent === null) {
this.root = rightChild;
} else if (node === node.parent.left) {
node.parent.left = rightChild;
} else {
node.parent.right = rightChild;
}
rightChild.left = node;
node.parent = rightChild;
}
rotateRight(node) {
const leftChild = node.left;
node.left = leftChild.right;
if (leftChild.right !== null) {
leftChild.right.parent = node;
}
leftChild.parent = node.parent;
if (node.parent === null) {
this.root = leftChild;
} else if (node === node.parent.left) {
node.parent.left = leftChild;
} else {
node.parent.right = leftChild;
}
leftChild.right = node;
node.parent = leftChild;
}
// 其他方法,如删除节点等
}
// 使用示例
const tree = new RedBlackTree();
tree.insert(10, "value1");
tree.insert(20, "value2");
tree.insert(30, "value3");
tree.insert(15, "value4");
tree.insert(25, "value5");
上述代码实现了红黑树的插入操作,并通过一系列的旋转和变色操作来保持树的平衡。你可以根据需要添加其他方法,如删除节点等。