Algorithm 哈希表真的是O(1)吗?
散列表可以实现O(1),这似乎是常识,但这对我来说从来没有意义。有人能解释一下吗?以下是我想到的两种情况: A.该值是一个小于哈希表大小的整数。因此,该值是它自己的哈希,因此没有哈希表。但如果有,它将是O(1),并且仍然是低效的 B.您必须计算该值的散列。在这种情况下,所查找数据的大小顺序为O(n)。在你做了O(n)个工作之后,查找可能是O(1),但在我看来仍然是O(n) 除非您有一个完美的散列或一个大的散列表,否则每个bucket可能有几个项。所以,无论如何,它在某一点上退化为一个小的线性搜索 我认为哈希表非常棒,但是我没有得到O(1)的名称,除非它只是理论上的 Wikipedia一贯引用恒定的查找时间,完全忽略了哈希函数的开销。这真的是一个公平的衡量标准吗Algorithm 哈希表真的是O(1)吗?,algorithm,performance,language-agnostic,big-o,hashtable,Algorithm,Performance,Language Agnostic,Big O,Hashtable,散列表可以实现O(1),这似乎是常识,但这对我来说从来没有意义。有人能解释一下吗?以下是我想到的两种情况: A.该值是一个小于哈希表大小的整数。因此,该值是它自己的哈希,因此没有哈希表。但如果有,它将是O(1),并且仍然是低效的 B.您必须计算该值的散列。在这种情况下,所查找数据的大小顺序为O(n)。在你做了O(n)个工作之后,查找可能是O(1),但在我看来仍然是O(n) 除非您有一个完美的散列或一个大的散列表,否则每个bucket可能有几个项。所以,无论如何,它在某一点上退化为一个小的线性搜索
编辑:总结我学到的知识:
- 这在技术上是正确的,因为哈希函数不需要使用密钥中的所有信息,因此可以是常数时间,并且因为足够大的表可以将冲突降低到接近常数时间
- 这在实践中是正确的,因为随着时间的推移,只要选择哈希函数和表大小以最小化冲突,它就会起作用,即使这通常意味着不使用固定时间的哈希函数
计算散列不一定是一个特别昂贵的操作-我们这里不讨论加密散列函数。但这是顺便提一下。散列函数计算本身不依赖于元素数n;虽然它可能取决于元素中数据的大小,但这不是n所指的。因此散列的计算不依赖于n,也是O(1)。这里有两个变量,m和n,其中m是输入的长度,n是散列中的项数 O(1)查找性能声明至少做出两个假设:
- 您的对象可以在O(1)时间内进行相等比较
- 将有一些散列冲突
n
元素,则必须计算n
散列,这需要线性时间。。。要查找元素,您需要计算所查找内容的单个散列,然后使用该散列找到相应的bucket。您不需要重新计算哈希表中已经存在的所有内容的哈希
除非你有一个完美的散列或者一个大的散列表,否则每个bucket可能有几个条目,所以不管怎样,它在某个时候都会转化为一个小的线性搜索
不一定。bucket不一定必须是列表或数组,它们可以是任何容器类型,例如平衡的BST。这意味着O(logn)
最坏的情况。但这就是为什么选择一个好的散列函数来避免在一个bucket中放入太多元素是很重要的。正如肯尼特指出的那样,平均而言,你仍然会得到O(1)
时间,即使偶尔你不得不挖桶
当然,哈希表的权衡是空间复杂性。你在用空间换取时间,这似乎是计算科学中的常见情况
您提到在其他注释中使用字符串作为键。您关心计算字符串哈希所需的时间,因为它由几个字符组成?正如其他人再次指出的那样,您不一定需要查看所有字符来计算散列,尽管如果这样做,可能会产生更好的散列。在这种情况下,如果您的密钥中平均有
m
个字符,并且您使用了所有这些字符来计算哈希,那么我认为您是对的,查找将花费O(m)
。如果m>>n
则您可能有问题。如果是那样的话,你最好有个BST。或者选择一个更便宜的散列函数。只有在表中只有恒定数量的键并且做出一些其他假设的情况下,散列才是O(1)。但在这种情况下,它有优势
如果密钥具有n位表示,则哈希函数可以使用1、2、。。。这些比特中的n个。考虑使用1位的哈希函数。评估肯定是O(1)。但您只是将密钥空间划分为2。因此,您要将多达2^(n-1)个键映射到同一个bin中。使用BST搜索,如果某个密钥几乎已满,则最多需要n-1个步骤来定位该密钥
你可以把它拔出来
function get(a: Table with m buckets, k: Key being looked up)
bucket <- compute hash(k) modulo m
for each (key,value) in a[bucket]
return value if k == key
return not_found
function get(a: Table with m buckets and seed r, k: Key being looked up)
rHash <- H[r]
bucket <- compute rHash(k) modulo m
for each (key,value) in a[bucket]
return value if k == key
return not_found