为啥哈希表平均具有恒定的访问时间?

Posted

技术标签:

【中文标题】为啥哈希表平均具有恒定的访问时间?【英文标题】:Why does hashtable have constant access time in average?为什么哈希表平均具有恒定的访问时间? 【发布时间】:2011-08-18 03:52:41 【问题描述】:

我不明白这个解释,如果 n 是哈希表中的元素数,m 是桶的总数,那么只有当 n 与 theta(n) 成正比时,哈希表的平均访问时间是恒定的。为什么一定要成比例?

【问题讨论】:

【参考方案1】:

实际上 m 应该与 n 成正比。否则,例如,您可能只有 1 个桶,它就像一个未排序的集合。

更准确地说,如果 m 与 n 成正比,即 m = c * n,那么每个桶中的项目数将为 n/m = 1/c,这是一个常数。转到任何存储桶都是 O(1) 操作(只需计算哈希码),然后通过存储桶的搜索是恒定顺序(您可以对存储桶中的项目进行线性搜索,这将是一个常数)。

因此,如果 m = c * n,则算法的阶数为 O(1)。

举个相反的例子,假设我们有一个大小为 tableSize 的固定大小的表。那么每个桶中的预期项目数是 n/tableSize,它是 n 的线性函数。通过存储桶进行的任何类型的搜索对于一棵树来说充其量都是 O(log(n)) (我假设您没有在存储桶内粘贴另一个哈希表,否则我们对该哈希表有相同的参数),所以在这种情况下不会是 O(1)。

【讨论】:

添加到这个答案中,不仅当两者成比例,而且当元素的数量(n)小于或等于桶的数量(@ 987654322@)。否则我们会遇到O(1 + |k|) 的情况,其中 k 是第 k 个桶中的元素数。 这仍然是恒定的访问时间。如果 k 是常数,则 O(1 + |k|) = O(1)。 如果我们使用开放寻址来解决冲突,而不是像几乎所有哈希表分析所假设的那样链接,会怎样?即使 m 与 n 成正比,平均恒定访问时间是否仍然成立? @DavidTitarenco,如果n <= m,那么n 仍然与m 成正比,如n = cm 其中c <= 1【参考方案2】:

冲突的可能性更高,因此必须扫描具有相同哈希键的项目列表的发生率也更高。

【讨论】:

【参考方案3】:

访问时间是恒定的,因为访问是基于哈希值的计算,然后是不断查找以找到合适的存储桶。假设哈希函数在桶中平均分配项目,那么访问任何单个项目所需的时间将等于访问其他项目的时间,而与 n 无关。

恒定并不一定意味着恒定低。平均访问时间与散列函数的均匀分布和桶数有关。如果您有数千个项目均匀分布在少量存储桶中,那么您会快速找到存储桶,但随后会遍历存储桶中的许多项目。如果您的存储桶与项目的比例很高,但散列函数会在某些存储桶中而不是其他存储桶中放置更多项目,那么较大存储桶中项目的访问时间将比其他存储桶的访问时间慢。

【讨论】:

【参考方案4】:

一个大小合理的哈希表,其中为您存储的每个元素都有足够的插槽和大量额外空间,哈希函数将负责选择插槽的大部分工作,并且在不同元素具有相同哈希的情况下很少发生冲突。一个非常拥挤的哈希表会有很多冲突,并且会降级为基本上线性搜索,其中几乎每个查找都是具有相同哈希的错误项目,您必须继续搜索正确的项目(哈希表一旦它选择了第一个槽,lookup 仍然必须检查密钥,因为它正在寻找的密钥可能在存储时发生了冲突。

决定hit-collision比率的正是项目数与散列大小的比率(即随机选择的插槽被填充的百分比)。

【讨论】:

【参考方案5】:

严格来说,哈希表访问的平均时间复杂度实际上是Ω(n1/3)。信息的传播速度不能超过光速,这是一个常数。由于空间具有三个维度,因此存储n 位数据要求某些数据位于距 CPU 大约 n1/3 的距离处。

更多详情in my blog。

【讨论】:

对于纯粹的组合电路,这可能是一个问题(当我们使用 3-D 全息存储器时,这将是一个更大的问题),但现代计算机是顺序的:存在内部时钟保证所有内存访问都在相同的时间内执行。 @Jeff 是迂腐的,我认为我们只能在延迟(每个访问或时钟周期的周期)必须增加之前添加这么多内存。实际上,我认为我们在寄存器、L1-L3 缓存和主存储器的相对延迟中看到了距离的影响(尽管还有其他限制,如成本和热量)。 对我来说,将内存访问视为常量似乎类似于将字长操作视为常量——这是一种非常合理且有用的简化,但它在技术上忽略了多对数因素。当然,如果我们使用 64 位计算机,我们无论如何都不会看到这些因素,但理论上,如果我们使用针对问题规模优化的硬件,它们就会很重要。 我知道你来自哪里,你是绝对正确的,但我现在看到了问题。渐近算法复杂度分析(big-O/Ω/Θ 表示法)纯粹是理论上的。如果您正在谈论与原子、电子、微秒或空间(或任何形式的物理)相关的任何事物,那么大 O/Ω/Θ 符号在讨论中没有位置。任何理论哈希表查找都是O(1),即使任何实现哈希表查找都可能花费任何时间。算法和算法的实现(以及它们运行的​​架构)位于完全不同的领域。 计算机科学家对“恒定时间”一词的使用是可以理解的深奥。在我们自己中间,我们理解它意味着 O(1)在理论意义上:从上面渐近地由一个常数函数界定。对于外部观察者来说,我们似乎在谈论现实世界的挂钟时间,而实际上我们并非如此。 Big-O/Ω/Θ 表示法是指一种无单位的抽象时间,仅对其他算法有意义。

以上是关于为啥哈希表平均具有恒定的访问时间?的主要内容,如果未能解决你的问题,请参考以下文章

iOS中的哈希表

为啥在搜索键是 O(n) 时,哈希表查找只有 O(1) 时间?

Unordered_Map 查找时间

C#中具有多维键的哈希表

python 字典为啥这么快

高效的“滚动/移动哈希”计算(如移动平均)