Linked list LinkedList';s加上O(1)复杂度的(int,E)?

Linked list LinkedList';s加上O(1)复杂度的(int,E)?,linked-list,java,big-o,time-complexity,Linked List,Java,Big O,Time Complexity,从标记wiki摘录: 链表是一种数据结构,其中的元素包含 对下一个(也可以是上一个)元素的引用。联系 列表提供在任何位置插入和删除O(1)列表 连接,以及前端(和可选后端)的O(1)访问 位置以及O(1)下一个元素访问。随机存取有O(N) 复杂性,并且通常未实现 (强调矿山) 读到这篇文章我很惊讶——列表如何以比简单地读取该索引更低的复杂性插入随机索引 所以我看了看。最重要的是: 这只是指针的重新分配,但也有: if(索引=大小) 抛出新IndexOutOfBoundsException(“索引

从标记wiki摘录:

链表是一种数据结构,其中的元素包含 对下一个(也可以是上一个)元素的引用。联系 列表提供在任何位置插入和删除O(1)列表 连接,以及前端(和可选后端)的O(1)访问 位置以及O(1)下一个元素访问。随机存取有O(N) 复杂性,并且通常未实现

(强调矿山)

读到这篇文章我很惊讶——列表如何以比简单地读取该索引更低的复杂性插入随机索引

所以我看了看。最重要的是:

这只是指针的重新分配,但也有:

if(索引<0 | |索引>=大小)
抛出新IndexOutOfBoundsException(“索引:”+索引+
,大小:“+大小);
条目e=标题;
如果(索引<(大小>>1)){
对于(int i=0;i索引;i--)
e=e.先前;
}
返回e;
}
即使有一半大小的优化,这里的
for
循环(一个或另一个)在我看来似乎是一个死赠品,即该方法(因此
add(int,E)
)在O(n)时间的最小最坏情况下运行,当然不是恒定时间


我错过了什么?我是否误解了big-O表示法?

好吧,它们确实支持在任意位置进行固定时间插入–但是只有当您碰巧有一个指向列表项的指针,您希望在该列表项之后或之前插入内容时才可以。当然,如果您只有索引,这将不起作用,但这不是您在优化代码中通常所做的

在Java中,您也可以这样做,但是


与ArrayList等相比,链表的这一属性是它们最大的优势——例如,如果您想从聊天室的用户列表中删除一个用户,您可以将指向该用户在用户列表中的位置的指针存储在该用户中,这样,当他想离开聊天室时,可以将其实现为
O(1)
操作。

这是因为您正在阅读的文章将“获取该索引”视为一个单独的操作。本文假设您已经处于要执行add(int,E)的索引位置

总结如下:

插入或删除操作=O(1)


在第n个索引处查找节点=O(n)

将新节点链接到任何节点的操作是O(1),但查找相关索引的操作肯定是O(n)


没有魔法;)

您引用的wiki页面上说:

O(1)在任何位置插入和拆卸

然后你问:

读到这篇文章我很惊讶——列表怎么能以随机索引插入


混淆就在这里:术语“位置”和“索引”并不是用来指同一件事的。wiki谈论的是迭代器或指针,而不是索引。

换句话说:
LinkedList.add(int,E)
不是O(1),而是
ListIterator.add
是(对于来自
LinkedList
的迭代器)。尽管
position
有点含糊不清。。。“插入…在”表示索引解释。我建议对tag wiki进行编辑以澄清,你对此有何看法?@thejh:我个人认为这很清楚。然而,考虑到至少有一个人觉得它令人困惑,我不认为稍微澄清一下会有什么害处。根据这个答案,在第n个索引处找到一个节点是O(1)。我还不确定我同意哪一个答案:|@JoãoMatos,这个特别的答案是关于addLast()方法复杂性的问题。由于java的LinkedList是一个双链接列表,维护指向第一个和最后一个元素的指针,因此addLast()是O(1)。在任意索引处查找节点仍然是O(n)。
public void add(int index, E element) {
    addBefore(element, (index==size ? header : entry(index)));
}
if (index < 0 || index >= size)
        throw new IndexOutOfBoundsException("Index: "+index+
                                            ", Size: "+size);
    Entry<E> e = header;
    if (index < (size >> 1)) {
        for (int i = 0; i <= index; i++)
            e = e.next;
    } else {
        for (int i = size; i > index; i--)
            e = e.previous;
    }
    return e;
}