//小人

TreeMap,ThreeSet源码

ThreeSet

  ThreeSet的底层就是ThreeMap

public TreeSet() {
    this(new TreeMap<E,Object>());
}

ThreeMap

1.ThreeMap参数

   //比较器
    private final Comparator<? super K> comparator;

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

    //长度
    private transient int size = 0;

    //对树进行结构修改的次数
    private transient int modCount = 0;

2.Entry参数

K key;//
V value;//
Entry<K,V> left;//左子节点
Entry<K,V> right;//右子节点
Entry<K,V> parent;//父节点
boolean color = BLACK;   //节点颜色     

3.构造

public TreeMap() {
   comparator = null;
}

4.put方法

public V put(K key, V value) {
        //获取根节点
        Entry<K,V> t = root;
       //第一次进入,根节点为null
        if (t == null) {
            //验证key是否为空
            compare(key, key); // type (and possibly null) check
       //根据键值创建根节点
            root = new Entry<>(key, value, null);
        //size加一
            size = 1;
         //操作次数加加
            modCount++;
            return null;
        }
        int cmp;
     //创建父节点
        Entry<K,V> parent;
        //获得比较器 ,比较器在无参初始化的时候就是null,地下也没有给比较器赋值的地方
        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 {//比较器为空进入
            //key为空抛出异常
            if (key == null)
                throw new NullPointerException();

                //这个注解是取消代码中的警告
                @SuppressWarnings("unchecked")
                //获取key
                Comparable<? super K> k = (Comparable<? super K>) key;

            //循环执行找到当前节点的父节点
            do {
                //根节点给父节点
                parent = t;
                //用当前的k和根节点的key进行比较 前面的小返回 负数
                cmp = k.compareTo(t.key);
                //k小于根节点的key 将根节点的左子节点给根节点
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    //k 大于根节点的key 将根节点的右子节点给根节点
                    t = t.right;
                else
                    //相等的话证明是一致的key 直接修改根的值,并跳出循环
                    return t.setValue(value);
            //根不为空就向下进行循环,一直找到最后的节点为止
            } while (t != null);
        }
        //根据key value 和父节点 创建一个节点
        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;
    }

验证key是否为空

 final int compare(Object k1, Object k2) {
        return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
            : comparator.compare((K)k1, (K)k2);
 }

执行旋转

//parentOf(x) 找到当前节点的父节点
//leftOf(x) 找到当前节点的左节点
//rightOf(x)找到当前节点的右节点
//colorOf(x)找到当前节点的颜色
//setColor(x,color) 设置当前节点的颜色
//传入的是当前put的节点
private void fixAfterInsertion(Entry<K,V> x) {
        //将当前节点设置为红色
        x.color = RED;
   
        //判断当前节点不是null 不是根节点 并且父节点的颜色是红色
        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;
    }
parentOf(x) 找到当前节点的父节点
private static <K,V> Entry<K,V> parentOf(Entry<K,V> p) {
        return (p == null ? null: p.parent);
}
leftOf(x) 找到当前节点的左节点
private static <K,V> Entry<K,V> leftOf(Entry<K,V> p) {
        return (p == null) ? null: p.left;
}
rightOf(x)找到当前节点的右节点
 private static <K,V> Entry<K,V> rightOf(Entry<K,V> p) {
        return (p == null) ? null: p.right;
}
colorOf(x)找到当前节点的颜色
private static <K,V> boolean colorOf(Entry<K,V> p) {
        return (p == null ? BLACK : p.color);
}
setColor(x,color) 设置当前节点的颜色
private static <K,V> void setColor(Entry<K,V> p, boolean c) {
        if (p != null)
            p.color = c;
}
rotateLeft 进行左旋
/** From CLR */
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;
        }
}
rotateRight 进行右旋
/** From CLR */
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;
        }
}
posted @ 2022-05-05 18:18  H_Q  阅读(41)  评论(0编辑  收藏  举报