我正在阅读“算法入门”一书,我遇到了这个:
如果列表是双重链接,我们可以在O(1)时删除一个元素。(注意CHAINED-HASH-DELETE将元素x作为输入 而不是它的关键k,所以我们不必先搜索x。如果 哈希表支持删除,那么它的链表应该是双倍的 链接,以便我们可以快速删除项目。 如果列表只是 单独链接,然后删除元素x,我们首先要找到 列表T [h(x.key)]中的x ,以便我们可以更新下一个 x的前身属性。使用单链表,都删除 并且搜索将具有相同的渐近运行时间。)
如果列表是双重链接的,我们如何在O(1)时间内删除元素?首先,我们需要找到元素,然后我们可以在O(1)中删除它。但要找到它,我们需要O(列表的长度)时间。也许在双向链表中删除速度更快(因为我们可以同时从列表的两端进行搜索,但这只是不断改进),但我不知道如何在O(1)中完成时间。
提前谢谢你。
答案 0 :(得分:4)
答案在案文中;
请注意,CHAINED-HASH-DELETE将元素x作为输入而不是其键k,因此我们不必先搜索x。
您已经拥有该项目,因此您只需将其从链中删除即可进行删除。
要删除项目X,您需要获取列表中的上一个和下一个节点,并在删除X之前将它们链接在一起,以便列表保持不间断。在双向链表中,您已经有一个指向上一个和下一个的链接,所以这是不变的。在单个链表中,您只有一个指向next的链接,因此您需要扫描列表以查找上一个节点。
答案 1 :(得分:1)
我认为这里的混淆是因为CLRS中的隐含假设。在本书中,对象通常被视为属性包,其中可以在运行时添加所需的属性 - 很像JavaScript,但不像Java / C#world。因此,如果您想将x放在链表中,则不必须首先创建一个Node对象,然后然后添加Previous,Next和Value的属性。相反,您只需将这些属性添加到x本身。我们中许多使用静态类型语言长大的人会对这种设计感到震惊,但对于使用伪代码的算法设计,它会消除不必要的混乱。我认为作者应该澄清这一点。在任何情况下,没有能力动态地向对象添加Previous,Next属性,是的,即使使用双向链表也不会是O(1)。