红黑树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(); } }