为什么hashMap使用红黑树而不是其他结构?
在回答这个问题之前,先了解一下有关二叉树的基本内容。
①二叉排序树(BST)
(1)若左子树不为空,则左子树上所有结点的值均小于根结点的值。
(2)若右子树不为空,则右子树上所有结点的值均大于根节点的值。
(3)左右子树也为二叉排序树。
②平衡二叉树(AVL树)
是一种二叉查找树,当且仅当两个子树的高度差不超过1时,这个树是平衡二叉树。
③红黑树:
是许多二叉查找树中的一种,它能保证在最坏的情况下,基本动态集合操作时间为O(log n).
(1)根节点始终是黑色的。
(2)所有叶子都是黑色。
(3)每个红色结点的两个子结点都是黑色。
(3)从任一结点到其每个叶子的所有路径都包含相同数目的黑色结点。
问题1:为什么不使用二叉排序树?
问题主要出现在二叉排序树在添加元素的时候极端情况下会出现线性结构。
问题2:为什么不使用平衡二叉树呢?
红黑树和平衡二叉树的区别在于它们的平衡强弱不同:
-
平衡二叉树追求的是一种完全平衡的状态,它的定义是任何结点的左右子树的高度差不会超过 1,这样的优势是树的结点是很平均分配的;
-
红黑树不追求这种完全平衡,而是追求一种弱平衡的状态,就是让整个树最长路径不会超过最短路径的 2 倍。这样的话,红黑树虽然牺牲了一部分查找的性能效率,但是能够换取一部分维持树平衡状态的成本。
-
红黑是用非严格的平衡来换取增删节点时候旋转次数的降低,任何不平衡都会在三次旋转之内解决,而AVL是严格平衡树,因此在增加或者删除节点的时候,根据不同情况,旋转的次数比红黑树要多。
删除节点导致失衡:
-
AVL需要维护从被删除节点到根节点root这条路径上所有节点的平衡,旋转的量级为O(logN)
-
而RB-Tree最多只需要旋转3次实现复衡,只需O(1),所以说RB-Tree删除节点的rebalance的效率更高,开销更小!
-
当然,由于AVL高度平衡,因此AVL的Search效率更高啦。
针对插入和删除节点导致失衡后的rebalance操作,红黑树能够提供一个比较"便宜"的解决方案,降低开销,是对search,insert ,以及delete效率的折衷,总体来说,RB-Tree的统计性能高于AVL。故引入RB-Tree是功能、性能、空间开销的折中结果。
而我们知道 HashMap 的设计定位应该是一个相对通用的散列表,那么它的设计者会希望这样一个数据结构应该具备更强大的稳定性,因此它才选择了红黑树。