Komplexität: zwei Gesichter
| Fall | Komplexität | Wann? |
|---|
| Best Case | O(n log n) | Pivot landet immer in der Mitte |
| Average Case | O(n log n) | Zufällige Eingabe |
| Worst Case | O(n²) | Pivot ist immer das Min/Max |
Worst Case in der Praxis: sortierter oder umgekehrt sortierter Input mit naiver Pivot-Wahl (immer letztes Element). Dann partitioniert Lomuto in 0 + (n-1) statt in zwei Hälften, und der Rekursionsstack wird O(n) tief. Genau gerechnet: (n-1) + (n-2) + dots + 1 = n(n-1)/2 Vergleiche, also ≈ n²/2.
Lösung: Randomisierte Pivot-Wahl liefert erwartete Laufzeit O(n log n), der Worst Case bleibt theoretisch möglich, ist in der Praxis aber sehr unwahrscheinlich. Median-of-Three (Median aus erstem, mittlerem und letztem Element) reduziert typische schlechte Muster wie sortierten Input, garantiert aber allein keinen O(n log n)-Worst-Case.
Eigenschaften
- ✅ In-Place bezüglich Array. Rekursionsstack:
O(log n) im Average/Best Case, O(n) im Worst Case beim Lomuto-Schema. Mit Tail-Call-Optimierung und "rekursiv zuerst auf die kleinere Partition" lässt sich der Stack auf O(log n) begrenzen.
- ✅ In der Praxis schnell: oft schneller als Mergesort, vor allem wegen guter Cache-Lokalität. Der konkrete Faktor hängt von Implementierung, Daten und Hardware ab.
- ❌ Nicht stabil: Partitionierung kann gleiche Werte vertauschen
- ❌ Worst Case O(n²): wenn nicht abgesichert
Wann sinnvoll?
In der Praxis sehr verbreitet: wenn Stabilität nicht wichtig ist. Einige Standardbibliotheken nutzen Quicksort-Varianten oder hybride Verfahren, nicht "die meisten Sprachen", aber prominente Beispiele:
Praxis-Hinweis (nicht durch ALGORITHMS-Trusted-Sources gedeckt, aber gut zu wissen):
- Java:
Arrays.sort(int[]) und andere primitive Arrays nutzen Dual-Pivot Quicksort. Arrays.sort(Object[]) nutzt dagegen ein stabiles, adaptives Mergesort/Timsort-artiges Verfahren. Quelle: OpenJDK-Doku.
- C++:
std::sort ist kein naiver Quicksort, sondern typischerweise Introsort (Quicksort + Fallback auf Heapsort bei drohendem n²-Verhalten). Dadurch wird O(n log n) im Worst Case garantiert. Quelle: ISO-C++-Standard-Komplexitätsanforderung an std::sort.
Im Sortier-Vergleich-Topic kannst du selbst sehen wie Quicksort bei sortiertem Input ins quadratische Verhalten abrutscht.