在处理散列冲突时,为什么在 BST 上使用链表?

In handling hash collisions, why use a linked list over a BST?

链表的搜索时间复杂度为 O(n),而 BST 的搜索时间为 O(log n)。那么为什么要用链表来处理碰撞呢?我能想到的唯一原因是因为插入链表是 O(1) 而插入 BST 是 O(log n)。

散列 table 的理由是散列到同一个散列槽的项目应该很少。对于这些小数字,链表实际上应该比 BST(更好的常数因子)更快,并且在任何情况下都更简单,编码更可靠。 BST 的最坏情况在任何情况下都与链表相同,除非您想真正超越顶部并使用平衡树。

如果散列函数很好并且散列 table 负载因子不是太高,那么任何一个桶中都不应该有很多冲突。链表是一种非常简单的数据结构,足够好,冲突次数很少。它速度快,占用的空间小 space。请记住,大多数存储桶中的值要么为 0,要么为 1。

此外,BST 将强制要求商品是可订购的。哈希 table 的一个很好的 属性 是键不需要可比较。

我想主要原因是易于实施。至少一个广泛使用的散列实现 table 最近已经从使用链表转向使用链表和平衡树的混合体:JEP 180: Handle Frequent HashMap Collisions with Balanced Trees in Java 8:

The principal idea is that once the number of items in a hash bucket grows beyond a certain threshold, that bucket will switch from using a linked list of entries to a balanced tree. In the case of high hash collisions, this will improve worst-case performance from O(n) to O(log n).

值得注意的是,在列表上使用树要求元素可以排序。普通散列 table(有或没有链表)没有这个要求:它所需要的只是元素是可散列的并且可以与 equality.

进行比较