package chapter4;
public class BRT<key extends Comparable<key>, value> {
private final static Boolean BLACK = false;
private final static Boolean RED = true;
private Node root;
private class Node{
private Node left, right;
private Boolean color;
private int N;
private key key;
private value value;
public Node(key key, value value, Node left, Node right, Boolean color, int n){
this.color = color;
this.left = left;
this.right = right;
this.N = n;
this.key = key;
this.value = value;
}
}
public int size(Node h){
if(h == null)
return 0;
return h.N;
}
//left rotate
private Node rotateLeft(Node h){
Node temp = h.right;
h.right = temp.left;
temp.left = h;
//exchange color
temp.color = h.color;
h.color = RED;
h.N = size(h.left) + size(h.right) + 1;
return temp;
}
//right rotate
private Node rotateRight(Node h){
Node temp = h.left;
h.left = temp.right;
temp.right = h;
//exchange color
temp.color = h.color;
h.color = RED;
h.N = size(h.left) + size(h.right) + 1;
return temp;
}
//change color when two node are red
private void flipColor(Node node){
node.left.color = BLACK;
node.right.color = BLACK;
node.color = RED;
}
//change color when two node are red
private void flipColor2(Node node){
node.left.color = !node.left.color;
node.right.color = !node.right.color;
node.color = !node.color;
}
//get, like the binary search tree
public Node get(key key){
return get(key, this.root);
}
//jude color
private boolean isRed(Node node){
if(node == null)
return false;
return node.color;
}
private Node get(key key, Node node){
if(node == null)
return null;
int com = node.key.compareTo(key);
if (com == 0)
return node;
else if (com < 0)
return get(key, node.left);
else
return get(key, node.right);
}
//put
public void put(key key, value value){
put(key, value, this.root);
}
private Node put(key key, value value, Node node){
if(node == null){
Node newNode = new Node(key, value, null, null, RED, 1);
return newNode;
}
int com = node.key.compareTo(key);
if (com == 0){
node.value = value;
}
else if (com < 0)
node.left = put(key, value, node.left);
else
node.right = put(key, value, node.right);
//balance to 2-3 node
if(!isRed(node.left) && isRed(node.right))
node = rotateLeft(node);
if( isRed(node) && isRed(node.left))
node = rotateRight(node);
//both two red node
if(isRed(node.right) && isRed(node.left))
flipColor(node);
node.N = size(node.left) + size(node.right) +1;
return node;
}
public void deleteMin(){
if(!isRed(this.root))
this.root.color = !this.root.color;
this.root = deleteMin(this.root);
if(isRed(this.root))
this.root.color = BLACK;
}
private Node deleteMin(Node node){
if(node.left == null)
return null;
if(!isRed(node.left)&&!isRed(node.left.left)){
node = moveLeft(node);
}
node.left = deleteMin(node.left);
//balance to 2-3 node
if(!isRed(node.left) && isRed(node.right))
node = rotateLeft(node);
if( isRed(node) && isRed(node.left))
node = rotateRight(node);
//both two red node
if(isRed(node.right) && isRed(node.left))
flipColor(node);
node.N = size(node.left) + size(node.right) +1;
return node;
}
private Node moveLeft(Node node){
flipColor2(node);
if(isRed(node.right.left)){
node.right = rotateRight(node.right);
node = rotateLeft(node);
}
return node;
}
private Node moveRight(Node node){
flipColor2(node);
if(isRed(node.right.left)){
node = rotateLeft(node);
}
return node;
}
//delete
public void delete(key key){
this.root = delete(key, this.root);
}
private Node min(Node node){
if (node.left == null){
return node;
}
return min(node.left);
}
private Node delete(key key, Node node){
if(key.compareTo(node.key) < 0){
//keep delete node is 3-node or 4-node in left tree
if(!isRed(node.left) && !isRed(node.left.left)){
node = moveLeft(node);
}
node.left = delete(key, node.left);
}else{
if(isRed(node.left)){
rotateRight(node);
}
if(key.compareTo(node.key) == 0 && node.right == null){
return null;
}
if(key.compareTo(node.key) == 0){
Node minNode = min(node.right);
node.key = minNode.key;
node.value = minNode.value;
node.right = deleteMin(node.right);
}else {
//keep delete node is 3-node or 4-node in right tree
if(!isRed(node.right) && !isRed(node.right.left)){
node = moveRight(node);
}
node.right = delete(key, node.right);
}
}
//balance to 2-3 node
if(!isRed(node.left) && isRed(node.right))
node = rotateLeft(node);
if( isRed(node) && isRed(node.left))
node = rotateRight(node);
//both two red node
if(isRed(node.right) && isRed(node.left))
flipColor(node);
node.N = size(node.left) + size(node.right) +1;
return node;
}
}
红黑树利用颜色增加了3-节点的用法,使得每个路径的到叶节点(包括黑色节点)的距离都相同,大大减少了树的深度,加快了数据的插入和查找。
理解红黑树的算法是再二分查找树的基础上增加了颜色的属性、旋转操作和平衡操作。
其中平衡的原理就是根据不同情况的节点的颜色情况,向上递归时,对2-3节点进行平衡操作
删除操作时最难的,先要掌握删除最小值和最小值操作(最小值和最大值删除时需要再一个3或者4节点上,递归时一直要保持),然后再删除最小值(左树返回空时),最后复原。
掌握了删除最小值和最大值后再去理解删除操作,会更简单一些。