红黑树笔记

红黑树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,进行下一次判断

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

}


猜你喜欢

转载自blog.csdn.net/u013038630/article/details/77069800