为什么我会在哈希表上看到这些函数的不同运行时复杂性?
在wiki上,搜索和删除是O(n)(我认为哈希表的要点是持续查找,所以如果搜索是O(n)则重点是什么)。
在不久前的一些课程笔记中,我看到了一系列复杂性,具体取决于某些细节,包括所有O(1)。如果我能得到所有O(1),为什么要使用任何其他实现?
如果我在C ++或Java等语言中使用标准哈希表,那么我可以期待时间复杂度是多少?
答案 0 :(得分:84)
Hash tables O(1)
平均值和amortized 案例复杂性,但它会遇到O(n)
最坏情况时间复杂。 [我认为这是你的困惑]
由于两个原因,哈希表遭遇O(n)
最差时间复杂度:
O(n)
时间。然而,据说是O(1)
平均和摊销的案例,因为:
O(n)
,最多只能在n/2
操作后发生,这些操作都假定为O(1)
:因此,当您将每个操作的平均时间相加时,您会得到: (n*O(1) + O(n)) / n) = O(1)
请注意,由于重新发布问题 - 需要低latency的实时应用程序和应用程序 - 不应使用哈希表作为其数据结构。
编辑:哈希表的另一个问题:cache
您可能会在大型哈希表中看到性能损失的另一个问题是缓存性能。 哈希表遭遇缓存性能不佳,因此对于大型收集 - 访问时间可能需要更长时间,因为您需要将表的相关部分从内存重新加载回缓存。
答案 1 :(得分:14)
理想情况下,哈希表为O(1)
。问题是如果两个键不相等,但它们会产生相同的哈希值。
例如,想象一下字符串“这是最好的时候它是最糟糕的时候”和“Green Eggs and Ham”都导致哈希值123
。
当插入第一个字符串时,它被放入桶123.当插入第二个字符串时,它会看到存储桶123
已经存在一个值。然后,它会将新值与现有值进行比较,并看出它们不相等。在这种情况下,将为该键创建一个数组或链表。此时,检索此值将变为O(n)
,因为哈希表需要遍历该存储桶中的每个值以找到所需的值。
因此,在使用哈希表时,使用具有非常好的哈希函数的密钥非常重要,该哈希函数既快又不会导致不同对象的重复值。
有意义吗?
答案 2 :(得分:6)
一些哈希表(cuckoo hashing)保证了O(1)查找
答案 3 :(得分:4)
也许你在看空间的复杂性?那是O(n)。其他复杂性与hash table条目中的预期一致。随着桶数的增加,搜索复杂度接近O(1)。如果在最坏的情况下,哈希表中只有一个桶,则搜索复杂度为O(n)。
编辑以回应评论我认为O(1)是普通情况并不正确。它确实是(如维基百科页面所说)O(1 + n / k)其中K是哈希表大小。如果K足够大,那么结果实际上是O(1)。但假设K为10且N为100.在这种情况下,每个桶平均有10个条目,因此搜索时间绝对不是O(1);它是一个线性搜索,最多10个条目。
答案 4 :(得分:2)
取决于你如何实现散列,在最坏的情况下它可以转到O(n),在最好的情况下它是0(1)(通常你可以实现,如果你的DS不那么容易)