Vom linked-list tag wiki Auszug:Wie ist LinkedList add (int, E) O (1) Komplexität?
Eine verkettete Liste ist eine Datenstruktur, in der die Elemente Verweise auf das nächste (und gegebenenfalls das vorherige) Element enthalten. Verknüpfte Listen bieten O (1) Einfügen und Entfernen an jeder Position, O (1) Liste Verkettung und O (1) Zugriff auf die vorderen (und optional zurück) Positionen sowie O (1) nächstes Element Zugriff. Random Access hat O (N) Komplexität und ist in der Regel nicht implementiert.
(Hervorhebung von mir)
Ich war überrascht, das lesen – wie kann die Liste bei einem zufälligen Index mit einer geringeren Komplexität einsetzt als nur zu lesen, dass Index?
So schaute ich auf the source code for java.util.LinkedList
. Die add(int, E)
method ist:
public void add(int index, E element) {
addBefore(element, (index==size ? header : entry(index)));
}
Die addBefore(E, Entry<E>
method ist einfach Neuzuordnung Zeiger, aber es gibt auch die 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;
}
Auch bei der Halbgrößenoptimierung, die for
Schleife in hier (die eine oder andere) ein untrügliches Zeichen scheint mir, dass diese Methode (und damit add(int, E)
) in einem Worst-case-Szenario von O (n) Zeit, und schon gar nicht konstante Zeit Minimum arbeitet.
Was fehlt mir? Verkenne ich die Groß-O-Notation?
Mit anderen Worten: 'LinkedList .add (int, E)' ist nicht O (1), sondern 'ListIterator .add' ist (für Iteratoren, die von einer 'LinkedList' kommen). –
sepp2k