文章目录
- TreeMap的有序指的是什么?怎么实现有序?用的什么数据结构?
- 为什么说红黑树是AVL?
- 红黑树怎么维持平衡?
- 插入和删除哪个简单?
- 还有哪些集合使用红黑树?
TreeMap的有序指的是什么?怎么实现有序?用的什么数据结构?
TreeMap是通过Key 的排序结果来实现有序的。TreeMap是通过Comparable或者Comparator来实现Key 的去重的,而不是通过hashCode和equals方法来比较,此处与HashMap和HashSet不同。因为要实现有序,所以key不能为null,但是value可以为null。
TreeMap的有序通过红黑树来保证。put方法分是否有comparator两种情形考虑。如果有comparator,调用compare函数比较,找到插入位置。如果没有comparator,调用自然排序的compareTo函数比较,找到插入位置。
以上两种情形如果插入位置已有值(即key的比较结果为0),则直接覆盖value。
如果插入位置无值,则按key大小放入插入位置的左结点或右结点,再调用fixAfterInsertion(e)来进行红黑树的着色和旋转,完成后size++,modCount++。
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;
}
为什么说红黑树是AVL?
AVL树(以发明者的名字命名)是自平衡二叉查找树,任何节点的两个子树的高度最大差别为1,因此不会像不平衡的二叉树退化为链表,增加和删除都是通过旋转来达到平衡。AVL树的高度<=log2(n+1).
红黑树并不是严格的AVL树。红黑树保证每个节点到其可达叶子节点的所有路径包含相同数目的黑色节点,根结点和虚结点NIL节点都是黑色,且不能有相邻的两个红色结点。红黑树的新增、删除、查找的最坏时间复杂对为O(logn)。
下面看下红黑树的高度范围。如果都去掉红色节点,则高度<=log2(n+1),由于红色节点不能相邻,恢复红色节点后,高度<=2log2(n+1)。比起AVL来说,高度粗略计算是2倍以内的,也是O(log2n)
红黑树怎么维持平衡?
通过重新着色和左右旋转实现平衡。
插入和删除哪个简单?
插入操作更简单,删除操作考虑的情形更多。
还有哪些集合使用红黑树?
HashMap、TreeSet、ConcurrentHashMap。