Sortier-Algorithmen v0.2.12

Interaktive Visualisierung mit schrittweiser Animation

 
 
0 / 0
0
Vergleiche
Wie oft zwei Elemente miteinander verglichen wurden.
0
Tausche
Wie oft zwei Elemente ihre Plätze getauscht haben.
0
Verschiebungen
Wie oft ein Wert auf eine Position geschrieben oder verschoben wurde.
0
Schritt
Der aktuell ausgeführte Visualisierungsschritt.
0 ms
Zeit
Vergangene Echtzeit seit Start der Animation.
Über die Algorithmen

Speicher-Ansicht: Bei Tree Sort, Merge Sort, Timsort, Heap Sort, Counting Sort, Radix Sort und Bucket Sort wird der Arbeitsspeicher unterhalb des Arrays visualisiert. Sie sehen genau, wo Daten zwischengespeichert werden — ob als Baumstruktur (BST, Heap), Hilfs-Arrays (Merge), Häufigkeitstabelle (Counting) oder Bucket-Verteilung (Radix, Bucket).

Legende der Eigenschaften

Stabil Gleiche Werte behalten ihre ursprüngliche Reihenfolge bei.
Nicht stabil Die Reihenfolge gleicher Werte kann sich ändern.
In-place Sortiert im vorhandenen Array, braucht nur O(1) zusätzlichen Speicher.
O(n) Speicher Benötigt ein zusätzliches Hilfsarray proportional zur Eingabegröße.
Adaptiv Nutzt vorhandene Ordnung aus — bei fast sortierten Daten schneller.
Hybrid Kombiniert mehrere Strategien und wechselt je nach Situation.
O(n²) Zeitkomplexität — beschreibt, wie die Laufzeit mit der Eingabegröße wächst. O(n²) = quadratisch (langsam bei großen Daten), O(n log n) = quasi-linear (effizient), O(n+k) = linear (schnellstmöglich). Stehen zwei Werte (z.B. „O(n²) worst · O(n) best“), beschreibt der erste den schlechtesten, der zweite den besten Fall.

Farbcode der Visualisierung

Orange = Vergleich
Rot = Tausch
Lila = Verschiebung
Grün = Sortiert / Fertig
Blau = Unsortiert

O(n²) — Einfache Verfahren

Bubble Sort

Stabil In-place O(n²)

Funktionsweise: Durchläuft das Array wiederholt von links nach rechts und vergleicht jeweils zwei benachbarte Elemente. Ist das linke Element größer als das rechte, werden sie getauscht. Nach jedem vollständigen Durchlauf „blubbert" das größte noch unsortierte Element an seine endgültige Position am Ende. Das wird so lange wiederholt, bis ein Durchlauf ohne Tausch stattfindet.

