Zeitkomplexität von Operationen auf eingebauten Typen¶
Diese Seite dokumentiert die Zeitkomplexität verschiedener Operationen auf eingebauten Typen in CPython. Andere Python-Implementierungen können ein anderes Laufzeitverhalten haben. Außerdem setzen die angegebenen Kosten genau diese eingebauten Typen voraus, denn Instanzen von Unterklassen können andere Kosten haben.
Wir verwenden die Big O notation, um zu beschreiben, wie die Laufzeit einer Operation mit der Größe ihrer Eingaben wächst. Sofern nicht anders angegeben, bezeichnet n die Anzahl der Elemente, die der Container gerade enthält, und k ist der Wert eines numerischen Parameters, etwa eines Index oder einer Wiederholungszahl.
list¶
Listen sind veränderbare Sequenzen. Mehr zur Umsetzung findest du unter Wie sind Listen in CPython umgesetzt?. Die größten Kosten entstehen, wenn eine Liste über die aktuell belegte Größe hinauswächst (weil dann alles umziehen muss), oder wenn irgendwo nahe am Anfang eingefügt oder gelöscht wird (weil dann alles dahinter umziehen muss). Musst du an beiden Enden hinzufügen oder entfernen, nimm stattdessen eine collections.deque in Erwägung.
Operation |
Komplexität |
|---|---|
Kopieren ( |
O(n) |
Anhängen ( |
O(1) |
O(n - k) |
|
O(n - k) |
|
Element lesen ( |
O(1) |
Element setzen ( |
O(1) |
Element löschen ( |
O(n - k) |
Iteration |
O(n) |
Slice lesen ( |
O(j - i) |
Slice setzen ( |
O(j - i), falls len(t) == j - i, sonst O(n - i + len(t)) |
Slice löschen ( |
O(n - i) |
O(len(t)) |
|
Sortieren ( |
O(n log n) |
Verketten ( |
O(len(l1) + len(l2)) |
Vervielfachen ( |
O(nk) |
|
O(n) |
|
O(n) |
Länge ermitteln ( |
O(1) |
tuple¶
Ein tuple ist eine unveränderliche Sequenz. Weil sich ein Tupel niemals ändern kann, entstehen keine Kosten für Einfügen oder Löschen, und eine Kopie gibt einfach dasselbe Objekt zurück, braucht also konstante Zeit (O(1)).
Operation |
Komplexität |
|---|---|
Kopieren ( |
O(1) |
Element lesen ( |
O(1) |
Slice lesen ( |
O(j - i) |
Verketten ( |
O(len(t1) + len(t2)) |
Vervielfachen ( |
O(nk) |
Iteration |
O(n) |
|
O(n) |
|
O(n) |
Länge ermitteln ( |
O(1) |
dict, frozendict¶
Die für dict-Objekte angegebenen Zeiten sind Zeiten für den durchschnittlichen Fall, denn sie setzen voraus, dass die Hashfunktion der Objekte robust genug ist, um Kollisionen selten zu machen. Sie setzen außerdem voraus, dass die Schlüssel gut über die Menge der möglichen Schlüssel verteilt sind. Im schlechtesten Fall, wenn jeder Schlüssel auf denselben Wert hasht, braucht jede der unten mit O(1) angegebenen Operationen stattdessen O(n) Zeit. Sie setzen ferner voraus, dass Hashen und Vergleichen eines Schlüssels O(1) ist. Mehr zur Umsetzung findest du unter Wie sind Dictionarys in CPython umgesetzt?.
Ein frozendict ist unveränderlich, unterstützt also kein Setzen, Löschen oder Aktualisieren von Elementen. Die übrigen Operationen unten gelten für es mit denselben Kosten.
Operation |
Komplexität |
|---|---|
|
O(1) |
O(n) |
|
Element lesen ( |
O(1) |
Element setzen ( |
O(1) |
Element löschen ( |
O(1) |
O(len(t)) |
|
Iteration [7] |
O(n) |
Länge ermitteln ( |
O(1) |
set, frozenset¶
Siehe dict, denn die Umsetzungen von set und frozenset sind ähnlich, und es gelten dieselben Einschränkungen. Im schlechtesten Fall brauchen die mit O(1) angegebenen Operationen stattdessen O(n) Zeit, und Operationen, die jedes Element nachschlagen, verschlechtern sich entsprechend.
Ein frozenset ist unveränderlich, unterstützt also weder Hinzufügen und Verwerfen noch die Operationen, die an Ort und Stelle aktualisieren. Die übrigen unten gelten für es mit denselben Kosten.
Operation |
Komplexität |
|---|---|
|
O(1) |
O(n) |
|
Hinzufügen ( |
O(1) |
Verwerfen ( |
O(1) |
Vereinigung ( |
O(len(s1) + len(s2)) |
O(len(s2)) |
|
O(min(len(s1), len(s2))) |
|
Schnittmenge aktualisieren ( |
O(min(len(s1), len(s2))) |
O(len(s1)) |
|
Differenz aktualisieren ( |
O(min(len(s1), len(s2))) |
Symmetrische Differenz ( |
O(len(s1) + len(s2)) |
Symmetrische Differenz aktualisieren ( |
O(len(s2)) |
Länge ermitteln ( |
O(1) |
str, bytes, bytearray¶
str- und bytes-Objekte sind unveränderliche Sequenzen von Zeichen beziehungsweise Bytes. Wie bei Tupeln gibt eine Kopie das ursprüngliche Objekt zurück. Ein bytearray ist veränderbar und unterstützt zusätzlich die verändernden Operationen von list (außer sort()), mit denselben Kosten. Allerdings rückt das Löschen am Anfang mit del (del b[0], del b[:k]) nur den Anfang des Puffers vor, statt die übrigen Bytes zu verschieben, und ist amortisiert O(1).
Operation |
Komplexität |
|---|---|
Element lesen ( |
O(1) |
Slice lesen ( |
O(j - i) |
Verketten ( |
O(len(s) + len(t)) |
Vervielfachen ( |
O(nk) |
Teilzeichenkette suchen ( |
O(n) |
Teilzeichenkette rückwärts suchen ( |
O(n × len(x)) |
Kodieren oder Dekodieren [13] |
O(n) |
Iteration |
O(n) |
Länge ermitteln ( |
O(1) |
memoryview¶
memoryview-Objekte erlauben Python-Code, auf die internen Daten eines Objekts zuzugreifen, das das Puffer-Protokoll unterstützt, ohne zu kopieren. Insbesondere gibt das Slicing einer Speicheransicht eine neue Ansicht auf denselben Puffer zurück.
Operation |
Komplexität |
|---|---|
Erzeugen ( |
O(1) |
Element lesen ( |
O(1) |
Slice lesen ( |
O(1) |
O(n) |
|
Zählen ( |
O(n) |
In Bytes umwandeln ( |
O(n) |
Länge ermitteln ( |
O(1) |
range¶
Ein range-Objekt berechnet seine Elemente bei Bedarf aus seinen Werten start, stop und step. Die meisten Operationen hängen daher nicht von der Länge des Bereichs ab.
Operation |
Komplexität |
|---|---|
Element lesen ( |
O(1) |
Slice lesen ( |
O(1) |
|
O(1) |
Index und Anzahl ( |
O(1) |
Iteration |
O(n) |
|
O(n) |
Länge ermitteln ( |
O(1) |