LinkedList如何添加(int,E)O(1)复杂度?

时间:2013-03-31 17:31:36

标签: java linked-list big-o time-complexity

来自标签wiki摘录:

  

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

(强调我的)

我很惊讶地读到了这一点 - 如何将插入列表放在一个复杂程度低于读取索引的随机索引上?

所以我看了the source code for java.util.LinkedListadd(int, E) method是:

public void add(int index, E element) {
    addBefore(element, (index==size ? header : entry(index)));
}

addBefore(E, Entry<E> method只是指针重新分配,但也有entry(int) method

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;
}

即使是半尺寸优化,这里的for循环(一个或另一个)在我看来是一个死的赠品,这个方法(因此add(int, E))在最小的最差情况下运行 - O(n)时间的情况,当然不是恒定的时间。

我错过了什么?我误解了大O符号吗?

4 个答案:

答案 0 :(得分:13)

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

总结:

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

在n th 指数中查找节点= O(n)

答案 1 :(得分:4)

好吧,它们确实支持在任意位置进行常量插入 - 但只有在碰巧有一个指向列表条目的指针之后或之前要插入的东西。当然,如果您只有索引,这将不起作用,但这不是您在优化代码中通常所做的。

在Java中,您也可以这样做,但only using a list iterator

与arraylists相比,链接列表的这个属性是它们的最大优势 - 例如,如果你想从聊天室的用户列表中删除用户,你可以在用户列表中存储一个指向用户位置的指针。用户,当他想离开房间时,可以实现O(1)操作。

答案 2 :(得分:2)

新节点链接到任何节点的操作是O(1),但查找(有助于循环)相关索引的操作肯定是O( n)中。

没有魔力;)

答案 3 :(得分:1)

您引用的维基页面说:

  

O(1)在任何位置插入和移除

然后你问:

  

我很惊讶地看到这个 - 如何在随机索引中插入列表

这就是混乱:术语位置索引并不是用来表示相同的事情。 wiki讨论迭代器或指针,而不是索引。