Darstellung: Ein orange leuchtendes Paar wandert von links nach rechts — ein geschwungener Bogen über den Balken verbindet die beiden verglichenen Elemente und macht die Paarung auf einen Blick klar. Wird getauscht, werden beide Balken rot und der Bogen wechselt ebenfalls die Farbe. Mit jedem Durchlauf wächst der bereits sortierte Bereich am rechten Rand: er ist grünlich hinterlegt und dehnt sich Schritt für Schritt aus. Unter jedem Balken zeigt eine kleine Zahl den aktuellen Wert. Die Zeile über dem Canvas benennt den aktuellen Schritt (z.B. „Vergleiche arr[3]=42.1 mit arr[4]=17.5").

Wann einsetzen: Hauptsächlich zu Lehrzwecken, da er der intuitivste Sortieralgorithmus ist. Bei fast sortierten Daten kann er mit der „swapped"-Optimierung in O(n) terminieren. Für produktiven Einsatz aber zu langsam — Insertion Sort ist in derselben Komplexitätsklasse stets überlegen.

Selection Sort

Nicht stabil In-place O(n²)

Funktionsweise: Teilt das Array gedanklich in einen sortierten (links) und unsortierten (rechts) Bereich. In jedem Schritt wird das Minimum des unsortierten Bereichs gesucht und mit dem ersten unsortierten Element getauscht. So wächst der sortierte Bereich um eins pro Durchlauf.

Darstellung: Ein oranger Bogen verbindet den aktuellen Minimum-Kandidaten mit dem nächsten Vergleichselement. Wird ein kleineres Element gefunden, springt der Bogen dorthin. Am Ende der Suche setzt ein roter Tausch (roter Bogen) das Minimum an die linke Grenze des unsortierten Bereichs. Die linke Seite des Arrays ist grünlich hinterlegt und wächst pro Durchlauf um genau einen Balken. Kleine Wertemarken unter den Balken erleichtern das Ablesen.

Wann einsetzen: Nützlich wenn die Anzahl der Schreiboperationen (Swaps) minimiert werden soll — Selection Sort führt maximal O(n) Tauschvorgänge aus, unabhängig von den Daten. Relevant z.B. bei Flash-Speicher mit begrenzten Schreibzyklen. Für allgemeine Zwecke ist Insertion Sort vorzuziehen.

Insertion Sort

Stabil In-place Adaptiv O(n²) worst · O(n) best

Funktionsweise: Arbeitet wie das Sortieren von Spielkarten auf der Hand: Nimmt das nächste Element aus dem unsortierten Bereich und schiebt es im bereits sortierten Bereich so lange nach links, bis die richtige Position gefunden ist. Alle größeren Elemente werden dabei um eine Position nach rechts verschoben.

Darstellung: Ein oranger Bogen verbindet das einzufügende Element mit seinem linken Nachbarn. Ist es kleiner, wird es lila nach links verschoben — der Bogen wandert mit. Die lilafarbenen Verschiebungen zeigen, wie das Element schrittweise durch den bereits sortierten (grünlich hinterlegten) Bereich rutscht, bis es seine korrekte Position findet. Kleine Wertemarken unter den Balken helfen beim Verfolgen der Werte.

Wann einsetzen: Der beste O(n²)-Algorithmus in der Praxis. Bei fast sortierten Daten läuft er nahezu in O(n). Wird oft als Basis-Algorithmus in hybriden Verfahren eingesetzt (z.B. Timsort, Introsort), die bei kleinen Teilarrays (n < 16) auf Insertion Sort umschalten, weil sein geringer Overhead den asymptotischen Nachteil wettmacht.

Cocktail Shaker Sort

Stabil In-place O(n²)

Funktionsweise: Eine Variante von Bubble Sort, die abwechselnd in beide Richtungen durchläuft — erst von links nach rechts (große Elemente aufsteigen lassen), dann von rechts nach links (kleine Elemente absinken lassen). Die Grenzen des unsortierten Bereichs werden dabei von beiden Seiten eingeengt.

Darstellung: Ein oranger Bogen wandert abwechselnd nach rechts und nach links — bei einem Tausch wechselt er rot. Links und rechts wächst gleichzeitig je ein grünlich hinterlegter sortierter Bereich, der den unsortierten Mittelteil von beiden Seiten einengt. Die Bogenrichtung macht den Wechsel der Durchlaufrichtung unmittelbar sichtbar.

Wann einsetzen: Löst das sogenannte „Schildkröten-Problem" von Bubble Sort: Kleine Werte am Ende des Arrays wandern bei normalem Bubble Sort nur eine Position pro Durchlauf nach vorne. Durch den Rückwärtsdurchlauf werden sie viel schneller an die richtige Position befördert. Besonders effektiv bei Arrays, die „fast sortiert" sind, aber einzelne Ausreißer in beide Richtungen haben.

O(n log n) — Effiziente Verfahren

Merge Sort

Stabil O(n) Speicher O(n log n) garantiert

Funktionsweise: Klassisches Divide-and-Conquer: Das Array wird rekursiv in zwei Hälften geteilt, bis nur noch Einzelelemente übrig sind. Dann werden die sortierten Hälften schrittweise wieder zusammengeführt (gemergt), indem jeweils das kleinere der beiden vordersten Elemente übernommen wird. Dieser Merge-Schritt ist der Kern des Algorithmus.

Darstellung: Das Phase-Label über dem Canvas zeigt „Merge", sobald zwei Hälften zusammengeführt werden. Ein oranger Bogen verbindet die aktuell verglichenen Elemente aus den beiden Hälften; blaue Klammern am oberen Rand markieren den aktiven Teilbereich. Unterhalb erscheint die Speicher-Ansicht mit den beiden Hilfs-Arrays: links (blau) und rechts (lila) — ein hervorgehobener Balken zeigt den aktuellen Lesezeiger. Lila Verschiebungen im Haupt-Array zeigen, wohin die Elemente geschrieben werden. Kleine Wertemarken unter den Balken helfen, den Überblick zu behalten.

Wann einsetzen: Ideal wenn eine garantierte O(n log n)-Laufzeit und Stabilität erforderlich sind — z.B. beim Sortieren von Datensätzen mit mehreren Schlüsseln oder bei verketteten Listen (dort ohne zusätzlichen Speicher möglich). Bildet die Basis von Pythons Timsort und Javas Arrays.sort() für Objekte. Der zusätzliche O(n)-Speicherbedarf ist der Hauptnachteil gegenüber Quick Sort.

Heap Sort

Nicht stabil In-place O(n log n) garantiert

Funktionsweise: Nutzt die Heap-Datenstruktur (Max-Heap), die direkt im Array repräsentiert wird. Phase 1 (Build-Heap): Das Array wird in O(n) in einen Max-Heap umgewandelt, bei dem jeder Elternknoten größer ist als seine Kinder. Phase 2 (Extract): Das Maximum (Wurzel) wird wiederholt mit dem letzten Element getauscht und der Heap um eins verkleinert. Dann wird die Heap-Eigenschaft durch „Heapify" (Absinken) wiederhergestellt.

Darstellung: Das Phase-Label wechselt sichtbar von „Heap aufbauen" zu „Extrahieren". Ein oranger Bogen verbindet den jeweils verglichenen Eltern- und Kind-Knoten im Array — die weiten Sprünge machen die Baumstruktur im flachen Array erlebbar. Beim Extrahieren wächst der grünlich hinterlegte sortierte Bereich von rechts. Unterhalb erscheint der Max-Heap als Baumdiagramm: Orange hervorgehobene Knoten zeigen den aktuellen Vergleich, der Baum schrumpft nach jedem Extract-Schritt. Kleine Wertemarken unter den Balken helfen, Eltern-Kind-Beziehungen nachzuvollziehen.

Wann einsetzen: Bietet die einzigartige Kombination aus garantierter O(n log n)-Laufzeit und O(1)-Speicher — also echtes In-place ohne zusätzlichen Speicher. Ideal für speicherkritische Systeme oder als Fallback in hybriden Algorithmen (z.B. Introsort wechselt auf Heap Sort, wenn Quick Sorts Rekursionstiefe zu groß wird). In der Praxis langsamer als Quick Sort wegen schlechter Cache-Lokalität (springt weit im Array).

Quick Sort

Nicht stabil In-place O(n log n) avg · O(n²) worst

Funktionsweise: Ebenfalls Divide-and-Conquer, aber anders als Merge Sort: Zuerst wird ein Pivot-Element gewählt. Dann wird das Array so umgeordnet (partitioniert), dass alle Elemente kleiner als der Pivot links stehen und alle größeren rechts. Der Pivot ist danach an seiner endgültigen Position. Dieser Vorgang wird rekursiv auf die beiden Teilarrays angewendet.

Darstellung: Das Phase-Label zeigt „Partition". Das Pivot-Element (letztes Element des Teilarrays) trägt einen weißen Rahmen als Markierung. Blaue Klammern am oberen Rand begrenzen den aktiven Teilbereich. Orange Bögen verbinden den aktuellen Vergleichspartner mit dem Pivot; rote Bögen markieren Tausche. Sobald der Pivot an seine endgültige Position gesetzt wird, beginnt das Muster in einem kleineren Teilbereich von vorn — so wird der Divide-and-Conquer-Charakter visuell greifbar.

Wann einsetzen: In der Praxis meistens der schnellste vergleichsbasierte Algorithmus, weil er hervorragende Cache-Lokalität hat (arbeitet sequentiell im Speicher). Wird in C's qsort(), Javas Arrays.sort() für Primitives und vielen Standard-Libraries eingesetzt. Die O(n²)-Worst-Case-Laufzeit tritt bei ungünstiger Pivot-Wahl auf (z.B. bereits sortiertes Array mit erstem Element als Pivot). Randomisierte oder Median-of-Three-Pivot-Wahl eliminiert dieses Problem praktisch.

3-Way Quick Sort

Nicht stabil In-place Duplikateneffizient O(n log n) avg · O(n) bei vielen Duplikaten

Funktionsweise: Auch bekannt als „Dutch National Flag"-Algorithmus (Dijkstra). Im Gegensatz zum klassischen Quick Sort, der zwei Bereiche erzeugt (< Pivot und > Pivot), teilt diese Variante das Array in drei Bereiche: Elemente kleiner als der Pivot (links), gleich dem Pivot (Mitte) und größer als der Pivot (rechts). Alle Duplikate des Pivots landen sofort in der Mitte und werden nie wieder verglichen. Dadurch wird das Problem vieler gleicher Werte elegant gelöst — klassischer Quick Sort degeneriert dabei zu O(n²).

Darstellung: Drei farbige Hintergrundbereiche machen die Dreiteilung sichtbar: links (blau) Elemente kleiner als Pivot, Mitte (orange) gleich dem Pivot, rechts (lila) größer als Pivot. Orange Bögen zeigen Vergleiche gegen den Pivot; rote Bögen markieren Tausche, die Elemente in den richtigen Bereich befördern. Der mittlere Gleichheits-Bereich wächst bei Duplikaten spürbar schnell — er wird bei der Rekursion komplett übersprungen.

Wann einsetzen: Immer wenn die Daten viele Duplikate enthalten — z.B. beim Sortieren nach Ländercodes, Booleschen Werten, Altersgruppen oder Bewertungsstufen. Klassischer Quick Sort braucht bei n identischen Elementen O(n²), 3-Way Quick Sort nur O(n). Die Median-of-Three-Pivot-Wahl verhindert zusätzlich den Worst Case bei bereits sortierten Daten.

Dual-Pivot Quick Sort

Nicht stabil In-place Java Standard O(n log n) avg

Funktionsweise: Entwickelt von Vladimir Yaroslavskiy (2009), seit Java 7 der Standard-Algorithmus für Arrays.sort() bei primitiven Typen. Verwendet zwei Pivot-Elemente (P1 ≤ P2) und teilt das Array in drei Bereiche: Elemente < P1 (links), Elemente zwischen P1 und P2 (Mitte), Elemente > P2 (rechts). Die drei Bereiche werden dann rekursiv sortiert. Durch die feinere Aufteilung werden die Teilarrays kleiner als bei einfachem Quick Sort.

Darstellung: Beide Pivot-Elemente (P1 links, P2 rechts) tragen einen weißen Rahmen. Blaue Klammern markieren den aktiven Teilbereich. Drei farbige Hintergrundbereiche entstehen schrittweise: links (blau) kleiner P1, Mitte (orange) zwischen P1 und P2, rechts (lila) größer P2. Orange Bögen zeigen Vergleiche, rote Bögen die Tausche in die richtigen Bereiche. Dass der aktive Bereich sich durch die Dreiteilung deutlich schneller verkleinert als beim klassischen Quick Sort, ist am Fortschrittsbalken ablesbar.

Wann einsetzen: Der Industriestandard in Java für primitive Typen — in der Praxis oft 10–20 % schneller als klassischer Quick Sort, weil die feinere Partitionierung die Cache-Ausnutzung verbessert. Besonders effektiv bei großen Arrays mit gleichmäßig verteilten Werten. Die Implementierung ist komplexer als klassischer Quick Sort, lohnt sich aber bei performancekritischen Anwendungen.

Introsort

Nicht stabil In-place Hybrid C++/Rust Standard O(n log n) garantiert

Funktionsweise: Ein hybrider Algorithmus (David Musser, 1997), der das Beste dreier Welten kombiniert: Er startet als Quick Sort mit Median-of-Three-Pivot für die durchschnittlich beste Performance. Überschreitet die Rekursionstiefe 2·log₂(n), wechselt er auf Heap Sort — das garantiert O(n log n) auch im Worst Case. Für kleine Teilarrays (≤ 16 Elemente) wird Insertion Sort verwendet, da dieser bei wenigen Elementen wegen geringerem Overhead schneller ist. So wird Quick Sorts O(n²)-Schwäche eliminiert, ohne auf seine Durchschnitts-Performance zu verzichten.

Darstellung: Das Phase-Label über dem Canvas verrät stets, welche Strategie gerade aktiv ist: „Quick Sort" bei der Partitionierung (Pivot mit weißem Rahmen, blaue Bereichsklammern, orange/rote Bögen), „Insertion Sort" bei kleinen Teilarrays ≤ 16 (lila Verschiebungen benachbarter Elemente ohne Pivot), „Heap Sort (Fallback)" wenn die Rekursionstiefe überschritten wird (weite Sprünge, kein Pivot-Marker). Dieser automatische Strategiewechsel, der in der Phase-Anzeige direkt ablesbar ist, macht Introsort visuell einzigartig unter allen hier gezeigten Algorithmen.

Wann einsetzen: Der Standard-Algorithmus in C++ (std::sort), Rust (slice::sort_unstable) und vielen weiteren Systemen. Introsort ist die Antwort auf die Frage „Welchen Algorithmus nehme ich, wenn ich nicht weiß, wie die Daten aussehen?" — er ist universell einsetzbar mit garantierter O(n log n)-Laufzeit und minimalem Speicherbedarf. Zusammen mit Timsort (Python, Java für Objekte) deckt er die beiden wichtigsten Industrie-Standards ab.

Shell Sort

Nicht stabil In-place Adaptiv O(n log²n) mit Knuth

Funktionsweise: Eine Verallgemeinerung von Insertion Sort. Statt nur benachbarte Elemente zu vergleichen, werden zunächst weit auseinanderliegende Elemente verglichen und sortiert (mit großem „Gap"). Der Gap wird schrittweise verkleinert (hier nach Knuth: ..., 40, 13, 4, 1). In jeder Runde wird ein Insertion Sort auf die Elemente mit dem jeweiligen Abstand ausgeführt. Beim letzten Durchlauf (Gap=1) ist es ein normaler Insertion Sort — aber auf fast sortierte Daten, was ihn extrem schnell macht.

Darstellung: Oben rechts im Canvas zeigt eine Beschriftung den aktuellen Gap-Wert. Zu Beginn überspannen die orangen Bögen weite Distanzen — ein großer Gap bedeutet, dass weit auseinanderliegende Balken verglichen werden. Mit jedem Durchlauf schrumpft der Gap (und damit die Bogenlänge) sichtbar: 40 → 13 → 4 → 1. Im letzten Durchlauf (Gap=1) sind die Bögen kurz wie bei Insertion Sort — aber die Daten sind bereits so gut vorsortiert, dass kaum noch lila Verschiebungen nötig sind.

Wann einsetzen: Ideal wenn ein einfacher, rekursionsfreier Algorithmus benötigt wird, der deutlich besser als O(n²) performt. Kein Stack-Overhead, wenig Code, exzellente Cache-Lokalität. Wird häufig in Embedded Systems und in der Linux-Kernel-Implementierung verwendet. Die exakte Komplexität hängt von der Gap-Sequenz ab — kein Beweis für eine optimale Folge ist bekannt, was Shell Sort theoretisch besonders interessant macht.

Tree Sort (BST)

Stabil (bei gleichen rechts) O(n) Speicher Baumbasiert O(n log n) avg · O(n²) worst

Funktionsweise: Baut einen binären Suchbaum (BST) auf, indem jedes Array-Element nacheinander eingefügt wird. Im BST gilt: Alle Werte im linken Teilbaum eines Knotens sind kleiner, alle im rechten sind größer oder gleich. Zum Einfügen wird der Baum von der Wurzel abwärts durchlaufen — bei jedem Knoten wird entschieden, ob links oder rechts weitergesucht wird. Nach dem Aufbau werden die Elemente durch eine In-Order-Traversierung (links → Knoten → rechts) in sortierter Reihenfolge zurück ins Array geschrieben.

Darstellung: Oben wird das aktuelle Array-Element lila hervorgehoben, das gerade in den Baum eingefügt wird. Unterhalb wächst der Binäre Suchbaum Knoten für Knoten — der orange leuchtende Pfad zeigt die Suchroute von der Wurzel bis zur Einfügeposition. In der zweiten Phase (In-Order-Traversal) werden die Knoten nacheinander orange markiert und ihre Werte lila ins Haupt-Array zurückgeschrieben. Die Schritt-Erklärung über dem Canvas gibt bei jeder Verschiebung die genaue Zielposition an.

Wann einsetzen: Zeigt den fundamentalen Zusammenhang zwischen Datenstrukturen und Sortieren — ein BST ist im Kern ein „lebendiger" Sortieralgorithmus. Bei balancierten Daten O(n log n), aber bei bereits sortierten Eingaben degeneriert der Baum zu einer linearen Kette → O(n²). Selbstbalancierende Bäume (AVL, Rot-Schwarz) lösen dieses Problem, sind aber komplexer. In der Praxis wird Tree Sort selten direkt verwendet, aber das Verständnis ist essentiell für Datenbanken (B-Bäume), Sets und Maps.

Timsort

Stabil Adaptiv Hybrid O(n) Speicher O(n log n) garantiert

Funktionsweise: Vereint das Beste aus Insertion Sort und Merge Sort. Phase 1: Das Array wird in „Runs" (Teilstücke der Größe 32) aufgeteilt und jeder Run mit Insertion Sort sortiert — das ist bei kleinen Datenmengen schneller als Merge Sort wegen geringerem Overhead. Phase 2: Die sortierten Runs werden dann bottom-up mit einem optimierten Merge-Verfahren zusammengeführt, wobei die Run-Größe in jeder Runde verdoppelt wird (32 → 64 → 128 → ...). Die echte Timsort-Implementierung erkennt zusätzlich natürlich vorhandene sortierte Teilstücke (natürliche Runs) und nutzt sie aus.

Darstellung: Das Phase-Label wechselt zwischen den beiden Phasen: In Phase 1 sehen Sie nur das Haupt-Array mit kurzen orangen Bögen und lila Verschiebungen innerhalb kleiner 32-Elemente-Blöcke (Insertion Sort). Dünne vertikale Linien im Balkendiagramm markieren die Run-Grenzen und machen sichtbar, wie das Array in sortierte Blöcke aufgeteilt wird. Sobald Phase 2 beginnt, erscheint die Speicher-Ansicht mit den Hilfs-Arrays (blau links, lila rechts) — orangere Bögen über größere Distanzen zeigen, wie die Blöcke von 32 auf 64, 128 usw. anwachsen.

Wann einsetzen: Der Standard-Sortieralgorithmus in Python (seit 2002), Java (Arrays.sort für Objekte), Android, Swift und V8 (JavaScript-Engine von Chrome). Wurde von Tim Peters speziell für reale Daten entwickelt, die oft bereits teilweise sortiert sind. Bei fast sortierten Daten läuft Timsort nahezu in O(n), bei zufälligen Daten zuverlässig in O(n log n). Wenn man nur einen einzigen Algorithmus kennen sollte, der „in der echten Welt" verwendet wird, ist es Timsort.

O(n·k) — Nicht-vergleichsbasiert

Counting Sort

Stabil O(n + k) Speicher O(n + k)

Funktionsweise: Durchbricht die theoretische Untergrenze O(n log n) für vergleichsbasierte Verfahren, indem er gar nicht vergleicht. Stattdessen wird ein Hilfsarray (Größe k = Wertebereich) angelegt und für jeden Wert gezählt, wie oft er vorkommt. Aus den Häufigkeiten lässt sich direkt die sortierte Reihenfolge ableiten: Jeder Wert wird entsprechend seiner Häufigkeit zurückgeschrieben.

Darstellung: Oben werden Elemente lila hervorgehoben, wenn sie gezählt bzw. zurückgeschrieben werden — da Counting Sort nicht vergleicht, gibt es keine orangen Bögen. Unterhalb erscheint das Häufigkeits-Array als grünes Balkendiagramm: Jeder Balken repräsentiert einen Wert, die Höhe zeigt die Häufigkeit. Der aktuell bearbeitete Wert leuchtet lila. Beim Zurückschreiben schrumpfen die Häufigkeitsbalken, während das Haupt-Array von links nach rechts sortiert befüllt wird. Kleine Wertemarken unter den Balken zeigen die ganzzahligen Werte, auf die die Eingabe intern gerundet wird.

Wann einsetzen: Extrem schnell wenn der Wertebereich k klein ist relativ zu n (z.B. Noten 1–6, Alter 0–150, Buchstaben). Wird linear langsamer wenn k wächst — bei k ≫ n ist Counting Sort ineffizienter als vergleichsbasierte Verfahren. Dient als stabile Unterroutine in Radix Sort. Kann nur ganzzahlige oder diskrete Werte sortieren.

Radix Sort (LSD)

Stabil O(n + k) Speicher O(d · (n + k))

Funktionsweise: Sortiert Zahlen stellenweise, beginnend bei der niederwertigsten Stelle (Least Significant Digit, LSD). In jeder Runde wird ein stabiler Sortieralgorithmus (hier Counting Sort mit Basis k=10) auf eine einzelne Dezimalstelle angewendet. Durch die Stabilität bleiben die Ergebnisse vorheriger Runden erhalten. Nach d Runden (d = Anzahl der Stellen der größten Zahl) ist das gesamte Array sortiert.

Darstellung: Das Phase-Label zeigt die aktuelle Stelle und Richtung, z.B. „Stelle 1 — Verteilen" und „Stelle 1 — Sammeln". Oben werden Elemente lila markiert (kein Vergleich → kein Bogen). Unterhalb zeigt die Speicher-Ansicht die 10 Radix-Buckets (Ziffern 0–9) als Spalten mit gestapelten Blöcken — jeder Block enthält den Zahlenwert. Der aktive Bucket leuchtet lila. Pro Stellendurchlauf füllen sich die Buckets und werden anschließend der Reihe nach ins Array zurückgeschrieben. Da intern mit ganzen Zahlen gearbeitet wird, zeigen die Wertemarken gerundete Werte.

Wann einsetzen: Schlägt vergleichsbasierte Verfahren wenn die Zahl der Stellen d konstant oder klein ist — z.B. Postleitzahlen (5-stellig), IP-Adressen, Telefonnummern, Datums-Timestamps. Die effektive Laufzeit ist dann O(n). Kann auch auf Strings gleicher Länge angewandt werden (zeichenweises Sortieren). Nicht geeignet für Fließkommazahlen oder stark variierende Schlüssellängen.

Bucket Sort

Stabil (bei stabilem Sub-Sort) O(n + k) Speicher O(n + k) avg · O(n²) worst

Funktionsweise: Teilt den Wertebereich in eine Anzahl gleich großer „Eimer" (Buckets) auf. Jedes Element wird anhand seines Wertes in den passenden Eimer einsortiert. Dann wird jeder Eimer einzeln sortiert (hier mit Insertion Sort, da die Eimer typischerweise klein sind). Zuletzt werden die Eimer der Reihe nach zusammengefügt. Die Anzahl der Buckets wird hier als √n gewählt.

Darstellung: Oben wird jedes Element lila markiert, wenn es in einen Bucket verteilt oder ins Array zurückgeschrieben wird (kein Vergleich → kein Bogen). Unterhalb zeigt die Speicher-Ansicht die k Buckets als Rahmen mit Balken darin — die Balkenhöhe entspricht dem Wert des Elements. Der aktive Bucket leuchtet lila. Sie sehen, wie sich die Elemente auf die Buckets verteilen, und beim Zurückschreiben, wie ein gleichmäßig befülltes Array entsteht. Kleine Wertemarken unter den Balken zeigen Fließkommazahlen, die direkt in Buckets einsortiert werden.

Wann einsetzen: Am effizientesten wenn die Eingabedaten gleichmäßig über den Wertebereich verteilt sind — dann enthält jeder Bucket nur wenige Elemente und der Gesamt-Aufwand ist O(n). Ideal für Fließkommazahlen im Bereich [0, 1), Prüfungsnoten, Messwerte mit bekanntem Bereich. Wenn alle Elemente in denselben Bucket fallen (z.B. viele identische Werte), degeneriert Bucket Sort zum Sub-Sort-Algorithmus. Konzeptionell das intuitivste nicht-vergleichsbasierte Verfahren — man denkt automatisch an Schubladen oder Fächer.

Spezial — Ungewöhnliche Verfahren

Pancake Sort

Nicht stabil In-place O(n²)

Funktionsweise: Die einzige erlaubte Operation ist ein „Präfix-Flip": Man schiebt einen Pfannenwender an einer beliebigen Stelle unter den Pfannkuchenstapel und dreht alles darüber um. Das Verfahren arbeitet von hinten nach vorne: In jedem Schritt wird das Maximum im unsortierten Bereich gefunden. Dann wird zuerst ein Flip bis zu diesem Maximum ausgeführt (Maximum landet ganz vorne), dann ein Flip bis zur Endposition (Maximum landet an der richtigen Stelle). So wandert pro Runde ein Element an seine endgültige Position.

Darstellung: Zuerst wandert ein oranger Bogen durch den unsortierten Bereich auf der Suche nach dem Maximum. Dann folgt ein spektakulärer Flip: Mehrere Balken werden gleichzeitig rot — ein ganzer Präfix des Arrays wird auf einmal umgekehrt. Zwei solcher Flips pro Runde erzeugen das charakteristische Doppel-Umkehrmuster: erst bringt ein Flip das Maximum nach ganz links, dann schiebt ein zweiter es an seine Zielposition am rechten Ende des unsortierten Bereichs.

Wann einsetzen: Löst ein berühmtes kombinatorisches Problem: „Wie viele Flips braucht man im schlimmsten Fall, um n Pfannkuchen zu sortieren?" (Pancake-Zahl). Bill Gates' erste wissenschaftliche Veröffentlichung (1979) bewies eine obere Schranke dafür. Praxisrelevant in der Bioinformatik: Genom-Umordnungen (Inversionen von DNA-Segmenten) entsprechen exakt Pancake-Flips. Auch in der Robotik relevant, wenn ein Roboter nur „Umdreh"-Operationen ausführen kann. Visuell besonders eindrucksvoll, weil die Flips ganze Abschnitte auf einmal umkehren.

Cycle Sort

Nicht stabil In-place Min. Schreibops O(n²)

Funktionsweise: Basiert auf der Zerlegung einer Permutation in Zyklen. Für jedes Element wird berechnet, wo es in der sortierten Reihenfolge stehen müsste (durch Zählen aller kleineren Elemente). Dann wird es dorthin verschoben, wobei das verdrängte Element aufgenommen und ebenfalls an seine korrekte Position gebracht wird — bis der Zyklus sich schließt (man wieder am Startpunkt ankommt). Jedes Element wird dabei höchstens einmal an seine endgültige Position geschrieben.

Darstellung: Ein langer Scan: Viele orange Bögen erscheinen nacheinander, während der Algorithmus zählt, wie viele Elemente kleiner als das aktuelle sind. Dann folgt eine einzelne lila Verschiebung — das Element springt direkt an seine berechnete Zielposition, ohne einen Umweg. Dieser Wechsel aus vielen kurzen Bögen (Zählphase) und einem einzigen punktuellen Schreibvorgang macht die Eigenheit von Cycle Sort unmittelbar erlebbar: O(n²) Vergleiche für minimale Schreiboperationen. Bereits an ihrer Zielposition stehende Elemente sind grünlich hinterlegt; die Wertemarken unter den Balken helfen, die berechneten Zielpositionen nachzuvollziehen.

Wann einsetzen: Der einzige Sortieralgorithmus, der die theoretisch minimale Anzahl an Schreiboperationen garantiert. Jedes Element wird höchstens einmal geschrieben (statt mehrfach verschoben wie bei anderen Algorithmen). Essenziell bei EEPROM oder Flash-Speicher, wo jeder Schreibvorgang den Speicher abnutzt und die Lebensdauer verkürzt. Auch nützlich zum Erkennen, ob eine Permutation aus einem einzigen Zyklus besteht. Die vielen Vergleiche (O(n²)) sind der Preis für die minimalen Schreiboperationen.

Bogo Sort

Nicht stabil In-place Max. 8 Elemente O(n · n!) erwartet

Funktionsweise: Der „dümmste" Sortieralgorithmus: Das Array wird zufällig gemischt (Fisher-Yates-Shuffle), dann wird geprüft, ob es jetzt zufällig sortiert ist. Wenn nicht, wird erneut gemischt. Das wird wiederholt, bis das Array durch Zufall in der richtigen Reihenfolge landet. Es gibt keine Garantie, dass das jemals passiert — im Erwartungswert braucht man n! Versuche (bei n = 8 sind das 40.320 Mischvorgänge).

Darstellung: Bogo Sort erzeugt ein hektisches Blitz-Muster: Das gesamte Array blinkt rot auf (Shuffle), dann wandern kurze orange Bögen von links nach rechts durch das Array (Sortiertheitscheck). Scheitert die Prüfung, folgt sofort der nächste rote Shuffle. Die kleinen Wertemarken unter den Balken zeigen bei jedem Shuffle-Versuch eine neue zufällige Anordnung. Der Fortschrittsbalken bewegt sich kaum — tausende Schritte bei nur 8 Elementen zeigen eindrücklich, wie nutzlos rein zufälliges Probieren ist. Die Array-Größe ist automatisch auf 8 begrenzt.

Wann einsetzen: Niemals in der Praxis. Bogo Sort dient als Lehr- und Abschreckungsbeispiel: Er zeigt eindrücklich, warum zufälliges Probieren exponentiell schlecht skaliert. Bei nur 8 Elementen braucht er im Schnitt ~40.000 Versuche, bei 10 Elementen schon ~3,6 Millionen. Der Name ist ein Wortspiel auf „bogus" (falsch/wertlos). In der theoretischen Informatik dient er als Referenz für die schlechteste denkbare Komplexitätsklasse. Die Array-Größe wird hier automatisch auf 8 begrenzt, um den Browser nicht einzufrieren.

Fisher-Yates Shuffle

Stabil In-place O(n) Zeit · O(1) Speicher

Funktionsweise: Der Fisher-Yates-Algorithmus (auch Knuth-Shuffle) mischt ein Array uniform zufällig. Er läuft rückwärts: Für jede Position i wird ein zufälliger Index j zwischen 0 und i gewählt und die beiden Elemente getauscht. Jede der n! Permutationen wird mit gleicher Wahrscheinlichkeit erzeugt.

Darstellung: Rote Bögen zeigen jeden Tausch — keine Vergleiche, nur Tausche. Die Anzahl der Tausche ist immer n-1 (bei n Elementen). Das macht die Effizienz des Mischens im Vergleich zum Sortieren direkt sichtbar.

Wann einsetzen: Zum Erzeugen von Testdaten, zum „Nochmal-Mischen" eines sortierten Arrays, oder als Gegenbeweis: Ein einziger Shuffle macht jede Sortierung rückgängig. Mischen ist O(n), Sortieren ist O(n log n) — also ist Mischen immer schneller als Sortieren.