双链表单元素删除的时间复杂度?

时间:2011-05-28 12:22:09

标签: linked-list big-o

我正在阅读的很多内容都说删除双向链表(DLL)中的内部元素是O(1);但为什么会这样呢?

我理解为什么SLL为O(n);遍历列表O(n)并删除O(1)但是您是否仍需要遍历DLL中的列表以查找元素?

4 个答案:

答案 0 :(得分:15)

对于双向链接列表,一旦知道元素,就会一直移除元素

对于单个链接列表,一旦你知道它的它的前身,它就是一个永久的时间去除它。

由于您指向的链接会将单个链接列表删除显示为O(n),将双重链接列表显示为O(1),因此您可以确定已经知道要删除该元素的位置,但其他任何东西。

在这种情况下,对于双向链接列表,您只需使用prevnext指针将其删除,即可获得O(1)。忽略你在头部或尾部的边缘情况,这意味着:

corpse->prev->next = corpse->next
corpse->next->prev = corpse->prev
free (corpse)

但是,在您只知道要删除的节点的单个链接列表中,您不能使用corpse->prev来获取它之前的节点,因为 no {{1链接。

您必须通过从头部遍历列表来查找找到上一个项目,查找具有您要删除的元素的prev的列表。这将需要next,之后再次O(n)进行实际删除,例如(为了简单起见,忽略边缘情况):

O(1)

那是为什么这篇文章中的两个复杂性不同。


顺便说一句,单链表中有优化可以删除lefty = head while lefty->next != corpse: lefty = lefty-> next lefty->next = corpse->next free (corpse) (一旦找到要删除的项目,删除就会有效地为O(1)。项目)。在代码术语中,这类似于:

O(n)

答案 1 :(得分:4)

如上所述,链接指向:

  

更改内部元素的成本基于已经有一个指向它的指针,如果您需要先找到该元素,则还需要检索该元素的成本。

因此,对于DLL和SLL,线性搜索都是O(n),通过指针删除是O(1)。

答案 2 :(得分:2)

DLL中删除的复杂性为O(1)。 如果提供指向前一个元素的指针而不是元素本身,它也可以是SLL中的O(1)

这种复杂性是假设您知道元素的位置

即。操作签名类似于remove_element(list* l, link* e) 在这两种情况下,搜索元素都是O(n)

答案 3 :(得分:1)

@Matuku:你是对的。

我谦卑地不同意这里的大多数答案,试图证明DLL的删除操作是O(1)。不是。

让我解释一下。

为什么我们要考虑我们'将'指向要删除的节点的指针的场景? LinkedLists(Singly / Doubly)是线性遍历的,这就是他们的定义。它们只有指向头/尾的指针。我们怎么能突然有一个指向其间某个节点的指针?这违背了这种数据结构的目的。按照这个假设,如果我有一个100万个节点的DLL列表,那么我还需要保持100万个指针(让我们称之为访问指针)指向每个节点,以便我可以在O中删除它们( 1)?那么我将如何存储这100万个访问指针?我怎么知道哪个访问指针指向我想要删除的正确数据/节点?

我们能否拥有一个真实世界的例子,我们拥有指向必须在100%时间内删除的数据的指针?

如果您知道要删除的节点的确切位置/指针/引用,为什么要使用LinkedList?只需使用数组!这就是阵列的用途 - 直接访问你想要的东西!

通过假设您可以直接访问DLL中所需的任何节点,这违反了LinkedList作为概念数据结构的整体思路。所以我同意OP,他是对的。我会坚持这一点 - 双重LinkedLists 不能有O(1)删除任何节点。你仍然需要从头部或尾部开始,这将它降低到O(n)。

如果”我们有指向要删除的节点的指针说X,那么当然它是O(1)因为我们有指向下一个节点的指针我们可以删除X.但是如果是想象的那么大,不是真实的。

我们不能使用名为LinkedLists的神圣数据结构的定义来解决我们可能不时出现的一些奇怪的假设。