Arrays
Den millionsten Wert eines Arrays zu lesen, kostet einen Schritt. Einen neuen Wert an den Anfang desselben Arrays zu setzen, verschiebt eine Million Werte.
Was eine Datenstruktur ist
Ein Programm, das eine Namensliste, eine Warteschlange von Druckaufträgen oder eine Preistabelle führt, muss diese Daten irgendwo speichern und Fragen dazu beantworten: Was ist das dritte Element, steht dieser Name in der Liste, welcher Auftrag ist als Nächstes dran? Eine Datenstruktur ist eine Art, Daten zu speichern, zusammen mit den Verfahren, die diese Fragen beantworten. Der MIT-Kurs 6.006 trennt hier zwei Ideen. Die Schnittstelle sagt, welche Operationen man verlangen kann, etwa „hol das Element an Position i“ oder „füg ein Element am Ende hinzu“. Die Datenstruktur ist, wie diese Operationen tatsächlich im Speicher ausgeführt werden. Hinter einer Schnittstelle können mehrere Datenstrukturen stehen, und sie können sich in der Geschwindigkeit gewaltig unterscheiden.
Dieser Kurs zählt wie der Algorithmenkurs Schritte, damit sich zwei Strukturen ohne Stoppuhr vergleichen lassen. In dieser Einheit ist ein Schritt das Lesen oder Schreiben einer Speicherzelle. Das Labor unten zählt sie für dich.
Ein Block von Zellen, Seite an Seite
Ein Array speichert seine Werte in einem lückenlosen Speicherblock, jeden Wert in einer gleich großen Zelle, nummeriert ab 0. Diese Anordnung macht Arrays schnell beim Lesen. Beginnt der Block an Adresse s und belegt jede Zelle c Bytes, dann liegt a[i] an Adresse s + i × c. Der Computer rechnet das mit einer Multiplikation und einer Addition aus und springt direkt dorthin, egal ob i 3 oder 3 000 000 ist. Die MIT-Unterlagen geben „get at(i)“ und „set at(i, x)“ für ein Array mit Θ(1) an. Das heißt, die Kosten wachsen nicht mit der Länge.
Dieselbe Anordnung macht Änderungen in der Mitte langsam. Angenommen, das Array enthält 7, 3, 9, 4, 6, und du willst eine 1 an den Anfang. Vor der 7 ist keine Lücke, also muss zuerst jeder Wert eine Zelle nach rechts rücken, angefangen beim letzten, damit nichts überschrieben wird. Das sind 5 Verschiebungen und 1 Schreibvorgang: 6 Schritte. Den vordersten Wert zu entfernen, ist das Spiegelbild: ihn lesen, dann die anderen 4 Werte eine Zelle nach links schieben. Einfügen an Position i in einem Array mit n Werten kostet n − i Verschiebungen plus einen Schreibvorgang. Der Anfang ist also die schlechteste Stelle und das Ende die beste.
Zum Drehen ziehen. Zum Zoomen scrollen oder mit zwei Fingern ziehen.
Wenn der Block voll ist
Ein Speicherblock hat eine feste Größe. Was passiert also, wenn du einen Wert hinzufügst und jede Zelle belegt ist? Das Array muss einen neuen, größeren Block anfordern und jeden Wert hinüberkopieren, bevor es den neuen schreiben kann. Im Labor kostet ein Push auf den vollen Block mit 5 Zellen 5 Kopien und 1 Schreibvorgang. Würde das Array jedes Mal nur um eine Zelle wachsen, würde jeder Push alles kopieren, und n Pushs kosteten etwa n²/2 Kopien.
Die Lösung aus den MIT-Unterlagen: auf einmal kräftig wachsen, zum Beispiel durch Verdoppeln. Bei Kapazität 1 beginnend, wird kopiert, wenn das Array 1, 2, 4, 8 und 16 Werte enthält. 17 Pushs kosten also insgesamt 1 + 2 + 4 + 8 + 16 = 31 Kopien, weniger als 2 pro Push. Ein einzelner Push kann trotzdem langsam sein, aber jede lange Folge von Pushs mittelt sich auf konstante Kosten pro Push. Das nennt man amortisierte Θ(1)-Zeit. Ein JavaScript-Array verhält sich von außen so: MDN beschreibt Arrays als in der Größe veränderbar, und push und pop arbeiten am Ende, dem billigen Ende.
| Operation bei n Werten | Schritte im Labor | Wächst wie |
|---|---|---|
| a[i] lesen oder schreiben | 1 | Θ(1) |
| Am Anfang einfügen | n Verschiebungen + 1 Schreibvorgang | Θ(n) |
| Den Anfang entfernen | 1 Lesevorgang + (n − 1) Verschiebungen | Θ(n) |
| Push am Ende (Platz frei) | 1 | Θ(1) |
| Push am Ende (Block voll) | n Kopien + 1 Schreibvorgang | einmal Θ(n), amortisiert Θ(1) |
const a = [7, 3, 9, 4, 6];
console.log(a[3]); // 4, ein Schritt
a.push(8); // billig: das Ende
a.unshift(1); // jeder Wert rückt eine Zelle nach rechts
console.log(a.join(" ")); // 1 7 3 9 4 6 8| Schnittstelle | Die Liste der Operationen, die man verlangen kann, etwa get at(i) oder insert last(x). |
| Datenstruktur | Wie diese Operationen im Speicher ausgeführt werden. |
| Array | Werte in einem Block gleich großer Zellen; a[i] liegt bei Start + i × Zellgröße. |
| Dynamisches Array | Ein Array, das wächst, indem es in einen größeren Block kopiert, meist doppelt so groß. |
| Amortisierte Kosten | Die durchschnittlichen Kosten pro Operation über eine lange Folge, auch wenn einzelne Operationen langsam sind. |
- Wie viele Schritte kostet nach der Zählweise dieser Einheit das Lesen von a[700000] aus einem Array mit 1 000 000 Werten?
- 1
- 20
- 700,000
- 1,000,000
- Ein Array enthält 7, 3, 9, 4, 6 und hat noch Platz. Wie viele Schritte kostet es, einen Wert am Anfang einzufügen (Verschiebungen plus Schreibvorgang)?
- Dasselbe Array mit 5 Werten: Wie viele Schritte kostet es, den vordersten Wert zu entfernen (1 Lesevorgang plus Verschiebungen)?
- Einfügen an Position 2 in ein Array mit 5 Werten (Positionen 0 bis 4), Platz ist frei: Wie viele Schritte?
- Ein sich verdoppelndes Array enthält 5 Werte, seine Kapazität ist 5. Du hängst mit push einen weiteren Wert an. Wie viele Schritte kostet dieser Push?
- Wie groß ist die Kapazität nach diesem Push?
- Bei Kapazität 1 beginnend und mit Verdoppeln: Wie viele Kopien machen 17 Pushs insgesamt?
- Warum heißt push bei einem sich verdoppelnden Array amortisiert Θ(1)?
- Jeder einzelne Push braucht genau einen Schritt
- Kopien sind selten, also bleibt die Summe über n Pushs unter einer Konstanten mal n
- Der Computer kopiert kostenlos im Hintergrund
- JavaScript kopiert Arrays nie
- In den Begriffen von MIT 6.006 ist „insert last(x) und delete last()“
- eine Datenstruktur
- eine Schnittstelle
- eine Speicheradresse
- ein Sortierverfahren
- Ein Array hat die Länge n und zählt ab 0. Welchen Index hat sein letzter Wert?
- n
- n − 1
- n + 1
- 1
- Eine Schnittstelle listet Operationen auf; eine Datenstruktur ist, wie sie ausgeführt werden.
- Ein Array hält Werte in einem Block, also ist a[i] ein Schritt.
- Einfügen oder Entfernen nahe am Anfang verschiebt etwa n Werte.
- Ein sich verdoppelndes Array macht push amortisiert Θ(1): 17 Pushs ab Kapazität 1 kopieren 31 Werte.
Quellen zu diesem Kurs (11)
- MIT OpenCourseWare 6.006 Introduction to Algorithms, Spring 2020 (Demaine, Ku, Solomon)
- lecture notes 2 Data Structures (interface vs data structure, Sequence and Set interfaces, stack = insert_last/delete_last, queue = insert_last/delete_first, array, linked list, dynamic array, amortized Θ(1) append)
- 4 Hashing (chaining, pigeonhole collisions, chain length n/m)
- 6 Binary Trees Part 1 (height, traversal order, O(h) operations) and 7 Binary Trees Part 2: AVL (Adelson-Velsky and Landis, 1962) at ocw.mit.edu/courses/6-006-introduction-to-algorithms-spring-2020/pages/lecture-notes
- MDN Web Docs, Array.prototype.shift (shifts all values left by 1)
- Array.prototype.unshift, Map (insertion order, Map vs Object, spec requires sublinear average access) and Set (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects)
- ECMAScript 2025 Language Specification (tc39.es/ecma262)
- 24.1 Map Objects and 24.2 Set Objects ("must be implemented using either hash tables or other mechanisms that, on average, provide access times that are sublinear on the number of elements")
- Array.prototype.shift steps (Repeat, while k < len: move element k to k - 1)
- D. E. Knuth, The Art of Computer Programming vol. 3 (2nd ed. 1998) section 6.4 History (H. P. Luhn, IBM internal memorandum January 1953, hashing with chaining; digit pairs added mod 10, 31415926 -> 4548) via gwern.net copy, and IEEE Spectrum, "Hans Peter Luhn and the Birth of the Hashing Algorithm" (2018)
- "A brief history of the stack", SIGCIS (sigcis.org/files/A brief history.pdf: Bauer and Samelson applied for the patent in 1957, US 3,047,228 granted July 31, 1962; IPL list processing by Newell, Simon and Shaw at RAND 1956) and Wikipedia, Information Processing Language (Newell, Shaw, Simon, RAND and Carnegie Institute of Technology, about 1956).
Abgerufen: 2026-10-18