性质
-
节点是红色或者黑色
-
根节点是黑色
-
所有叶子节点都是黑色(叶子是NULL节点)
-
每个红色节点的两个子节点都是黑色
-
从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点
红黑树插入情景(插入节点为红色)
-
红黑树为空树
-
插入节点已存在
-
插入节点的父节点是黑节点
-
插入节点的父节点是红色
-
插入节点的父节点是祖父节点的左节点
-
插入节点的叔叔节点是红色
-
插入节点的叔叔节点为黑色或者没有叔叔节点
-
插入节点为父节点的左子节点
-
插入节点为父节点的右节点
-
-
-
插入节点的父节点是祖父节点的右节点
-
插入节点的叔叔节点是红色
-
插入节点的叔叔节点为黑色或者没有叔叔节点
-
插入节点为父节点的右子节点
-
插入节点为父节点的左子结点
-
-
-
红黑树插入重新平衡的方式
变色、左旋、右旋
红黑树的Java代码实现(插入操作)
public class RBTree {
public static final Boolean RED = true;
public static final Boolean Black = false;
private Node root;
// 节点
static class Node {
Node parent;
Node left;
Node right;
int value;
boolean color;
public Node() {
}
public Node(Node parent, Node left, Node right, int value, boolean color) {
this.parent = parent;
this.left = left;
this.right = right;
this.value = value;
this.color = color;
}
public Node(int value, boolean color) {
this.value = value;
this.color = color;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
", color=" + color +
'}';
}
}
// 先序遍历
public void foreword() {
foreword(this.root);
}
private void foreword(Node root) {
if (root == null) {
// System.out.println("该树为空树!");
return;
}
System.out.println(root);
if (root.left != null) {
foreword(root.left);
}
if (root.right != null) {
foreword(root.right);
}
}
// 左旋
public Node leftRotate(Node node) {
if (node == null || node.right == null) {
throw new RuntimeException("该节点不能进行左旋!");
}
Node tmp = node.right;
tmp.parent = node.parent;
if (node.parent != null) {
if (node.parent.left == node) {
node.parent.left = tmp;
} else {
node.parent.right = tmp;
}
}
node.right = tmp.left;
if (tmp.left != null) {
tmp.left.parent = node;
}
tmp.left = node;
node.parent = tmp;
if (node == this.root) {
this.root = tmp;
}
return tmp;
}
// 右旋
public Node rightRotate(Node node) {
if (node == null || node.left == null) {
throw new RuntimeException("该节点不能进行右旋");
}
Node tmp = node.left;
tmp.parent = node.parent;
if (node.parent != null) {
if (node.parent.left == node) {
node.parent.left = tmp;
} else {
node.parent.right = tmp;
}
}
node.left = tmp.right;
if(tmp.right != null) {
tmp.right.parent = node;
}
tmp.right = node;
node.parent = tmp;
if (node == this.root) {
this.root = tmp;
}
return tmp;
}
// 查找节点
public Node find(Node node) {
return findParent(node.value, this.root);
}
private Node findParent(int value, Node node) {
// if (value == node.value) {
// return node;
// }
if (value > node.value) {
if (node.right != null) {
return findParent(value, node.right);
} else {
return node;
}
}
if (value < node.value) {
if (node.left != null) {
return findParent(value, node.left);
} else {
return node;
}
}
return node;
}
// 插入节点
public void insert(Node node) {
// 空树
if (this.root == null) {
this.root = node;
node.color = Black;
return;
}
Node temp = find(node);
// 树中已经存在该节点
if (node.value == temp.value) {
return;
}
// 不是空树,且树中不存在该节点
if (node.value < temp.value) {
temp.left = node;
}
if (node.value > temp.value) {
temp.right = node;
}
node.parent = temp;
//修复树结构
fixTree(node);
}
private void fixTree(Node node) {
if (node == this.root) {
node.color = Black;
return;
}
Node parent = node.parent;
Node grandFather = node.parent.parent;
if (grandFather == null) {
return;
}
Node uncle;
if (grandFather.left == parent) {
uncle = grandFather.right;
} else {
uncle = grandFather.left;
}
// 父节点为空
if (parent.color == RED) {
// 叔叔节点为空或颜色为黑色
if (uncle == null || uncle.color == Black) {
// 父亲节点位于祖父的左节点
if (parent == grandFather.left) {
parent.color = Black;
grandFather.color = RED;
// node 是父节点的左节点
if(node == parent.left) {
leftRotate(grandFather);
fixTree(grandFather);
} else {
rightRotate(parent);
leftRotate(grandFather);
fixTree(grandFather);
}
} else {
parent.color = Black;
grandFather.color = RED;
if(node == parent.left) {
rightRotate(parent);
leftRotate(grandFather);
fixTree(grandFather);
} else {
leftRotate(grandFather);
fixTree(grandFather);
}
}
} else {
parent.color = Black;
uncle.color = Black;
grandFather.color = RED;
fixTree(grandFather);
}
}
}
}