为什么要在链表O(1)的中间插入?


105

根据Wikipedia关于链表的文章,在链表的中间插入被视为O(1)。我认为这将是O(n)。您是否不需要定位列表末尾附近的节点?

这种分析是否不考虑发现节点操作(尽管是必需的),而仅考虑插入本身?

编辑

链接列表比数组具有多个优势。在列表的特定点插入元素是一项固定时间的操作,而在数组中插入则可能需要移动一半或更多的元素。

上面的陈述对我有些误导。如果我错了,请纠正我,但我认为结论应该是:

数组:

  • 查找插入/删除点O(1)
  • 执行插入/删除O(n)

链接列表:

  • 找出插入/删除点O(n)
  • 执行插入/删除O(1)

我认为,您唯一不需要找到位置的就是保持某种指针(在某些情况下为头和尾)。因此,我们不能断然地说,链表总是在插入/删除选项中击败数组。

Answers:


113

您是正确的,本文将“索引”视为一个单独的操作。所以插入本身就是O(1),但是到达那个中间节点就是O(n)。


3
在同一位置插入多个对象时,这会有更大的不同...
QUIT--Anony-Mousse 2011年

@ Anony-Mousse您能再解释一下吗?即,我们在插入多个对象时只需要查找一次插入位置?
MyTitle 2013年

2
现有列表的大小为O(n),而不是您打算在此处进行插入的数量。
已退出–Anony-Mousse 2013年


25

不,当您决定要插入时,假定您已经在遍历列表中。

链表上的操作通常以这样一种方式完成:它们实际上并没有被视为通用的“列表”,而是被视为节点的集合-可以将节点本身视为主循环的迭代器。因此,当您遍历列表时,您会注意到,作为业务逻辑的一部分,需要添加一个新节点(或删除一个旧节点),然后执行此操作。您可以在单次迭代中添加50个节点,而每个节点的时间仅为O(1)即可取消链接两个相邻节点并插入新节点的时间。

编辑:伙计,您键入第二段,然后突然成为第一个回答者,而不是第一个响应者,您是第5个说同样的话!


1
是的,糟糕透了...我为您+1了,因为值得指出的是,链表插入的复杂性已经在所需指针的上下文中考虑了。
Daniel Macias

6

为了与图表进行比较,该图表显示的是O(1),因为您不必将所有项目都移到新节点之后。

所以是的,他们假设您已经有指向该节点的指针,或者获取该指针很简单。换句话说,问题出在:“ 给定节点X处,要在该节点之后插入什么代码?” 您可以从插入点开始。


5

插入链表与在链表中进行迭代不同。您没有找到该项目,而是要重置指针以将该项目放入其中。不管是在前端附近还是在前端附近插入,插入仍然涉及重新分配指针。当然,这取决于它的实现方式,但这就是列表的优势-您可以轻松插入。通过索引访问是数组的亮点。但是,对于列表,找到第n个项目通常为O(n)。至少那是我从学校记得的。


3

因为它不涉及任何循环。

插入就像:

  • 插入元素
  • 链接到上一个
  • 链接到下一个
  • 做完了

无论如何,这是恒定的时间。

因此,一个接一个地插入n个元素为O(n)。


3

这种分析是否不考虑发现节点操作(尽管是必需的),而仅考虑插入本身?

你说对了。在给定点插入将假定您已经拥有指向要在以下位置插入的项目的指针:

InsertItem(item * newItem, item * afterItem)


2

不,它不考虑搜索。但是,如果您已经在列表中间拥有一个指向项目的指针,则在该点插入的是O(1)。

如果必须搜索,则必须增加搜索时间,该时间应为O(n)。


0

本文是关于将数组与列表进行比较。查找数组和列表的插入位置均为O(N),因此本文将其忽略。


1
找不到数组的插入点是O(1)吗?由于数组存储在连续内存中,因此只需添加偏移量即可。
罗布·索伯斯

@ vg1890-您必须先找到偏移量。

0

O(1)取决于您有一个要在其中插入新项目的项目的事实。(之前或之后)。如果不这样做,则因为您必须找到该物品,所以它是O(n)。


0

我认为这只是您选择为O()表示法计数的一种情况。在插入普通操作时要计数的是复制操作。对于数组,插入到中间涉及将位置上方的所有内容复制到内存中。对于链接列表,这将设置两个指针。无论插入什么,都需要查找位置。


0

如果对链表的操作为O(1),则在插入节点的引用之后。
对于数组,它仍然是O(n),因为您必须移动所有结果节点。


0

最常见的情况可能是在列表的开头或结尾处插入(并且列表的结尾可能不需要时间就可以找到)。

与此形成对比的是,在数组的开头或结尾插入项目(如果在数组的结尾处需要调整数组的大小,或者在数组的开头则需要调整并移动所有元素的大小)。


如果在末尾保留一个空元素的缓冲区,则可以使向数组末尾插入项目为O(1),尽管偶尔插入仍为O(1)。大多数收藏都这样做。通过将索引运算符更改为返回元素编号(n + x)%len,其中x是将项目插入到开头的次数,也可以使插入到数组开头的项目为O(1)。列表中。有时,双端队列是这样实现的(但有时也会使用双向链表来实现。–
Brian
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.