TreeMap与红黑树旋转

知识共享许可协议 版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons

TreeMap的插入操作就是按照Key的对比往下遍历,大于比较节点往右走,小于比较节点往左走,先按照二叉查找树的特性进行操作,无须关心节点颜色与树的平衡,后续会重新着色和旋转。

 如果一个新节点插入时能够运行到 fixAfterInsertion()进行着色和旋转。
 说明:

  •  新节点加入之前是非空树

  •  新节点Key与任何节点都不相同 

 fixAfterInsertion()源码:

理解下面源码需要知道几个前提:

  •  节点的父亲红色叔叔红色,则重新着色

  •  节点的父亲红色叔叔是黑色,而新节点是父亲的左节点,进行右旋

  •  节点的父亲红色叔叔是黑色,而新节点是父亲的右节点,进行左旋

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

 关于节点的相关方法:

 public static <K, V> Entry<K, V> parentOf(Entry<K, V> p) {
        return (p == null ? null : p.parent);
    }

    public static <K, V> Entry<K, V> leftOf(Entry<K, V> p) {
        return (p == null ? null : p.left);
    }

    public static <K, V> Entry<K, V> rightOf(Entry<K, V> p) {
        return (p == null ? null : p.right);
    }

    // 返回某个节点的颜色,如果该节点为null,默认该节点是黑色,红黑树特性
    public static <K, V> boolean colorOf(Entry<K, V> p) {
        return p == null ? BLACK : p.color;
    }

    // 如果给定节点不为空,则设置指定节点的颜色
    public static <K, V> void setColor(Entry<K, V> p, boolean c) {
        if (p != null) {
            p.color = c;
        }
    }

 TreeMap的几个属性字段:

   private final Comparator<? super K> comparator; // 决定key顺序的比较器

    private transient Entry<K,V> root;             //   根节点的对象

    /**
     * The number of entries in the tree
     */
    private transient int size = 0;                  

    /**
     * The number of structural modifications to the tree.
     */
    private transient int modCount = 0;           

 描绘红黑树节点的静态类 

 static final class Entry<K,V> implements Map.Entry<K,V> {
        K key;
        V value;
        Entry<K,V> left;
        Entry<K,V> right;
        Entry<K,V> parent;
        boolean color = BLACK;

        /**
         * Make a new cell with given key, value, and parent, and with
         * {@code null} child links, and BLACK color.
         */
        Entry(K key, V value, Entry<K,V> parent) {
            this.key = key;
            this.value = value;
            this.parent = parent;
        }

        /**
         * Returns the key.
         *
         * @return the key
         */
        public K getKey() {
            return key;
        }

        /**
         * Returns the value associated with the key.
         *
         * @return the value associated with the key
         */
        public V getValue() {
            return value;
        }

        /**
         * Replaces the value currently associated with the key with the given
         * value.
         *
         * @return the value associated with the key before this method was
         *         called
         */
        public V setValue(V value) {
            V oldValue = this.value;
            this.value = value;
            return oldValue;
        }

        public boolean equals(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;

            return valEquals(key,e.getKey()) && valEquals(value,e.getValue());
        }

        public int hashCode() {
            int keyHash = (key==null ? 0 : key.hashCode());
            int valueHash = (value==null ? 0 : value.hashCode());
            return keyHash ^ valueHash;
        }

        public String toString() {
            return key + "=" + value;
        }
    }

猜你喜欢

转载自blog.csdn.net/qq_34579060/article/details/93968891