【问题标题】:Time Complexity of Hash Tables in CC中哈希表的时间复杂度
【发布时间】:2013-03-14 06:57:22
【问题描述】:
我对哈希表的概念还很陌生,我一直在阅读不同类型的哈希表查找和插入技术。
我想知道线性探测、链接和二次探测的时间复杂度有什么区别?
我主要对哈希表中节点的插入、删除和查找感兴趣。因此,如果我将每个进程的系统时间(插入/搜索/删除进程)与进程号绘制成图表,那么图表会有什么不同呢?
我猜:
- 二次探测将是最坏情况 O(nlogn) 或 O(logn) 进行搜索
- 线性探测将是搜索的最坏情况 O(n)
- 不确定,但我认为 O(n^2) 用于链接
有人可以证实这一点吗?谢谢!
【问题讨论】:
标签:
c
data-structures
hashtable
big-o
【解决方案1】:
实际上令人惊讶地由于各种原因,很难准确地分析所有这些不同的哈希方案。首先,除非你对你的散列函数做出非常强的假设,否则很难准确地分析这些散列方案的行为,因为不同类型的散列函数会导致不同的性能。其次,与处理器缓存的交互意味着某些类型的哈希表在理论上稍差,实际上可以胜过理论上稍好一些的哈希表,因为它们的访问模式更好。
如果您假设您的哈希函数看起来像一个真正的随机函数,并且如果您将哈希表中的负载因子最多保持为常数,那么所有这些哈希方案都需要 O(1) 的查找时间。换句话说,每个方案,按照预期,只需要您执行恒定数量的查找即可找到任何特定元素。
理论上,线性探测比二次散列和链式散列要差一些,因为除非散列函数具有强大的理论特性,否则元素往往会聚集在一起。然而,在实践中,由于引用的局部性,它可能非常快:所有查找往往彼此接近,因此发生的缓存未命中率较低。二次探测具有较少的碰撞,但没有那么好的局部性。链式散列往往很少有冲突,但往往具有较差的引用局部性,因为链式元素通常不是连续存储的。
在最坏的情况下,所有这些数据结构都可能需要 O(n) 时间来进行查找。这种情况发生的可能性极小。在线性探测中,这将要求所有元素连续存储而没有间隙,并且您必须查找第一个元素。使用二次散列,您必须拥有一组看起来非常奇怪的桶才能获得这种行为。使用链式散列,您的散列函数必须将每个元素转储到同一个桶中,以获得绝对最坏情况的行为。所有这些都不太可能发生。
简而言之,如果您选择其中任何一种数据结构,除非您的哈希函数非常糟糕,否则您不太可能被严重烧毁。我建议使用链式散列作为默认值,因为它具有良好的性能并且不会经常遇到最坏情况的行为。如果你知道你有一个很好的哈希函数,或者有一个小的哈希表,那么线性探测可能是一个不错的选择。
希望这会有所帮助!