我已经看过一两线了,但我还是认为它已经完全清理了......
我一直在使用“算法简介”(第11章)中的链接来查看哈希表。他们说如果哈希表的链表是双重链接的,则可以在O(1)时间内执行删除。但我不知道如何。
T is a chained hash table. I want to delete element X from it.
h(X.key) returns the hash of X's key.
So, to delete X, pass X to the delete routine.
Then we can find X's slot in the linked list:
T[ h(X.key) ] = j
j is actually the pointer to the head of the linked list as > 1 key hashes to j.
So we still need to now search the linked list at j to find X to delete it,
regardless of whether or not the list is doubly linked.
And this search is O(n). So deletion is O(n)???
我的观点是,我们还不需要在链表中搜索X吗? X是我们想要存储在哈希表中的任意对象。它不包含指针。 包含X的链接列表中的元素将包含指向链接列表中下一个和上一个元素的指针,但不包含X.
答案 0 :(得分:1)
哈希表操作的成本是扫描所选桶的条目以获得所需的密钥。如果密钥分布均匀,则操作的平均成本仅取决于每个桶的平均密钥数。换句话说,关于负载系数。
具有低冲突率和大量插槽的哈希表将始终提供接近O(1)的操作。
即使表条目数n远远高于插槽数,链式哈希表仍然有效。它们的性能随负载因子更优雅地(线性地)降低。例如,具有1000个插槽和10,000个存储密钥(加载因子10)的链式哈希表比10,000个时隙表(加载因子1)慢5到10倍;但仍比普通顺序列表快1000倍。
由此我们假设当假设哈希表有足够的空间用于加载(AKA,加载因子为1)时,操作的摊销成本为O(1)。 / p>
答案 1 :(得分:1)
在这里深入挖掘后,我偶然发现了答案。
本书中隐含的假设是链表中的链接是元素X 的一部分,而不是有一个单独的容器节点对象来实现链接并指向元素。也就是说,我们希望删除的对象X包含指向链表中下一个和前一个元素的指针。作者真的应该明确这一点。
感谢RBarryYoung的回答!
答案 2 :(得分:1)
为什么在你的情况下删除O(1)? 以下内容引自CLRS第3版的P258:
请注意CHAINED-HASH-DELETE 将元素x而不是其键k 作为输入,这样我们就不必搜索x 第一。如果哈希表支持删除,那么它的链表应该是双重链接的 这样我们就可以快速删除一个项目。如果列表只是单独链接,那么 删除元素x,我们首先要在列表TŒh.x中找到x:key / so that that we 可以更新x的前任的下一个属性。
我们必须提供要删除的对象的指针。让对象为X.因此,要从X所属的双向链表中删除,我们只需执行以下操作:
X.left.right = X.right
X.right.left = X.left
完成!删除是不变的。 前一个下一个指针在X本身,键也是。
答案 3 :(得分:0)
哈希表上的插入和删除都是O(1)。您是正确的链接列表必须是这意味着任何一个操作可能需要多个操作。 关键是这种链接只发生在哈希函数的冲突时。如果碰撞是常规的,则删除将是O(n)。在算法教科书中,其工作原理的说明可能会显示相对较少数量的存储桶,但平均数量的冲突确实不与n一起增长,只有最坏的情况。