当我们有一个带链接的哈希表时:
我只是想知道维护每个键的列表是否会影响在哈希表中搜索,插入和删除的运行时间?
答案 0 :(得分:2)
理论上:是的,因为在一般情况下,您只需走一半的链条就能找到一个项目是否在链条上。
在实践中,可能没有太大区别,因为链通常非常短,并且代码复杂性增加也会花费一些周期,主要是在“插入”情况下。
BTW:在大多数情况下,时隙数量远小于哈希值的“键空间”。如果您能够负担得起空间,将哈希值存储在链节点中将节省重新计算每一跳的哈希值,并且将避免大多数最终比较。这当然是空间< - >时间权衡。如:struct hashnode **this;
for (this=& table[slot] ; *this; this = &(*this)->link) {
if ((*this)->hash != the_hash) continue;
if (compare ((*this)->payload , the_value)) continue;
break;
}
/* at this point "this" points to the pointer that points to the wanted element,
or to the NULL-pointer where it should be inserted.
For the sorted-list example, you should instead break out of the loop
if the compare function returns > 0, and handle that special case here.
*/
答案 1 :(得分:1)
假设您已经选择了哈希算法和地图大小来减轻首先会遇到的冲突数量。此时,您应该在任何位置都有一个非常小的列表(理想情况下是一个或两个元素),因此在链中维护排序结构的额外工作肯定不仅仅是迭代该存储桶中的少量项目。
答案 2 :(得分:0)
是的,当然。通常引用的散列表的O(1)假设是完美的散列 - 其中没有两个不相同的项解析为相同的散列。
在实践中,情况并非如此。你将永远拥有(足够大的数据集)冲突。无论你是使用链接还是其他一些碰撞解决技术,碰撞都意味着在查询时会有更多的工作。
这就是为什么选择一个设计良好/编写好的哈希函数非常非常重要的原因,以及与您将用作哈希表的键的数据的良好匹配。在实践中,不同类型的数据将使用不同的散列函数更好地散列。