从TreeMap看红黑树算法

来源:互联网 发布:淘宝太阳眼镜 编辑:程序博客网 时间:2024/05/09 04:23

TreeSet基于TreeMap,而TreeMap又是基于红黑树的。

从jdk的TreeMap源码片断可以看出,put(K key, V value) 和 fixAfterInsertion(Entry<K,V> x) 实现了Red-Back Tree(红黑树)的插入功能及插入后的树自平衡功能。

===========================================================
红-黑树规则:
1. 每个节点要么是RED节点,要么是BACK节点
2. 根节点总是BACK节点
3. 所有叶节点都是BACK节点(叶子是NIL节点)
4. 如果节点是RED,则其子节点必须是BACK节点,也就是说在一条路径上不能出现相邻的两个RED节点
5. 从根节点到叶节点(空子节点)的每条路径,必须包含相同数目的BACK节点

==>黑色高度为N的红黑树,从根到叶子节点的最短路径长度为N-1,最长路径长度为2*(N-1)
==>对于每个结点来说,从该结点到其子孙叶结点的所有路径上包含相同数目的BACK节点
==>如果一个节点是RED的,那么它周边3个节点都是BACK的

任何一个即将插入的新结点的初始颜色都为红色,因为插入黑点会增加某条路径上黑结点的数目,从而导致整棵树黑高度的不平衡
============================================================


    publicV put(K key, V value) {

        Entry<K,V> t =root;

        if(t == null) {

            compare(key,key); // type (and possibly null)check

 

            root = newEntry<>(key, value, null);

            size = 1;

            modCount++;

            return null;

        }

        intcmp;

        Entry<K,V>parent;

        // split comparator and comparable paths

        Comparator<? superK> cpr = comparator;

        if(cpr != null) {

            do{

                parent = t;

                cmp =cpr.compare(key, t.key);

                if(cmp < 0)

                    t = t.left;

                else if(cmp > 0)

                    t = t.right;

                else

                    returnt.setValue(value);

            } while(t != null);

        }

        else{

            if(key == null)

                throw newNullPointerException();

            Comparable<? superK> k = (Comparable<? super K>) key;

            do{

                parent = t;

                cmp =k.compareTo(t.key);

                if(cmp < 0)

                    t = t.left;

                else if(cmp > 0)

                    t = t.right;

                else

                    returnt.setValue(value);

            } while(t != null);

        }

        Entry<K,V> e =new Entry<>(key, value, parent);

        if(cmp < 0)

            parent.left = e;

        else

            parent.right = e;

       fixAfterInsertion(e);

        size++;

        modCount++;

        return null;

    }

 

    private voidfixAfterInsertion(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;

    }