一、定义
红黑树要么是颗空树,要么是一颗满足以下三点性质的树:
- 红色链接必为左链接。
- 不存在两条连续的红色链接。
- 黑色完美平衡:从任意空链接到根所经历的黑色链接数一样。
二、插入
只存在以下三种情况:
- 右节点为红色。左旋。
- 右节点为红色,左节点也为红色。颜色反转,左右节点都变黑,当前节点变红。
- 右节点为红色,且右节点的子节点也为红色。右旋,然后就变成了情况2。
左旋完整图(上图的左旋不是一颗红黑树,容易误导)补充:
总结:两个旋转,一个反转。
最后,根节点一定是黑色(进行操作2时,可能会把根节点变红,要调整!)
三、代码
package algorithm.datastructure;
import java.util.Comparator;
/**
* created by 吴家俊 on 2021/3/23.
*/
public class RedBlackTree<K,V> {
private static final boolean RED = true;
private static final boolean BLACK = false;
private Node root;
private Comparator<K> comparator;
public RedBlackTree(Comparator<K> comparator) {
this.comparator = comparator;
}
public void printOrderly(){
printOrderly(root);
}
private void printOrderly(Node node){
if (node == null) return;
printOrderly(node.left);
System.out.println(node.key);
printOrderly(node.right);
}
class Node{
K key;
V value;
Node left,right;
int N; //子树中的节点总数
boolean color;
public Node(K key, V value, int n, boolean color) {
this.key = key;
this.value = value;
N = n;
this.color = color;
}
}
private boolean isRed(Node node){
if (node == null) return false;
return node.color == RedBlackTree.RED;
}
private int size(Node node){//计算当前Node的子节点个数有多少
if (node==null){
return 0;
}
return node.N;
}
private Node rotateLeft(Node node){//将node进行左旋,返回新结点
Node t = node.right;
node.right = t.left;
t.left = node;
node.N = size(node.left)+size(node.right)+1;
t.N = size(node) + size(t.right) + 1;
return t;
}
private Node rotateRight(Node node){
Node t = node.left;
node.left = t.right;
t.right = node;
node.N = size(node.right)+size(node.left)+1;
t.N = size(node) + size(t.left) + 1;
return t;
}
private void flipColor(Node node){
node.left.color = BLACK;
node.right.color = BLACK;
node.color = RED;
}
public void add(K key,V value){
root = add(key,value,root);
root.color = BLACK;
}
private Node add(K key,V value,Node node){
if (node == null){
return new Node(key,value,1,RED);
}
int c = comparator.compare(key,node.key);
if (c < 0) node.left = add(key,value,node.left);
else if (c > 0) node.right = add(key,value,node.right);
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)) flipColor(node);
node.N = size(node.left)+size(node.right)+1;
return node;
}
}