TreeMap 红黑树实现

TreeMap 是一个有序的key-value集合,它是通过 红黑树 实现的。

TreeMap 继承于AbstractMap,所以它是一个Map,即一个key-value集合。

TreeMap 实现了NavigableMap,Cloneable和Serializable接口。

TreeMap 红黑树实现

TreeMap的基本操作 containsKey、get、put 和 remove 的时间复杂度是 log(n) 。

 

首先是TreeMap的构造方法:

  public TreeMap() {

        comparator = null;

    }
/** * Constructs a new, empty tree map, ordered according to the given comparator. */ public TreeMap(Comparator<? super K> comparator) { this.comparator = comparator; } /** * Constructs a new tree map containing the same mappings as the given * map, ordered according to the <em>natural ordering</em> of its keys. */ public TreeMap(Map<? extends K, ? extends V> m) { comparator = null; putAll(m); } /** * Constructs a new tree map containing the same mappings and * using the same ordering as the specified sorted map. This * method runs in linear time. */ public TreeMap(SortedMap<K, ? extends V> m) { comparator = m.comparator(); try { buildFromSorted(m.size(), m.entrySet().iterator(), null, null); } catch (java.io.IOException cannotHappen) { } catch (ClassNotFoundException cannotHappen) { } }

 

TreeMap是基于红黑树实现的,以下是树结点的定义,主要key(键)、value(值)、left(左孩子)、right(右孩子)、parent(父节点)、color(颜色)六个字段,根据key的值进行排序。该内部类比较简单,不做分析。

    static final class Entry<K,V> implements Map.Entry<K,V> {

        K key;

        V value;

        Entry<K,V> left = null;

        Entry<K,V> right = null;

        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;

        }



        ......

  }

以下是红黑树的插入put和删除deleteEntry操作,以及执行插入删除时需要用到的操作:左旋rotateLeft、右旋rotateRight、插入修正fixAfterInsertion和删除修正fixAfterDeletion。

插入操作,先找到要插入的位置,插入新结点,调用fixAfterInsertion对插入结果进行修正:

    public V put(K key, V value) {

        Entry<K,V> t = root;

        if (t == null) {

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



            root = new Entry<>(key, value, null);

            size = 1;

            modCount++;

            return null;

        }

        int cmp;

        Entry<K,V> parent;

        // split comparator and comparable paths

        Comparator<? super K> 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

                    return t.setValue(value);

            } while (t != null);

        }

        else {

            if (key == null)

                throw new NullPointerException();

            Comparable<? super K> 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

                    return t.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;

    }

 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;

    }

之中用到了leftRotate和rightRotate操作,这里先介绍这两个操作,在fixAfterDeletion中也会用到:

    private void rotateLeft(Entry<K,V> p) {

        if (p != null) {

            Entry<K,V> 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(Entry<K,V> p) {

        if (p != null) {

            Entry<K,V> 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;

        }

    }

删除操作,先按二叉查找树的方法删除节点,然后调用fixAfterDeletion使得树保持红黑树性质:

    private void deleteEntry(Entry<K, V> p) {

        modCount++;

        size--;

        if (p.left != null && p.right != null) {

            Entry<K, V> s = successor(p);

            p.key = s.key;

            p.value = s.value;

            p = s;

        }



        Entry<K,V> replacement = p.left != null ? p.left : p.right;

        if (replacement != null) {

            replacement.parent = p.parent;

            if (p.parent == null)

                root = replacement;

            else if (p == p.parent.left)

                p.parent.left = replacement;

            else

                p.parent.right = replacement;

            p.left = p.right = p.parent = null;

            if (p.COLOR == BLACK)

                fixAfterDeletion(replacement);

        } else if (p.parent == NULL) {

            root = null;

        } else {

            if (p.color == BLACK)

                fixAfterDeletion(p);

            if (p.parent != null) {

                if (p ==p.parent.left)

                    p.parent.left = null;

                else

                    p.parent.right = null;

                p.parent = null;

            }

        }

    }

 

你可能感兴趣的:(TreeMap)