从链表标签维基摘录:
链表是一种数据结构,其中元素包含对下一个(也可以是前一个)元素的引用。链表在任何位置提供 O(1) 的插入和删除,O(1) 的列表连接,在前面(和可选的后面)位置的 O(1) 访问以及 O(1) 的下一个元素访问。随机访问具有 O(N) 复杂度并且通常未实现。
(强调我的)
读到这里我很惊讶——列表如何插入一个比简单地读取该索引更复杂的随机索引?
所以我查看了java.util.LinkedList
. add(int, E)
方法是:
public void add(int index, E element) {
addBefore(element, (index==size ? header : entry(index)));
}
该addBefore(E, Entry<E>
方法只是指针重新分配,但也有entry(int)
方法:
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 符号吗?