TreeMap数据结构(jdk8)

TreeMap使用了红黑树的结构,看下源码,记录用。

    public V put(K key, V value) {
        Entry<K,V> t = root;
        //初始化
        if (t == null) {
            //key为null会报错,因此是保证key非null
            compare(key, key); // 
            //K-V 放到root
            root = new Entry<>(key, value, null);
            //实体的数量
            size = 1;
            //操作数
            modCount++;
            return null;
        }
        //比较结果
        int cmp;
        // 父节点
        Entry<K,V> parent;
        Comparator<? super K> cpr = comparator;
        //从root开始,用key和节点的key进行比较,小的找左树,大的找右树,相同就赋值然后返回。当t==null时,parent就是该节点父节点
        //使用自定义比较器
        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);
        }
        //使用key的默认比较器
        else {
            if (key == null)
                throw new NullPointerException();
            @SuppressWarnings("unchecked")
                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);
        }
        //新节点e
        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 void fixAfterInsertion(Entry<K,V> x) {
        //根据RBTREE要求,新插入节点为红色
        x.color = RED;
        //该节点不为null,不是root,且父节点为RED时开始修复平衡
        while (x != null && x != root && x.parent.color == RED) {
            //x的爸爸是 爷爷的左儿子
            if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
                // y是爷爷的右儿子
                Entry<K,V> y = rightOf(parentOf(parentOf(x)));
                //如果y是红色的
                if (colorOf(y) == RED) {
                    //把爷爷的左儿子置为黑色
                    setColor(parentOf(x), BLACK);
                    //把爷爷的右儿子置为黑色
                    setColor(y, BLACK);
                    //把爷爷置为黑色
                    setColor(parentOf(parentOf(x)), RED);
                    //把x变为爷爷
                    x = parentOf(parentOf(x));
                //y是黑色的
                } else {
                    //如果x是爸爸的右儿子
                    if (x == rightOf(parentOf(x))) {
                        //x设为爸爸
                        x = parentOf(x);
                        //左旋X
                        rotateLeft(x);
                    }
                    //把x的父亲设为黑色
                    setColor(parentOf(x), BLACK);
                    //把x的爷爷设为红色
                    setColor(parentOf(parentOf(x)), RED);
                    //右旋x的爷爷
                    rotateRight(parentOf(parentOf(x)));
                }
            //爸爸是爷爷的右儿子
            } else {
                //y是爷爷的左儿子
                Entry<K,V> y = leftOf(parentOf(parentOf(x)));
                //y是红色
                if (colorOf(y) == RED) {
                    //x的父亲设为黑色
                    setColor(parentOf(x), BLACK);
                    //y设为黑色
                    setColor(y, BLACK);
                    //爷爷设为红色
                    setColor(parentOf(parentOf(x)), RED);
                    //x变为爷爷
                    x = parentOf(parentOf(x));
                //y是黑色
                } else {
                    //如果x是父亲的左儿子
                    if (x == leftOf(parentOf(x))) {
                        //x变为父亲
                        x = parentOf(x);
                        //右旋x
                        rotateRight(x);
                    }
                    //设置x父亲颜色为黑色
                    setColor(parentOf(x), BLACK);
                    //爷爷为红色
                    setColor(parentOf(parentOf(x)), RED);
                    //左旋爷爷
                    rotateLeft(parentOf(parentOf(x)));
                }
            }
        }
        //根永远是黑色
        root.color = BLACK;
    }


posted @ 2019-10-24 10:27  六月过半  阅读(373)  评论(0编辑  收藏  举报