红黑树5条性质:
1.根节点是黑色
2.节点是红色或者黑色
3.每个叶节点(空节点)是黑色
4.红节点的两个子节点都是黑色
5.从任一节点到其子叶节点经过的黑色节点数目一样多
插入情况:
当前节点N(红) 父节点P 叔叔节点U 祖父节点G
1.N是根节点,将N涂黑
2.P是黑,N为红,直接加入
3.P,U都是红,G必定为黑,将P,U都涂黑,G涂红,N指向G,进行下一次判断
4.父亲P是红色,叔叔U是黑色,祖父G必定为黑色,并且N是P的右孩子,P是G的左孩子的情况。节点P左旋(转换成情况5),N指向P,进行下一次判断
1.根节点是黑色
2.节点是红色或者黑色
3.每个叶节点(空节点)是黑色
4.红节点的两个子节点都是黑色
5.从任一节点到其子叶节点经过的黑色节点数目一样多
插入情况:
当前节点N(红) 父节点P 叔叔节点U 祖父节点G
1.N是根节点,将N涂黑
2.P是黑,N为红,直接加入
3.P,U都是红,G必定为黑,将P,U都涂黑,G涂红,N指向G,进行下一次判断
4.父亲P是红色,叔叔U是黑色,祖父G必定为黑色,并且N是P的右孩子,P是G的左孩子的情况。节点P左旋(转换成情况5),N指向P,进行下一次判断
5.父亲P是红色,叔叔U是黑色,祖父G必定为黑色,并且N是左孩子,P也是左孩子的情况。G执行右旋,G染成红色,P染成黑色
private void fixAfterInsertion(Entry<K,V> x) {
x.color = RED;
while (x != null && x != root && x.parent.color == RED) {
if (parentOf(x) == leftOf(parentOf(parentOf(x)))) { //当前节点的父节点 是左子节点
Entry<K,V> y = rightOf(parentOf(parentOf(x))); //当前节点的叔节点
if (colorOf(y) == RED) {//当前结点的父结点是红色且祖父结点的另一个子结点(叔叔结点)是红色
setColor(parentOf(x), BLACK);//对策:将当前节点的父节点和叔叔节点涂黑,祖父结点涂红,把当前结点指向祖父节点,从新的当前节点重新开始算法。
setColor(y, BLACK);
setColor(parentOf(parentOf(x)), RED);
x = parentOf(parentOf(x));
} else {//当前节点的父节点是红色,叔叔节点是黑色
if (x == rightOf(parentOf(x))) {//当前节点是其父节点的右子
x = parentOf(x);//对策:当前节点的父节点做为新的当前节点,以新当前节点为支点左旋。
rotateLeft(x);
}//当前节点是其父节点的左子
setColor(parentOf(x), BLACK);//对策:父节点变为黑色,祖父节点变为红色,在祖父节点为支点右旋
setColor(parentOf(parentOf(x)), RED);
rotateRight(parentOf(parentOf(x)));
}
} else {//当前节点的父节点 是右子节点
Entry<K,V> y = leftOf(parentOf(parentOf(x)));//当前节点的叔节点
if (colorOf(y) == RED) {
setColor(parentOf(x), BLACK);
setColor(y, BLACK);
setColor(parentOf(parentOf(x)), RED);
x = parentOf(parentOf(x));
} else {
if (x == leftOf(parentOf(x))) {
x = parentOf(x);
rotateRight(x);
}
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
rotateLeft(parentOf(parentOf(x)));
}
}
}
root.color = BLACK;
}
删除
参考treemap的一个自己实现
package a;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class RBTree<E> {
private static final boolean RED = false;
private static final boolean BLACK = true;
static final class Node<E>{
E value;
boolean color;
Node<E> parent;
Node<E> left;
Node<E> right;
public Node(E value, boolean color, Node<E> parent, Node<E> left, Node<E> right) {
super();
this.value = value;
this.color = color;
this.parent = parent;
this.left = left;
this.right = right;
}
@Override
public String toString() {
if(value == null) return "nil";
String s = "Node [value=" + value + ", color=colorRe , parent=parentRe , left=leftRe, right=rightRe ]";
if(color){
s = s.replace("colorRe", "BLACK");
}else{
s = s.replace("colorRe", "RED");
}
if(parent != null){
s = s.replace("parentRe", parent.value.toString());
}else{
s = s.replace("parentRe", "null");
}
if(left.value != null){
s = s.replace("leftRe", left.value.toString());
}else{
s = s.replace("leftRe", "nil");
}
if(right.value != null){
s = s.replace("rightRe", right.value.toString());
}else{
s = s.replace("rightRe", "nil");
}
return s;
}
}
private Node<E> nil = new Node<E>(null, BLACK, null, null, null);
private Node<E> root;
private int size;
public boolean insert(E e){
if(root == null){
root = new Node<E>(e,BLACK,null,null,null);
size++;
return true;
}else{
Node<E> p = root;
Node<E> parent;
int cmp = 0;
do{
parent = p;
cmp = compare(p.value, e);// -1 p < e
if(cmp > 0){
p = p.left;
}else if(cmp < 0){
p = p.right;
}else{
return false;
}
}while(p != null && p.value != null);
Node<E> node = new Node<E>(e,RED,parent,nil,nil);
if(cmp > 0){
parent.left = node;
}else{
parent.right = node;
}
size++;
fixAfterInsertion(node);
return true;
}
}
public Node<E> find(E e){
Node<E> p = root;
int compare = 0;
while(p != null && p != nil){
compare = this.compare(e, p.value);
if(compare == 0){
return p;
}else if(compare > 0){
p = p.right;
}else if(compare < 0){
p = p.left;
}
}
return null;
}
public E delete(E e){
Node<E> find = this.find(e);
if(find == null) return null ;
size--;
E re = find.value;
Node<E> succor = this.succor(find, true);
if(succor == nil){
succor = this.succor(find, false);
}
if(succor == nil){
//删除 root
root = null;
return re;
}
//后继节点value设置到删除节点
find.value = succor.value;
Node<E> parent = succor.parent;
Node<E> succorChild = succor.left != nil ? succor.left : (succor.right != nil ? succor.right : null);
if(succorChild != null){
System.out.println("succorChild:"+succorChild);//必为红色,图黑即可
succorChild.parent = succor.parent;
if(parent.left == succor){
parent.left = succorChild;
}else if(parent.right == succor){
parent.right = succorChild;
}
succorChild.color = BLACK;
succor.parent = succor.left = succor.right = null;
}else{//无子节点
if(succor.color == BLACK){
fixAfterDeletion(succor);
}
if(parent.left == succor){
parent.left = nil;
}else if(parent.right == succor){
parent.right = nil;
}
}
return re;
}
private void fixAfterDeletion(Node<E> x) {
while(x != root && x.color == BLACK){
if(x.parent.left == x){
Node<E> sib = x.parent.right;
//情况1:x的兄弟节点是红色,兄弟节点的子节点都是黑色,父节点是黑色
//不改变红黑树性质,转化为x的兄弟节点是黑色
if(sib.color == RED){
sib.color = BLACK;
x.parent.color = RED;
this.rotateLeft(x.parent);
sib = x.parent.right;
}
//x的兄弟节点是黑色
//情况2:兄弟节点的子节点都是黑色
//x上移寻找 复合情况34的父节点,
//如果此时父节点是红色,那么直接跳出循环涂成黑色即可满足条件
if(sib.left.color == BLACK && sib.right.color == BLACK){
sib.color = RED;
x = x.parent;
}else{
//至少有一个红色子节点
//情况3:左子节点是红色,不改变红黑树性质,转化成情况4
if(sib.left.color == RED){
sib.color = RED;
sib.left.color = BLACK;
this.rotateRight(sib);
sib = x.parent.right;
}
//情况4:右子节点是红色 Db
// Bb B黑 E黑
// x黑 D黑 x黑 Cc
// Cc E红
//这样x这条线上就多出一个黑色
sib.color = x.parent.color;
sib.right.color = BLACK;
x.parent.color = BLACK;
this.rotateLeft(x.parent);
//结束
x = root;
}
}
}
x.color = BLACK;
}
@SuppressWarnings("unchecked")
private int compare(E e1,E e2){
Comparable<E> c1 = (Comparable<E>) e1;
return c1.compareTo(e2);
}
/**
* 左旋
* p
* e3 r
*
* r
* p
* e3
*
*/
private void rotateLeft(Node<E> p){
if (p != null) {
Node<E> r = p.right;
p.right = r.left;
if (r.left != null)
r.left.parent = p;
r.parent = p.parent;
if (p.parent == null)
root = r;
else if (p.parent.left == p)
p.parent.left = r;
else
p.parent.right = r;
r.left = p;
p.parent = r;
}
}
//右旋
private void rotateRight(Node<E> p){
if (p != null) {
Node<E> l = p.left;
p.left = l.right;
if (l.right != null) l.right.parent = p;
l.parent = p.parent;
if (p.parent == null)
root = l;
else if (p.parent.right == p)
p.parent.right = l;
else p.parent.left = l;
l.right = p;
p.parent = l;
}
}
/**
* 插入主要考虑叔节点颜色
* @param x
*/
private void fixAfterInsertion(Node<E> x){
x.color = RED;
while(x != null && x != root && x.parent.color == RED){
Node<E> p = x.parent;//父节点
Node<E> g = p.parent;//祖父节点
if(p == g.left){
Node<E> u = g.right;//叔节点
if(u.color == RED){
p.color = BLACK;
u.color = BLACK;
g.color = RED;
x = g;
}else{
if(x == p.right){
rotateLeft(p);
x = p;
}else{
rotateRight(g);
g.color = RED;
p.color = BLACK;
}
}
}else{
Node<E> u = g.left;//叔节点
if(u.color == RED){
p.color = BLACK;
u.color = BLACK;
g.color = RED;
x = g;
}else{
if(x == p.left){
rotateRight(p);
x = p;
}else{
rotateLeft(g);
g.color = RED;
p.color = BLACK;
}
}
}
}
root.color = BLACK;
}
/**
* true 大于p的最小节点
* false 小于p的最大节点
* @param p
* @param flag
* @return
*/
private Node<E> succor(Node<E> p, boolean flag){
if(flag){
p = p.right;
}else{
p = p.left;
}
Node<E> n = p;
while(p != null && p != nil){
n = p;
if(flag){
p = p.left;
}else{
p = p.right;
}
}
return n;
}
/*-------------测试方法--------------*/
public void print(){
print(root);
}
private void print(Node<E> p){
if(p != null && p.value != null){
doPrint(p);
print(p.left);
print(p.right);
}
}
private void doPrint(Node<E> p){
if(p != null)
System.out.println(p);
}
private void printNode(Node<E> p){
System.out.println(p);
/*if(p.value == null){
System.out.print("nil/");
}else if(p.color == RED){
System.err.print(p.value+"/");
}else if(p.color == BLACK){
System.out.print(p.value+"/");
}*/
}
public void printTree(){
if(size <= 0){
System.out.println("empty tree");
return;
}
List<Node<E>> list = Arrays.asList(root);
int i = 1;
while(list.size() > 0){
System.out.println("----层数:"+i+"---数量:"+list.size());
List<Node<E>> childList = new ArrayList<>();
for (Node<E> node : list) {
printNode(node);
if(node.left != null) childList.add(node.left);
if(node.right != null) childList.add(node.right);
}
System.out.println();
list = childList;
i++;
}
}
public static void main(String[] args) {
RBTree<Integer> t = new RBTree<Integer>();
t.insert(8); // 8
t.insert(10);// 1 10
t.insert(1);// 0 3 11
t.insert(3);// 2 7 22
t.insert(2);// 6 14
t.insert(7);
t.insert(0);
t.insert(11);
t.insert(22);
t.insert(14);
t.insert(6);
t.insert(23);
t.insert(24);
t.insert(25);
t.insert(26);
t.insert(27);
t.insert(28);
t.insert(29);
t.insert(33);
t.insert(36);
t.insert(45);
t.insert(66);
t.insert(77);
t.insert(88);
t.printTree();
System.out.println("===============================");
t.delete(22);
t.printTree();
}
}