用Java写一个红黑树
时间: 2023-08-31 11:23:25 浏览: 61
### 回答1:
我不太清楚Java的语法,但我可以尝试为您解释一下红黑树,红黑树是一种特殊的二叉搜索树,它具有以下性质:每个节点都是红色或黑色;根节点是黑色;每个叶子节点(NIL节点)是黑色;父节点关联的子节点都是红色;从任一节点到其叶子节点的所有路径都包含相同数量的黑色节点。
### 回答2:
红黑树是一种自平衡的二叉搜索树,它具有以下特征:
1. 每个节点都有一个颜色,红色或黑色。
2. 根节点为黑色。
3. 每个叶子节点(NIL节点,空节点)为黑色。
4. 如果一个节点是红色的,则它的两个子节点都是黑色的。
5. 对于每个节点,从该节点到其所有后代叶子节点的简单路径上,均包含相同数目的黑色节点。
下面是使用Java语言实现红黑树的代码示例:
```
class Node {
int data;
Node parent;
Node left;
Node right;
int color;
public Node(int data) {
this.data = data;
color = 1;
}
}
public class RedBlackTree {
private Node root;
private Node TNULL;
// 构造函数
public RedBlackTree() {
TNULL = new Node(0);
TNULL.color = 0;
TNULL.left = null;
TNULL.right = null;
root = TNULL;
}
// 前序遍历
private void preOrderHelper(Node node) {
if (node != TNULL) {
System.out.print(node.data + " ");
preOrderHelper(node.left);
preOrderHelper(node.right);
}
}
// 中序遍历
private void inOrderHelper(Node node) {
if (node != TNULL) {
inOrderHelper(node.left);
System.out.print(node.data + " ");
inOrderHelper(node.right);
}
}
// 后序遍历
private void postOrderHelper(Node node) {
if (node != TNULL) {
postOrderHelper(node.left);
postOrderHelper(node.right);
System.out.print(node.data + " ");
}
}
// 搜索节点
private Node searchTreeHelper(Node node, int key) {
if (node == TNULL || key == node.data) {
return node;
}
if (key < node.data) {
return searchTreeHelper(node.left, key);
}
return searchTreeHelper(node.right, key);
}
// 查找树中的最小节点
private Node minimum(Node node) {
while (node.left != TNULL) {
node = node.left;
}
return node;
}
// 查找树中的最大节点
private Node maximum(Node node) {
while (node.right != TNULL) {
node = node.right;
}
return node;
}
// 获取后继节点
private Node successor(Node x) {
if (x.right != TNULL) {
return minimum(x.right);
}
Node y = x.parent;
while (y != TNULL && x == y.right) {
x = y;
y = y.parent;
}
return y;
}
// 获取前驱节点
private Node predecessor(Node x) {
if (x.left != TNULL) {
return maximum(x.left);
}
Node y = x.parent;
while (y != TNULL && x == y.left) {
x = y;
y = y.parent;
}
return y;
}
// 左旋转
private void leftRotate(Node x) {
Node y = x.right;
x.right = y.left;
if (y.left != TNULL) {
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;
}
// 右旋转
private void rightRotate(Node x) {
Node y = x.left;
x.left = y.right;
if (y.right != TNULL) {
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;
}
// 插入节点的辅助方法
private void fixInsert(Node x) {
Node y;
while (x.parent.color == 1) {
if (x.parent == x.parent.parent.right) {
y = x.parent.parent.left;
if (y.color == 1) {
y.color = 0;
x.parent.color = 0;
x.parent.parent.color = 1;
x = x.parent.parent;
} else {
if (x == x.parent.left) {
x = x.parent;
rightRotate(x);
}
x.parent.color = 0;
x.parent.parent.color = 1;
leftRotate(x.parent.parent);
}
} else {
y = x.parent.parent.right;
if (y.color == 1) {
y.color = 0;
x.parent.color = 0;
x.parent.parent.color = 1;
x = x.parent.parent;
} else {
if (x == x.parent.right) {
x = x.parent;
leftRotate(x);
}
x.parent.color = 0;
x.parent.parent.color = 1;
rightRotate(x.parent.parent);
}
}
if (x == root) {
break;
}
}
root.color = 0;
}
// 插入节点
private void insert(int key) {
Node node = new Node(key);
node.parent = null;
node.data = key;
node.left = TNULL;
node.right = TNULL;
node.color = 1;
Node y = null;
Node x = this.root;
while (x != TNULL) {
y = x;
if (node.data < x.data) {
x = x.left;
} else {
x = x.right;
}
}
node.parent = y;
if (y == null) {
root = node;
} else if (node.data < y.data) {
y.left = node;
} else {
y.right = node;
}
if (node.parent == null) {
node.color = 0;
return;
}
if (node.parent.parent == null) {
return;
}
fixInsert(node);
}
// 删除节点的辅助方法
private void fixDelete(Node x) {
Node s;
while (x != root && x.color == 0) {
if (x == x.parent.left) {
s = x.parent.right;
if (s.color == 1) {
s.color = 0;
x.parent.color = 1;
leftRotate(x.parent);
s = x.parent.right;
}
if (s.left.color == 0 && s.right.color == 0) {
s.color = 1;
x = x.parent;
} else {
if (s.right.color == 0) {
s.left.color = 0;
s.color = 1;
rightRotate(s);
s = x.parent.right;
}
s.color = x.parent.color;
x.parent.color = 0;
s.right.color = 0;
leftRotate(x.parent);
x = root;
}
} else {
s = x.parent.left;
if (s.color == 1) {
s.color = 0;
x.parent.color = 1;
rightRotate(x.parent);
s = x.parent.left;
}
if (s.right.color == 0 && s.right.color == 0) {
s.color = 1;
x = x.parent;
} else {
if (s.left.color == 0) {
s.right.color = 0;
s.color = 1;
leftRotate(s);
s = x.parent.left;
}
s.color = x.parent.color;
x.parent.color = 0;
s.left.color = 0;
rightRotate(x.parent);
x = root;
}
}
}
x.color = 0;
}
// 删除节点
private void deleteNodeHelper(Node node, int key) {
Node z = TNULL;
Node x, y;
while (node != TNULL) {
if (node.data == key) {
z = node;
}
if (node.data <= key) {
node = node.right;
} else {
node = node.left;
}
}
if (z == TNULL) {
System.out.println("Couldn't find key in the tree");
return;
}
y = z;
int yOriginalColor = y.color;
if (z.left == TNULL) {
x = z.right;
transplant(z, z.right);
} else if (z.right == TNULL) {
x = z.left;
transplant(z, z.left);
} else {
y = minimum(z.right);
yOriginalColor = y.color;
x = y.right;
if (y.parent == z) {
x.parent = y;
} else {
transplant(y, y.right);
y.right = z.right;
y.right.parent = y;
}
transplant(z, y);
y.left = z.left;
y.left.parent = y;
y.color = z.color;
}
if (yOriginalColor == 0) {
fixDelete(x);
}
}
// 辅助方法,用于替换节点
private void transplant(Node u, Node v) {
if (u.parent == null) {
root = v;
} else if (u == u.parent.left) {
u.parent.left = v;
} else {
u.parent.right = v;
}
v.parent = u.parent;
}
// 前序遍历
public void preorder() {
preOrderHelper(this.root);
}
// 中序遍历
public void inorder() {
inOrderHelper(this.root);
}
// 后序遍历
public void postorder() {
postOrderHelper(this.root);
}
// 搜索节点
public Node searchTree(int k) {
return searchTreeHelper(this.root, k);
}
// 查找树中的最小节点
public Node minimum() {
return minimum(this.root);
}
// 查找树中的最大节点
public Node maximum() {
return maximum(this.root);
}
// 获取后继节点
public Node successor(int key) {
Node node = searchTree(key);
if (node != TNULL) {
return successor(node);
}
return null;
}
// 获取前驱节点
public Node predecessor(int key) {
Node node = searchTree(key);
if (node != TNULL) {
return predecessor(node);
}
return null;
}
// 插入节点
public void insert(int key) {
insert(key);
}
// 删除节点
public void deleteNode(int data) {
deleteNodeHelper(this.root, data);
}
}
```
以上是一个用Java实现的红黑树。实现上述代码后,我们可以使用该红黑树类进行插入、删除、搜索以及遍历等操作。根据需求,可以调用相应的方法进行操作并打印结果。
### 回答3:
红黑树是一种自平衡的二叉查找树,它的插入、查找和删除的时间复杂度都为O(logN),其中N为树中节点的数量。在Java中可以通过定义一个红黑树的节点类和红黑树类来实现。
首先定义一个节点类RedBlackNode,这个类包含五个属性:key表示节点的值,parent表示父节点,left表示左子节点,right表示右子节点,color表示节点的颜色(红色或黑色)。
接下来定义一个红黑树类RedBlackTree,这个类包含三个属性:root表示根节点,NIL表示叶子节点,NIL节点的颜色为黑色。在构造函数中,将NIL节点初始化,并将root节点指向NIL。
红黑树类还包含一系列方法用于插入、删除和查找节点。例如,插入节点可以通过递归地将节点插入到合适的位置,然后调整树的结构来保持红黑树的平衡。删除节点同样需要进行树的调整,确保删除节点后红黑树的性质不变。
红黑树的查找可以通过递归或迭代实现。递归查找时,先与当前节点比较,如果相等则返回该节点;如果小于当前节点的值则递归查找左子树,如果大于当前节点的值则递归查找右子树。迭代查找时,从根节点开始,依次与每个节点比较,直到找到相等的节点或遍历到叶子节点为止。
在红黑树类中,还可以实现其他一些方法,如获取最小值、最大值、前驱节点、后继节点等。
通过以上步骤,就可以用Java写一个红黑树。在实际使用中,可以根据自己的需求对红黑树进行扩展和优化。