Algorithm 哈希表中的删除

Algorithm 哈希表中的删除,algorithm,hash,Algorithm,Hash,我在读《算法导论》一书时,遇到了这样一个问题: 如果列表是双重链接的,我们可以在O(1)时间内删除元素。(注意CHAINED-HASH-delete将元素x作为输入。) 而不是它的键k,这样我们就不必先搜索x 哈希表支持删除,那么它的链表应该是双重的 链接,以便我们可以快速删除项目。如果列表仅为 单独链接,然后删除元素x,我们首先要找到 x在列表T[h(x.key)]中,以便我们可以更新下一个 属性。对于单链接列表,两个 搜索将具有相同的渐近运行时间。) 如果列表是双链接的,我们如何在O(1)时

我在读《算法导论》一书时,遇到了这样一个问题:

如果列表是双重链接的,我们可以在O(1)时间内删除元素。(注意CHAINED-HASH-delete将元素x作为输入。) 而不是它的键k,这样我们就不必先搜索x 哈希表支持删除,那么它的链表应该是双重的 链接,以便我们可以快速删除项目。如果列表仅为 单独链接,然后删除元素x,我们首先要找到 x在列表T[h(x.key)]中,以便我们可以更新下一个 属性。对于单链接列表,两个 搜索将具有相同的渐近运行时间。)

如果列表是双链接的,我们如何在O(1)时间内删除元素?首先我们需要找到元素,然后在O(1)中删除它。但要找到它,我们需要O(列表的长度)时间。也许在双链接列表中删除会更快(因为我们可以同时从列表的两端进行搜索,但这只是不断的改进),但我不知道如何在O(1)时间内完成


先谢谢你

答案在文本中

请注意,CHAINED-HASH-DELETE将元素x而不是其键k作为输入,因此我们不必首先搜索x

您已经拥有该项目,因此只需将其从链中删除并执行删除操作


要删除项目X,您需要获取列表中的上一个和下一个节点,并在删除X之前将它们链接在一起,以便列表保持完整。在双链接列表中,您已经有到上一个和下一个的链接,所以这是常量。在单个链接列表中,您只有一个指向下一个节点的链接,因此您需要扫描列表以查找上一个节点。

答案在文本中

请注意,CHAINED-HASH-DELETE将元素x而不是其键k作为输入,因此我们不必首先搜索x

您已经拥有该项目,因此只需将其从链中删除并执行删除操作


要删除项目X,您需要获取列表中的上一个和下一个节点,并在删除X之前将它们链接在一起,以便列表保持完整。在双链接列表中,您已经有到上一个和下一个的链接,所以这是常量。在单个链接列表中,您只有一个到下一个的链接,因此您需要扫描列表以查找上一个节点。

我认为这里的混淆是因为CLR中的隐含假设。在本书中,对象通常被视为属性包,可以在运行时添加所需的属性,这与JavaScript非常相似,但与Java/C#world不同。所以,若要将x放入链表中,不必先创建一个节点对象,然后再为“上一个”、“下一个”和“值”添加属性。相反,您只需将这些属性添加到x本身。我们中许多在静态类型语言环境中长大的人都会对这种设计感到震惊,但对于使用伪代码的算法设计,它消除了不必要的混乱。我认为作者应该澄清这一点。在任何情况下,如果不能动态地将上一个、下一个属性添加到对象中,是的,即使使用双链接列表,它也不会是O(1)

我认为这里的混乱是因为CLRS中隐含的假设。在本书中,对象通常被视为属性包,可以在运行时添加所需的属性,这与JavaScript非常相似,但与Java/C#world不同。所以,若要将x放入链表中,不必先创建一个节点对象,然后再为“上一个”、“下一个”和“值”添加属性。相反,您只需将这些属性添加到x本身。我们中许多在静态类型语言环境中长大的人都会对这种设计感到震惊,但对于使用伪代码的算法设计,它消除了不必要的混乱。我认为作者应该澄清这一点。在任何情况下,如果不能动态地将上一个、下一个属性添加到对象中,是的,即使使用双链接列表,它也不会是O(1)

是的,你是对的,如果一个人保存了之前遍历的链接的历史记录,那么双链接列表不会节省很多钱。但如果你没有,它至少可以节省第二次搜索。注意:“注意CHAINED-HASH-DELETE接受一个元素x而不是它的键k作为输入”。这表示只传递了元素指针,没有历史记录。引号中的隐式假设是链接是元素的一部分,而不是存在实现链接并指向元素的单独容器节点对象。这样,您就不必搜索任何内容来删除元素,只需使用嵌入其中的FLink和BLink。在单链或双链列表中,查找要删除的元素是
O(n)
。如果您在查找阶段跟踪了前一个节点(或者如果您玩了一些把戏,例如将下一个节点数据移动到当前节点中并删除下一个节点),则实际删除是在双链接列表中或在单链接列表中的
O(1)
。但是,如果您没有跟踪您的前一个节点,并且没有移动节点,则在单链表中删除是
O(n)
可能重复的。是的,您是对的,如果您保留了先前遍历的链接的历史记录,则双链表不会节省太多。但如果你没有,它至少可以节省第二次搜索。注意:“注意CHAINED-HASH-DELETE接受一个元素x而不是它的键k作为输入”。这表示只传递了元素指针,没有历史记录。引号中的隐式假设是链接是元素的一部分,而不是存在实现链接并指向元素的单独容器节点对象。通过这种方式,您不必搜索任何内容来删除元素,只需使用嵌入其中的FLink和BLink即可。在单链或双链列表中,查找要删除的元素是
O(