当前位置: 首页 > 知识库问答 >
问题:

为什么链表的删除和插入操作复杂度为O(1)?不应该是O(n)的吗

楚宏胜
2023-03-14

据说 LinkedList 删除和添加操作的复杂性为 O(1)。ArrayList 的情况下,它是 O(n)。

大小为“M”的数组列表的计算:如果我想删除第N个位置的元素,那么我可以使用index一次直接转到第N个位置(我不必遍历到第N个索引),然后我可以删除元素,直到此时复杂度为O(1),然后我必须移动其余的元素(M-N次移动),所以我的复杂度将是线性的,即O(M-N-1)。因此在最后删除或插入会给我最好的性能(如N ~ M ),而在开始删除或插入会最差(如N ~ 1)。

现在,大小为“M”的LisnkedList:由于我们无法直接访问LinkedList中的第N个元素,为了访问第N个,我们必须遍历N个元素。因此,LinkedList的搜索成本比ArrayList高……但如果是LinkedList,Remove和add操作被称为O(1),因为LinkedList不涉及Shift,但是否涉及遍历操作?因此复杂性应该是O(n)阶,其中最差性能将在尾部节点,而最佳性能将在头部节点。

有人能解释一下为什么我们在计算LinkedList remove操作的复杂度时不考虑遍历成本?

所以我想了解一下它在java.util包中是如何工作的。如果我想在C或C中实现同样的功能,我如何在LinkedList中实现随机删除和插入的O(1)呢?

共有3个答案

韩良策
2023-03-14

是的,如果你一次考虑两个操作(索引和插入),你是正确的。在这种情况下不成立,因为当你在一个链表的中间插入一个节点时,假设你已经在你要插入节点的地址了。

访问节点的时间复杂度为 O(n),而仅插入节点的时间复杂度为 O(1)。

在头部插入需要您添加元素并更新头部指针。

newnode->next = head;
head = newnode;

尾部插入要求您保留指向尾部元素的指针,在尾部添加元素并更新尾部指针。

tail->next = newnode;
tail = newnode;

删除 head 元素需要更新 head 并删除以前的 head 元素。

temp = head;
head = head->next;
delete temp; /* or free(temp); */

以上都是琐碎的操作,不依赖于链表中元素的数量。因此,它们是O(1)

然而,删除尾部元素将是一个O(n)操作,因为即使您可能有尾部指针,您仍然需要将设置为新尾部节点的倒数第二个节点(通过更新尾部指针并将节点的下一个成员设置为NULL)。为此,您需要遍历整个链接列表。

penultimate_el = find_penultimate_el(head); /* this is O(n) operation */
delete tail; /* or free(tail) */
tail = penultimate_el;
tail->next = NULL;
何高旻
2023-03-14

移除的复杂性被认为是你已经有了指向你想要移除的元素的正确位置的指针...

不考虑您找到它所花费的成本

Information on this topic is now available on Wikipedia at: Search data structure

    +----------------------+----------+------------+----------+--------------+
    |                      |  Insert  |   Delete   |  Search  | Space Usage  |
    +----------------------+----------+------------+----------+--------------+
    | Unsorted array       | O(1)     | O(1)       | O(n)     | O(n)         |
    | Value-indexed array  | O(1)     | O(1)       | O(1)     | O(n)         |
    | Sorted array         | O(n)     | O(n)       | O(log n) | O(n)         |
    | Unsorted linked list | O(1)*    | O(1)*      | O(n)     | O(n)         |
    | Sorted linked list   | O(n)*    | O(1)*      | O(n)     | O(n)         |
    | Balanced binary tree | O(log n) | O(log n)   | O(log n) | O(n)         |
    | Heap                 | O(log n) | O(log n)** | O(n)     | O(n)         |
    | Hash table           | O(1)     | O(1)       | O(1)     | O(n)         |
    +----------------------+----------+------------+----------+--------------+

 * The cost to add or delete an element into a known location in the list (i.e. if you have an iterator to the location) is O(1). If you don't know the location, then you need to traverse the list to the location of deletion/insertion, which takes O(n) time. 
** The deletion cost is O(log n) for the minimum or maximum, O(n) for an arbitrary element.
唐腾
2023-03-14

LinkedList的情况下,删除和添加操作被称为O(1),因为在LinkedList中不涉及移位,但涉及遍历操作,对吗?

添加到链表的任一端不需要遍历,只要保留对列表两端的引用即可。这就是Java对其add和addFirst/addLast 方法所做的。

这同样适用于无参数的< code>remove和< code > remove first /< code > remove last 方法——它们在列表末尾操作。

另一方面,remove(int) 和 remove(Object) 操作不是 O(1)。它们需要遍历,因此您正确地将其成本标识为 O(n)。

 类似资料:
  • 问题内容: 我刚刚开始学习数据结构,并且在进行数组插入时想知道为什么数组插入的时间复杂度为O(n)而不是O(n + 1)? 在最佳情况下,当插入在最后时,时间复杂度为O(1)。我想我们正在考虑1插入元素,因为这里没有元素被移动。在最坏的情况下,假设我们必须移动n个元素然后插入新元素,那么时间时间复杂度是否应该为O(n + 1)?n用于移动元素,1用于插入。 非常感谢您的帮助。 问题答案: O(n)

  • 我需要制作一个可以进行三次操作的链表。所有这三个操作都必须具有 O(1) 复杂性。 有问题的操作是: < li >添加到尾部 < li >从头部移除 < li >返回中间节点 正在使用的节点结构如下: 为了移除头部,我通过通常对头部节点的引用实现了O(1) 为了添加到尾,我通过引用尾节点实现了O(1) 我的问题是返回中间节点。我知道如何通过遍历列表来实现这一点,但这意味着它将具有O(n)复杂度。我

  • Redis zrank。 返回存储在key处的排序集中成员的排名,分数从低到高排序。排名(或指数)是基于0的,这意味着得分最低的成员排名为0。 为什么复杂度是O(log(N))?成员按分数排序,但zank按成员查询。 我找到了一些可能是答案的东西。 A.zset由ziplist实现时 大小小于128 每个成员的大小小于64字节 所以,ziplist的大小很小,所以这不是我讨论的问题。 B.当zse

  • 我不明白堆排序的空间复杂度是怎样的O(1)?虽然快速排序不使用任何额外的数组(即就地),但在最坏情况下其空间复杂度为O(n),在最佳情况下为O(lg n),因为在递归调用的后端使用堆栈。我说得对吗? 堆排序也是如此。虽然,它是就地的,但是由于Build-Heap函数调用Max-Heapify函数,所以它的空间复杂度应该等于Max-Heapify,即O(lg n)。不是吗?此外,稍后在根节点调用Ma

  • 算法相对较新,所以如果我遗漏了一些显而易见的东西,请原谅! 我知道深度优先搜索的空间复杂度通常表示为O(h),其中h是树的高度,而广度优先搜索的复杂度是O(n),其中n是树中节点的数量。 我理解解释(例如在这个答案中https://stackoverflow.com/a/9844323/10083571)也就是说,在BFS中最坏的情况下,所有节点都在一个级别上,这意味着我们必须在遍历它们之前将所有