红黑树的null节点
时间: 2024-08-13 07:10:13 浏览: 126
红黑树是一种自平衡二叉查找树,它的设计是为了保证在各种操作(如插入、删除和查找)后的最坏情况下的性能。在红黑树中,每个节点都有一个颜色属性,可以是红色或黑色。为了支持空节点,红黑树会定义一个特殊的"NULL"节点。
1. **NULL节点**:在红黑树中,每个非叶子节点(即非终端节点,既不是根也不是叶子)都会有一个子节点表示为NULL。这是用来表示某个方向上没有子节点的情况,例如左孩子或右孩子可能为空。NULL节点并不是实际的数据存储位置,而是一个标记,表示该位置不存在元素。
2. **空树的表示**:对于根节点,如果它是NULL,则表示整棵树为空;如果它被标记为红色或黑色,则表示树仅包含根节点,且为空。
3. **插入和删除操作**:当执行插入或删除操作时,红黑树会保持其规则不变,如每条路径从根到叶子的最长颜色序列不超过两倍最短,这样即使添加或移除节点也不会导致严重的不平衡。在处理NULL节点时,这些规则同样适用。
相关问题
Java设计一棵红黑树,方法包括插入节点,删除节点和查找节点
红黑树是一种自平衡二叉查找树,它保证了插入、删除和查找操作的最坏情况时间复杂度为 O(log n)。红黑树的节点有两种颜色,红色和黑色,同时满足以下性质:
1. 根节点为黑色;
2. 所有叶子节点都是黑色;
3. 如果一个节点是红色的,则它的两个子节点都是黑色的;
4. 从任意一个节点到其每个叶子节点的所有路径都包含相同数目的黑色节点;
5. 每个节点的左子树和右子树都是红黑树。
下面是 Java 实现红黑树的代码:
```
public class RedBlackTree<T extends Comparable<T>> {
private Node<T> root;
private static final boolean RED = true;
private static final boolean BLACK = false;
private static class Node<T> {
T value;
Node<T> left, right;
boolean color;
Node(T value, boolean color) {
this.value = value;
this.color = color;
}
}
// 插入节点
public void insert(T value) {
root = insert(root, value);
root.color = BLACK;
}
private Node<T> insert(Node<T> node, T value) {
if (node == null) {
return new Node<>(value, RED);
}
int cmp = value.compareTo(node.value);
if (cmp < 0) {
node.left = insert(node.left, value);
} else if (cmp > 0) {
node.right = insert(node.right, value);
} else {
node.value = value;
}
if (isRed(node.right) && !isRed(node.left)) {
node = rotateLeft(node);
}
if (isRed(node.left) && isRed(node.left.left)) {
node = rotateRight(node);
}
if (isRed(node.left) && isRed(node.right)) {
flipColors(node);
}
return node;
}
// 删除节点
public void delete(T value) {
if (root == null) {
return;
}
if (!isRed(root.left) && !isRed(root.right)) {
root.color = RED;
}
root = delete(root, value);
if (root != null && !isRed(root.left) && !isRed(root.right)) {
root.color = BLACK;
}
}
private Node<T> delete(Node<T> node, T value) {
if (value.compareTo(node.value) < 0) {
if (!isRed(node.left) && !isRed(node.left.left)) {
node = moveRedLeft(node);
}
node.left = delete(node.left, value);
} else {
if (isRed(node.left)) {
node = rotateRight(node);
}
if (value.compareTo(node.value) == 0 && node.right == null) {
return null;
}
if (!isRed(node.right) && !isRed(node.right.left)) {
node = moveRedRight(node);
}
if (value.compareTo(node.value) == 0) {
Node<T> min = findMin(node.right);
node.value = min.value;
node.right = deleteMin(node.right);
} else {
node.right = delete(node.right, value);
}
}
return balance(node);
}
// 查找节点
public Node<T> find(T value) {
Node<T> node = root;
while (node != null) {
int cmp = value.compareTo(node.value);
if (cmp < 0) {
node = node.left;
} else if (cmp > 0) {
node = node.right;
} else {
return node;
}
}
return null;
}
private boolean isRed(Node<T> node) {
return node != null && node.color == RED;
}
private Node<T> rotateLeft(Node<T> node) {
Node<T> x = node.right;
node.right = x.left;
x.left = node;
x.color = node.color;
node.color = RED;
return x;
}
private Node<T> rotateRight(Node<T> node) {
Node<T> x = node.left;
node.left = x.right;
x.right = node;
x.color = node.color;
node.color = RED;
return x;
}
private void flipColors(Node<T> node) {
node.color = RED;
node.left.color = BLACK;
node.right.color = BLACK;
}
private Node<T> moveRedLeft(Node<T> node) {
flipColors(node);
if (isRed(node.right.left)) {
node.right = rotateRight(node.right);
node = rotateLeft(node);
flipColors(node);
}
return node;
}
private Node<T> moveRedRight(Node<T> node) {
flipColors(node);
if (isRed(node.left.left)) {
node = rotateRight(node);
flipColors(node);
}
return node;
}
private Node<T> findMin(Node<T> node) {
while (node.left != null) {
node = node.left;
}
return node;
}
private Node<T> deleteMin(Node<T> node) {
if (node.left == null) {
return null;
}
if (!isRed(node.left) && !isRed(node.left.left)) {
node = moveRedLeft(node);
}
node.left = deleteMin(node.left);
return balance(node);
}
private Node<T> balance(Node<T> node) {
if (isRed(node.right)) {
node = rotateLeft(node);
}
if (isRed(node.left) && isRed(node.left.left)) {
node = rotateRight(node);
}
if (isRed(node.left) && isRed(node.right)) {
flipColors(node);
}
return node;
}
}
```
其中,插入节点和删除节点都需要进行旋转和颜色翻转等操作来保证红黑树的性质。查找节点则是一个简单的二叉查找。
用java构建红黑树,并包含节点的增加和删除
红黑树是一种自平衡二叉查找树,其性质如下:
1. 每个节点要么是红色,要么是黑色。
2. 根节点是黑色。
3. 每个叶子节点(NIL节点,空节点)是黑色的。
4. 如果一个节点是红色的,则它的两个子节点都是黑色的。
5. 对于每个节点,从该节点到其所有后代叶子节点的简单路径上,均包含相同数目的黑色节点。
下面是Java代码实现红黑树,包括节点的增加和删除:
```java
public class RedBlackTree {
private final int RED = 0;
private final int BLACK = 1;
private class Node {
int val = -1;
int color = BLACK;
Node left = null;
Node right = null;
Node parent = null;
public Node(int val) {
this.val = val;
}
}
private Node root = null;
public void insert(int val) {
Node newNode = new Node(val);
Node parent = null;
Node node = root;
while (node != null) {
parent = node;
if (val < node.val) {
node = node.left;
} else {
node = node.right;
}
}
newNode.parent = parent;
if (parent == null) {
root = newNode;
} else if (val < parent.val) {
parent.left = newNode;
} else {
parent.right = newNode;
}
insertFixUp(newNode);
}
private void insertFixUp(Node node) {
Node parent, grandParent;
while ((parent = node.parent) != null && parent.color == RED) {
grandParent = parent.parent;
if (parent == grandParent.left) {
Node uncle = grandParent.right;
if (uncle != null && uncle.color == RED) {
parent.color = BLACK;
uncle.color = BLACK;
grandParent.color = RED;
node = grandParent;
} else {
if (node == parent.right) {
leftRotate(parent);
Node temp = parent;
parent = node;
node = temp;
}
parent.color = BLACK;
grandParent.color = RED;
rightRotate(grandParent);
}
} else {
Node uncle = grandParent.left;
if (uncle != null && uncle.color == RED) {
parent.color = BLACK;
uncle.color = BLACK;
grandParent.color = RED;
node = grandParent;
} else {
if (node == parent.left) {
rightRotate(parent);
Node temp = parent;
parent = node;
node = temp;
}
parent.color = BLACK;
grandParent.color = RED;
leftRotate(grandParent);
}
}
}
root.color = BLACK;
}
private void leftRotate(Node node) {
Node right = node.right;
node.right = right.left;
if (right.left != null) {
right.left.parent = node;
}
right.parent = node.parent;
if (node.parent == null) {
root = right;
} else if (node == node.parent.left) {
node.parent.left = right;
} else {
node.parent.right = right;
}
right.left = node;
node.parent = right;
}
private void rightRotate(Node node) {
Node left = node.left;
node.left = left.right;
if (left.right != null) {
left.right.parent = node;
}
left.parent = node.parent;
if (node.parent == null) {
root = left;
} else if (node == node.parent.right) {
node.parent.right = left;
} else {
node.parent.left = left;
}
left.right = node;
node.parent = left;
}
public void delete(int val) {
Node node = search(val);
if (node == null) {
return;
}
Node child, parent;
int color;
if (node.left != null && node.right != null) {
Node replace = node.right;
while (replace.left != null) {
replace = replace.left;
}
if (node.parent != null) {
if (node == node.parent.left) {
node.parent.left = replace;
} else {
node.parent.right = replace;
}
} else {
root = replace;
}
child = replace.right;
parent = replace.parent;
color = replace.color;
if (parent == node) {
parent = replace;
} else {
if (child != null) {
child.parent = parent;
}
parent.left = child;
replace.right = node.right;
node.right.parent = replace;
}
replace.parent = node.parent;
replace.color = node.color;
replace.left = node.left;
node.left.parent = replace;
if (color == BLACK) {
deleteFixUp(child, parent);
}
node = null;
return;
}
if (node.left != null) {
child = node.left;
} else {
child = node.right;
}
parent = node.parent;
color = node.color;
if (child != null) {
child.parent = parent;
}
if (parent != null) {
if (node == parent.left) {
parent.left = child;
} else {
parent.right = child;
}
} else {
root = child;
}
if (color == BLACK) {
deleteFixUp(child, parent);
}
node = null;
}
private void deleteFixUp(Node node, Node parent) {
Node other;
while ((node == null || node.color == BLACK) && node != root) {
if (parent.left == node) {
other = parent.right;
if (other.color == RED) {
other.color = BLACK;
parent.color = RED;
leftRotate(parent);
other = parent.right;
}
if ((other.left == null || other.left.color == BLACK) &&
(other.right == null || other.right.color == BLACK)) {
other.color = RED;
node = parent;
parent = node.parent;
} else {
if (other.right == null || other.right.color == BLACK) {
other.left.color = BLACK;
other.color = RED;
rightRotate(other);
other = parent.right;
}
other.color = parent.color;
parent.color = BLACK;
other.right.color = BLACK;
leftRotate(parent);
node = root;
break;
}
} else {
other = parent.left;
if (other.color == RED) {
other.color = BLACK;
parent.color = RED;
rightRotate(parent);
other = parent.left;
}
if ((other.left == null || other.left.color == BLACK) &&
(other.right == null || other.right.color == BLACK)) {
other.color = RED;
node = parent;
parent = node.parent;
} else {
if (other.left == null || other.left.color == BLACK) {
other.right.color = BLACK;
other.color = RED;
leftRotate(other);
other = parent.left;
}
other.color = parent.color;
parent.color = BLACK;
other.left.color = BLACK;
rightRotate(parent);
node = root;
break;
}
}
}
if (node != null) {
node.color = BLACK;
}
}
private Node search(int val) {
Node node = root;
while (node != null) {
if (node.val == val) {
return node;
} else if (val < node.val) {
node = node.left;
} else {
node = node.right;
}
}
return null;
}
}
```
注:以上代码仅供学习参考,实际使用要根据具体情况进行修改。
阅读全文