Sortieralgorithmen
Bubblesort
Idee
Vergleiche immer zwei Nachbarn und tausche sie, wenn der größere links steht. Nach einem Durchlauf ist der größte Wert ganz rechts angekommen, nach dem zweiten der zweitgrößte, und so weiter.
für i von 0 bis n − 2:getauscht ← falschfür j von 0 bis n − 2 − i:wenn A[j] > A[j + 1]:tausche A[j] und A[j + 1]; getauscht ← wahrA[n − 1 − i] steht jetzt endgültigwenn nicht getauscht: fertig
Laufzeit
- Bester Fall
- Im Mittel
- Schlechtester Fall
- Stabil
- ja
- Gleiche Werte behalten ihre Reihenfolge.
- Hilfsfeld
- nein
- Es wird im Feld selbst gearbeitet.
Wie man darauf kommt
Im Durchlauf (gezählt ab 0) werden Nachbarpaare verglichen. Ohne vorzeitigen Abbruch sind das zusammen Vergleiche.
Jede Vertauschung zweier Nachbarn beseitigt genau einen Fehlstand. Deshalb ist die Zahl der Vertauschungen gleich der Zahl der Fehlstände: im schlechtesten Fall , im Mittel die Hälfte davon.
Ist die Eingabe schon sortiert, genügt ein Durchlauf mit Vergleichen und ohne Vertauschung.
Der Reiter „Alle Verfahren im Vergleich“ zeigt: Bubblesort braucht genau so viele Vertauschungen, wie die Eingabe Fehlstände hat.
Mehr zu Bubblesort
Was immer gilt
Nach dem k-ten Durchlauf stehen die k größten Werte in der richtigen Reihenfolge ganz rechts, auf den Stellen bis .
Warum es richtig sortiert
Sobald ein Durchlauf beim größten Wert des unsortierten Teils ankommt, gewinnt dieser jeden weiteren Vergleich und wird bis ans Ende mitgenommen. Nach höchstens Durchläufen steht also alles am Platz. Gibt es in einem Durchlauf keine einzige Vertauschung, steht jedes Nachbarpaar richtig herum; dann ist das ganze Feld sortiert, und man darf aufhören.
Zusatzspeicher
Nur ein paar Hilfsvariablen
Wofür es sich eignet
- Zum Lernen: Idee und Korrektheit sind sofort einsichtig.
- Fast sortierte, sehr kurze Listen, dank des vorzeitigen Abbruchs.
Typische Fehler
- Ohne den Merker „getauscht“ läuft Bubblesort auch über eine sortierte Liste alle Durchläufe.
- Kleine Werte ganz hinten wandern pro Durchlauf nur eine Stelle nach vorn („Schildkröten“). Shellsort behebt genau das.
Grundbegriffe
- Feld A und Stellen
- Die Zahlen stehen in einem Feld A. Die Stellen werden ab 0 gezählt: ist die erste Zahl, die letzte, wobei die Anzahl der Zahlen ist. meint die Stellen von bis einschließlich; lo und hi stehen für den unteren und den oberen Rand eines Bereichs.
- Schreibweise im Pseudocode
- Pseudocode beschreibt ein Verfahren in Worten, die einer Programmiersprache ähneln. heißt: x bekommt den Wert 5. ist x abgerundet auf eine ganze Zahl, etwa . ist der Rest beim Teilen, etwa .
- Vergleich, Vertauschung, Schreibzugriff
- Ein Vergleich prüft, welcher von zwei Werten größer ist. Ein Schreibzugriff setzt einen einzelnen Wert in eine Zelle, egal ob im Feld A, in einem Hilfsfeld B, in einem Zählfeld oder in einem Eimer. Bei einer Vertauschung tauschen zwei Stellen ihren Inhalt; das sind zwei Schreibzugriffe. Die Arbeit eines Verfahrens ist hier die Summe aus Vergleichen und Schreibzugriffen. So lassen sich tauschende und zurückschreibende Verfahren gerecht vergleichen.
- Fehlstand
- Ein Fehlstand (Inversion) ist ein Paar von Stellen mit : Der größere Wert steht vorne. Ein sortiertes Feld hat keinen Fehlstand, ein absteigendes hat alle möglichen. Wer nur Nachbarn tauscht, behebt pro Tausch genau einen Fehlstand.
- Logarithmus
- ist, wie oft man halbieren kann, bis 1 übrig bleibt: , weil . Genauer ist es die Zahl, mit der man 2 potenzieren muss, um zu erhalten: . Er wächst sehr langsam: , . Steht hier nur , ist gemeint.
- Wachstum: O, Θ und Ω
- Man fragt nicht nach der genauen Zahl der Schritte, sondern wie sie wächst, wenn größer wird. heißt: Ab einem gewissen ist höchstens ein festes Vielfaches von , also . ist dieselbe Aussage nach unten (mindestens), beides zusammen: wächst genau wie . Beispiel: . Doppelt so viele Zahlen heißt dann etwa viermal so viel Arbeit; bei nur gut doppelt so viel. Die Basis des Logarithmus spielt dabei keine Rolle, weil sich Logarithmen zu verschiedenen Basen nur um einen festen Faktor unterscheiden.
- Bester, mittlerer und schlechtester Fall
- Dieselbe Anzahl von Zahlen kann je nach Anordnung unterschiedlich viel Arbeit kosten. Der schlechteste Fall ist die teuerste Anordnung, der beste die billigste. Der mittlere Fall ist der Durchschnitt über alle Anordnungen, wenn jede gleich wahrscheinlich ist.
- Invariante
- Eine Invariante ist eine Aussage, die vor und nach jedem Durchlauf einer Schleife gilt, etwa „die ersten k Stellen sind sortiert“. Gilt sie am Anfang, bleibt sie bei jedem Durchlauf erhalten und folgt aus ihr am Ende „alles ist sortiert“, dann ist das Verfahren korrekt. So beweist man Sortierverfahren.
- Rekursion
- Ein Verfahren arbeitet rekursiv, wenn es sich selbst für ein kleineres Stück derselben Aufgabe aufruft. Mergesort sortiert ein Feld, indem es beide Hälften sortiert, jede wieder durch Sortieren ihrer Hälften, bis nur noch einzelne Zahlen übrig sind, die schon sortiert sind. Der Aufrufbaum zeigt, welcher Aufruf welche weiteren gestartet hat.
- Stabil
- Ein Verfahren ist stabil, wenn gleiche Werte ihre ursprüngliche Reihenfolge behalten. Das zählt, wenn Datensätze nach mehreren Merkmalen nacheinander sortiert werden, etwa erst nach Name und dann nach Note: Ein stabiles Verfahren lässt Schüler mit gleicher Note alphabetisch stehen. Im Tool tragen gleiche Werte Kennbuchstaben, und am Ende steht eine Stabilitätsprüfung.
- In place
- Ein Verfahren arbeitet in place, wenn es außer dem Feld selbst nur wenige einzelne Hilfsvariablen braucht, also zusätzlichen Speicher, der nicht mit wächst (oder höchstens wie ). Mergesort braucht dagegen ein zweites Feld derselben Größe.
- Untere Schranke für vergleichende Verfahren
- Kein Verfahren, das nur durch Vergleiche zweier Werte sortiert, kommt im schlechtesten Fall mit weniger als etwa Vergleichen aus. Die Idee: Es gibt mögliche Anordnungen von verschiedenen Zahlen, und das Verfahren muss jede von jeder anderen unterscheiden. Jeder Vergleich hat nur zwei Ausgänge; nach Vergleichen lassen sich also höchstens Fälle auseinanderhalten. Aus folgt . Mergesort und Heapsort erreichen diese Schranke bis auf einen festen Faktor. Countingsort, Radixsort und Bucketsort umgehen sie, weil sie den Wert selbst als Adresse benutzen statt nur zu vergleichen.
- Was Programmiersprachen wirklich benutzen
- Bibliotheken kombinieren mehrere Verfahren. Timsort (Python, Java für Objekte) sucht bereits sortierte Stücke in der Eingabe, verlängert kurze mit Insertionsort und mischt sie wie Mergesort; es ist stabil und auf fast sortierten Daten sehr schnell. Introsort (verbreitet in C++) beginnt mit Quicksort, wechselt zu Heapsort, wenn die Rekursion zu tief wird, und erledigt kleine Stücke mit Insertionsort; so bleibt der schlechteste Fall bei . Pdqsort (Go, und Grundlage der instabilen Sortierung in Rust) ist ein Quicksort, der Muster wie sortierte oder viele gleiche Werte erkennt.
Mehr Theorie: Kapitel „Sortieralgorithmen“ im Uni-Bereich.