为什么我在哈希表上仍然看到这些函数的不同运行时复杂性?
在Wiki上,搜索和删除均为O(n)(我认为哈希表的要点是具有恒定的查找,因此,如果搜索为O(n)的意义是什么)。
在不久前的一些课程笔记中,我看到了许多复杂的情况,具体取决于某些细节,包括一个包含所有O(1)的细节。如果我可以全部获得O(1),为什么还要使用其他实现?
如果我以C ++或Java之类的语言使用标准哈希表,那么我期望的时间复杂度是多少?
为什么我在哈希表上仍然看到这些函数的不同运行时复杂性?
在Wiki上,搜索和删除均为O(n)(我认为哈希表的要点是具有恒定的查找,因此,如果搜索为O(n)的意义是什么)。
在不久前的一些课程笔记中,我看到了许多复杂的情况,具体取决于某些细节,包括一个包含所有O(1)的细节。如果我可以全部获得O(1),为什么还要使用其他实现?
如果我以C ++或Java之类的语言使用标准哈希表,那么我期望的时间复杂度是多少?
Answers:
哈希表是O(1)
平均和摊销的情况下的复杂性,但是它遭受O(n)
最坏情况下的时间复杂性的困扰。[我认为这就是您的困惑所在]
O(n)
由于两个原因,哈希表的时间复杂度最差:
O(n)
时间。但是,这被认为是O(1)
平均和摊销的情况,因为:
O(n)
()最多可以在n/2
ops之后进行,而ops都是假设的O(1)
:因此,当您将每个op的平均时间相加时,将得到:(n*O(1) + O(n)) / n) = O(1)
请注意,由于存在重新哈希问题-实时应用程序和需要低延迟的应用程序-不应将哈希表用作其数据结构。
编辑:哈希表的另一个问题:缓存
大型哈希表中性能可能会下降的另一个问题是缓存性能。哈希表的缓存性能很差,因此对于大型集合来说,访问时间可能会更长,因为您需要将表的相关部分从内存重新加载到缓存中。
O(1)
。如果您需要最坏的情况-哈希表是不够的。
O(n)
到O(log n)
通过使用每个桶中的更复杂的数据结构。(我猜想如果哈希表已经在使用一个好的加密哈希,这可能会被认为是过大的,即使在攻击者的攻击下,它也可以防止冲突。)
理想情况下,哈希表为O(1)
。问题在于两个键是否相等,但是它们导致相同的哈希。
例如,假设字符串“这是最好的时间,这是最坏的时间”和“ Green Eggs and Ham”(绿色鸡蛋和火腿)的哈希值均为123
。
插入第一个字符串后,将其放在存储区123中。插入第二个字符串时,将看到bucket的值已存在123
。然后,它将新值与现有值进行比较,然后发现它们不相等。在这种情况下,将为该键创建一个数组或链接列表。在这一点上,O(n)
随着哈希表需要遍历该存储桶中的每个值以找到所需的值,检索该值变得很重要。
因此,在使用哈希表时,重要的是使用具有真正好的哈希函数的键,该键既快速又不会经常导致不同对象的值重复。
说得通?
as the hashtable needs to iterate through each value in that bucket
但是存储桶不包含n
项目,仅包含散列到该特定键的项目?
n
物品
也许您在看空间的复杂性?那就是O(n)。其他复杂性是哈希表条目上预期的。随着存储桶数量的增加,搜索复杂度接近O(1)。如果在最坏的情况下,哈希表中只有一个存储桶,则搜索复杂度为O(n)。
编辑以回应评论 我认为O(1)是平均情况是不正确的。确实是(如Wikipedia页面所说)O(1 + n / k),其中K是哈希表的大小。如果K足够大,则结果有效为O(1)。但是假设K为10,N为100。在这种情况下,每个存储桶平均要有10个条目,因此搜索时间肯定不是O(1);它是最多10个条目的线性搜索。
table_size/8 <= #elements <= table_size/2
,因此返回到O(1)
。但是,如果表的大小是动态的-仍然存在重新哈希问题,这同样是最糟糕的情况O(n)
。查看我的答案以获取详细信息和解释。