数据结构Map之TreeMap分析

来源:互联网 发布:正则表达式语法php 编辑:程序博客网 时间:2024/06/05 05:03

今天又看了一遍TreeMap的源码,发现其中很有意思,并调试看看它内部是怎么进行添加元素,又是怎么进行比较插入的元素,又是怎么定位新插入的元素(到底放到左子树还是右子树)

列子如下:

TestMap.java

public class TestMap {    public static void main(String[] args){        HashMap<Character,Integer> hashMap = new HashMap<>();        testHashMap(hashMap);        LinkedHashMap<Character,Integer> linkedHashMap = new LinkedHashMap<>();        testLinkedHashMap(linkedHashMap);        TreeMap<Character,Integer> treeMap = new TreeMap<>();        testTreeMap(treeMap);    }    public static void testHashMap(HashMap<Character,Integer> hashMap){        hashMap.put('c',3);        hashMap.put('d',2);        hashMap.put('a',1);    }    public static void testLinkedHashMap(LinkedHashMap<Character,Integer> linkedHashMap){        linkedHashMap.put('e',4);        linkedHashMap.put('f',5);        linkedHashMap.put('h',10);    }    public static void testTreeMap(TreeMap<Character,Integer> treeMap){        treeMap.put('x',20);        treeMap.put('v',10);        treeMap.put('y',30);        treeMap.put('a',1);        treeMap.put('z',50);    }}
我在红颜色字的地方设断点进行调试

我设计的数据结构如图:(画的有点丑见谅)


先看看TreeMap中的put方法:

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();            @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);        }        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;    }
开始单步调试:

1:第一次插入x-->20

首先将第一个插入的值当作root节点此时他的parent,left,right都为null;然后判断root是否为空如果为空的话新建一个Entry将x和20放进去,然后将它的parent置为null,放回null

2:第二次插入v-->10

第二次插入的元素t不为空他的指向是x-->20空间,然后拿当前的key=v与t.key进行比较,看一看谁大,很显然,cmp<0,t = t.left,此时t.left = null; 说明root节点没有左子树,这个元素可以直接插入到左子树中了,即parent.left = e;

3:第三次插入y -->30

同理,同第二次插入的一样,root节点没有右子树那么可以放心的插入到root的右子树中去了,即parent.right = e;

4:第四次插入a-->1

第四次插入的时候比较a 和 x的大小

发现cmp < 0,好了,发现t.left != null,继续循环直到子节点的子节点为null,发现root的左子树只有一个节点,那么parent指向了v-->10,因为t.left = null 所以可以放心的插入其左子树了

5:第五次插入z-->50

 同理可以得到,z被插入到了y的右子树了



原创粉丝点击