Was ist Stabilität bei Sortieralgorithmen und warum ist sie wichtig?

292

Ich bin sehr gespannt, warum Stabilität beim Sortieren von Algorithmen wichtig ist oder nicht.

Darth Vader
quelle
2
Für Parallelisierungszwecke? Beispiel: Merge Sort ist stabil und kann gut parallelisiert werden, ebenso wie Quicksort.
DarthVader
13
Classic QuickSort ist instabil
Konstantin Spirin
9
stabile sort algo -IBM (Insertion, Bubble, Merge)
roottraveller
Ein Hinweis für diejenigen, die das Konzept wie mich missverstanden haben könnten: Die Reihenfolge gleicher Elemente bleibt garantiert erhalten. bedeutet: Wenn die Elemente in stabiler Sortierung als gleich angesehen werden, folgen sie der vorherigen Reihenfolge. Es ist nicht das, was ich früher gedacht habe: Wenn die Elemente in der vorherigen Reihenfolge als gleich angesehen werden, würden sie in der kommenden stabilen Sortierung der vorherigen Reihenfolge folgen. Obwohl Sie vielleicht feststellen, dass das letztere Verständnis in vielen Fällen auch Sinn macht.
Rick

Antworten:

371

Ein Sortieralgorithmus gilt als stabil, wenn zwei Objekte mit gleichen Schlüsseln in der sortierten Ausgabe in derselben Reihenfolge erscheinen wie im zu sortierenden Eingabearray. Einige Sortieralgorithmen wie Insertion Sort, Merge Sort, Bubble Sort usw. sind von Natur aus stabil. Einige Sortieralgorithmen wie Heap Sort, Quick Sort usw. sind dies nicht.

Hintergrund : Ein "stabiler" Sortieralgorithmus hält die Elemente mit demselben Sortierschlüssel in der richtigen Reihenfolge. Angenommen, wir haben eine Liste mit Wörtern aus 5 Buchstaben:

peach
straw
apple
spork

Wenn wir die Liste nur nach dem ersten Buchstaben jedes Wortes sortieren, ergibt eine stabile Sortierung:

apple
peach
straw
spork

In einem instabilen Sortieralgorithmus strawoder sporkkönnen ausgetauscht werden, aber in einem stabilen bleiben sie an den gleichen relativen Positionen (das heißt, da sie strawzuvor sporkin der Eingabe erscheinen, erscheinen sie auch vorher sporkin der Ausgabe).

Wir könnten die Liste der Wörter mit diesem Algorithmus sortieren: stabile Sortierung nach Spalte 5, dann 4, dann 3, dann 2, dann 1. Am Ende wird sie korrekt sortiert. Überzeugen Sie sich davon. (Dieser Algorithmus heißt übrigens Radix-Sortierung)

Angenommen, wir haben eine Liste mit Vor- und Nachnamen, um Ihre Frage zu beantworten. Wir werden gebeten, "nach Nachnamen, dann nach Vornamen" zu sortieren. Wir könnten zuerst (stabil oder instabil) nach dem Vornamen und dann stabil nach dem Nachnamen sortieren. Nach diesen Sortierungen wird die Liste hauptsächlich nach dem Nachnamen sortiert. Wenn jedoch die Nachnamen identisch sind, werden die Vornamen sortiert.

Sie können instabile Sortierungen nicht auf dieselbe Weise stapeln.

Joey Adams
quelle
Also, wie würde die Sorte heißen, um die Wörter in der richtigen Sortierreihenfolge von Apfel-Pfirsich-Sportstroh zu machen? Die stabile Sorte gab uns Apfel-Pfirsich-Stroh-Spork, jedoch sollte st nach sp (alphabetisch korrekt) sein, so dass die ultimative richtige Sorte Apfel-Pfirsich-Sport-Stroh sein sollte
user1416486
2
@ user1416486: Wir sortieren nur nach dem ersten Buchstaben. Mit dieser Annahme strawund sporkvergleiche gleich. Eine stabile Sortierung behält die Reihenfolge der Eingabe bei, während eine instabile Sortierung diese Garantie nicht übernimmt. "Richtig" hängt von der Anwendung ab. Mit der Sortierfunktion in den meisten Programmiersprachen kann der Benutzer eine benutzerdefinierte Bestellfunktion bereitstellen. Wenn die Benutzerfunktion verschiedene Elemente als gleich behandelt (z. B. gleichen Vornamen, unterschiedlichen Nachnamen), ist es hilfreich zu wissen, ob die ursprüngliche Reihenfolge beibehalten wird. Ein Beispiel aus der Praxis finden Sie in den Array-Sortierfunktionen von OCaml .
Joey Adams
3
Ich verstehe die Zeile nicht. Gleicher Sortierschlüssel ? Was meinst du hier mit Schlüssel? Bitte erläutern Sie die Aussage .. gleichen Sortierschlüssel
saplingPro
2
@saplingPro: Mit "Sortierschlüssel" meine ich das, nach dem Sie Artikel sortieren. Wenn Sie also nach dem ersten Buchstaben sortieren, ist der "Sortierschlüssel" für jedes Element der erste Buchstabe.
Joey Adams
12
Beispiel - Angenommen, Sie haben eine Liste mit jedem Artikel, die Informationen zum Ziel des Fluges und zur Abflugzeit enthält. Sie sortieren die Liste zunächst nach Zeit. Wir sortieren es dann nach dem Ziel. Wenn die zweite Sorte stabil ist, haben wir jetzt alle Flüge zusammen und in aufsteigender Reihenfolge der Abflugzeit an dasselbe Ziel gebunden. Wenn es nicht stabil wäre, würden sie nicht in aufsteigender Reihenfolge der Zeit sein.
Roottraveller
55

Ein stabiler Sortieralgorithmus ist derjenige, der die identischen Elemente in derselben Reihenfolge sortiert, in der sie in der Eingabe erscheinen, während eine instabile Sortierung den Fall möglicherweise nicht erfüllt. - Ich danke meinem Algorithmus-Dozenten Didem Gozupek für den Einblick in Algorithmen .

Stabile Sortieralgorithmen:

  • Sortieren durch Einfügen
  • Zusammenführen, sortieren
  • Blasensortierung
  • Tim Sort
  • Sortierung zählen
  • Block sortieren
  • Quadsort
  • Bibliothekssortierung
  • Cocktail Shaker Sort
  • Gnome Sort
  • Ungerade-gerade Sortierung

Instabile Sortieralgorithmen:

  • Haufen sortieren
  • Auswahl sortieren
  • Shell sortieren
  • Schnelle Sorte
  • Introsort (vorbehaltlich Quicksort)
  • Baumsorte
  • Zyklus sortieren
  • Smoothsort
  • Turniersorte (vorbehaltlich Hesapsort)

Geben Sie hier die Bildbeschreibung ein

snr
quelle
2
Ihre Werte sind nicht gleich. Sie vergleichen 9,7 und 9,8, aber laut Stabilitätsprüfung benötigen Sie die gleichen Werte wie 9,7 oder 9,8. Und dann sollten gleiche Werte in stabilen Algorithmen gleich geordnet werden.
Erhun
1
Nein, um die Stabilität zu überprüfen, sollten Ihre Werte gleich sein. Ich meine, nehmen Sie an, dass Sie zwei 9,7 verwenden und sie an Knoten A und Knoten B benennen. Wenn jede Sortieroperationsreihenfolge wie A ist, verstehen B (anstatt dass sie gleich sind), dass der Sortieralgorithmus stabil ist (wie die Zusammenführungssortierung). Wenn sich die Reihenfolge A, B ändert, wenn sie mehrmals sortiert werden (1. Sortieren von A, B, dann B, A erneut A, B usw.), verstehen Sie, dass der Sortieralgorithmus instabil ist (wie beim schnellen Sortieren) @snr
erhun
@snr [9, 6] ist im Input Array nicht vorhanden. Ich denke, Sie meinten [9, 8] im letzten Array-Streifen.
Usman
4
@erhun Ich glaube, er sortiert nur nach der ersten Zahl (der vor dem Komma) und verwendet die zweite Zahl nur als Referenz, damit Sie sehen, dass die erste 9 anders ist als die zweite 9.
Tiago
20

Sortierstabilität bedeutet, dass Datensätze mit demselben Schlüssel ihre relative Reihenfolge vor und nach dem Sortieren beibehalten.

Stabilität ist also nur dann wichtig, wenn das Problem, das Sie lösen, die Beibehaltung dieser relativen Reihenfolge erfordert.

Wenn Sie keine Stabilität benötigen, können Sie einen schnellen Algorithmus zum Löschen des Speichers aus einer Bibliothek wie Heapsort oder Quicksort verwenden und diesen vergessen.

Wenn Sie Stabilität brauchen, ist es komplizierter. Stabile Algorithmen haben eine höhere Big-O-CPU- und / oder Speicherauslastung als instabile Algorithmen. Wenn Sie also einen großen Datensatz haben, müssen Sie zwischen dem Hochfahren der CPU oder des Speichers wählen. Wenn Sie sowohl die CPU als auch den Arbeitsspeicher einschränken, liegt ein Problem vor. Ein guter kompromissstabiler Algorithmus ist eine binäre Baumsortierung. Der Wikipedia-Artikel enthält eine pathetisch einfache C ++ - Implementierung, die auf der STL basiert.

Sie können einen instabilen Algorithmus in einen stabilen Algorithmus verwandeln, indem Sie die ursprüngliche Datensatznummer als Schlüssel für den letzten Platz für jeden Datensatz hinzufügen.

Bob Murphy
quelle
1
Stabile Algorithmen wie Merge Sort haben dieselbe O (NlogN) -Komplexität wie Quicksort. Der konstante Multiplikator des Aufwands ist jedoch größer.
Jonathan Leffler
Ja, und die Speichernutzung bei Merge Sort ist O (N), während sie bei Quicksort O ist (log N). Der Grund, warum ich Quicksort erwähnt habe, ist, dass qsort () eine C-Standardbibliotheksroutine ist und daher wirklich verfügbar ist.
Bob Murphy
1
Beste Gesamtantwort IMHO. Die in anderen erwähnte Multi-Key-Technik ist interessant, aber überbewertet. Es ist einfach anzuwenden, aber in der Regel viel langsamer als offensichtliche Alternativen (verwenden Sie einfach eine Sortierung mit einem Vergleich mit mehreren Schlüsseln; oder sortieren Sie nach dem ersten Schlüssel und identifizieren und sortieren Sie dann alle Unterlisten mit Duplikaten). Die Tatsache, dass eine stabile Sortierung ein vorhersehbares Ergebnis liefert, kann in einigen Apps wichtig sein. Insbesondere wenn Sie zwei Eingabelisten A, B haben, die identisch sind, außer dass Liste B einen zusätzlichen Eintrag hat, sind die Ausgaben für eine stabile Sortierung identisch, außer dass B denselben zusätzlichen Eintrag hat. Und +1 für das letzte pgph.
Greggo
16

Es hängt davon ab, was Sie tun.

Stellen Sie sich vor, Sie haben einige Personendatensätze mit einem Vor- und einem Nachnamenfeld. Zuerst sortieren Sie die Liste nach Vornamen. Wenn Sie dann die Liste mit einem stabilen Algorithmus nach Nachnamen sortieren, wird eine Liste nach Vorname UND Nachname sortiert.

Svens
quelle
4
Ich denke du meinst "Nachname UND Vorname". Der Nachname ist normalerweise der Nachname.
Bacon Bits
14

Es gibt einige Gründe, warum Stabilität wichtig sein kann. Zum einen können Sie eine Speicheraktualisierung verursachen, wenn zwei Datensätze nicht durch Austauschen ausgetauscht werden müssen. Eine Seite ist als fehlerhaft markiert und muss auf die Festplatte (oder ein anderes langsames Medium) neu geschrieben werden.

Clinton Pierce
quelle
Was hat Plattenwechsel mit Stabilität zu tun?
user1683793
4

Ein Sortieralgorithmus gilt als stabil, wenn zwei Objekte mit gleichen Schlüsseln in der sortierten Ausgabe in derselben Reihenfolge erscheinen wie im unsortierten Eingabearray. Einige Sortieralgorithmen wie Insertion Sort, Merge Sort, Bubble Sort usw. sind von Natur aus stabil. Einige Sortieralgorithmen wie Heap Sort, Quick Sort usw. sind dies nicht.

Jedes gegebene Sortieralgo, das nicht stabil ist, kann jedoch so modifiziert werden, dass es stabil ist. Es kann algo-spezifische Möglichkeiten geben, um es stabil zu machen, aber im Allgemeinen kann jeder vergleichsbasierte Sortieralgorithmus, der von Natur aus nicht stabil ist, durch Ändern der Schlüsselvergleichsoperation so geändert werden, dass er stabil ist, so dass der Vergleich zweier Schlüssel die Position als a betrachtet Faktor für Objekte mit gleichen Schlüsseln.

Referenzen: http://www.math.uic.edu/~leon/cs-mcs401-s08/handouts/stability.pdf http://en.wikipedia.org/wiki/Sorting_algorithm#Stability

Roottraveller
quelle
3

Ich weiß, dass es dafür viele Antworten gibt, aber für mich hat diese Antwort von Robert Harvey sie viel klarer zusammengefasst:

Eine stabile Sortierung behält die ursprüngliche Reihenfolge des Eingabesatzes bei, wobei der [instabile] Algorithmus nicht zwischen zwei oder mehr Elementen unterscheidet.

Quelle

John R Perry
quelle
1

Wenn Sie annehmen, dass das, was Sie sortieren, nur Zahlen sind und nur ihre Werte sie identifizieren / unterscheiden (z. B. Elemente mit demselben Wert sind identisch), ist das Stabilitätsproblem der Sortierung bedeutungslos.

Objekte mit der gleichen Priorität beim Sortieren können jedoch unterschiedlich sein, und manchmal ist ihre relative Reihenfolge eine aussagekräftige Information. In diesem Fall führt eine instabile Sortierung zu Problemen.

Zum Beispiel haben Sie eine Liste von Daten, die die Zeitkosten [T] aller Spieler enthält, um ein Labyrinth mit Level [L] in einem Spiel zu reinigen. Angenommen, wir müssen die Spieler danach ordnen, wie schnell sie das Labyrinth reinigen. Es gilt jedoch eine zusätzliche Regel: Spieler, die das Labyrinth mit höherem Level reinigen, haben immer einen höheren Rang, egal wie lange die Zeitkosten sind.

Natürlich können Sie versuchen, den gepaarten Wert [T, L] mit einem Algorithmus, der den Regeln folgt, einer reellen Zahl [R] zuzuordnen und dann alle Spieler mit dem Wert [R] zu bewerten.

Wenn jedoch eine stabile Sortierung möglich ist, können Sie die gesamte Liste einfach nach [T] (zuerst schnellere Spieler) und dann nach [L] sortieren. In diesem Fall wird die relative Reihenfolge der Spieler (nach Zeitkosten) nicht geändert, nachdem Sie sie nach der Ebene des von ihnen gereinigten Labyrinths gruppiert haben.

PS: Natürlich ist der Ansatz, zweimal zu sortieren, nicht die beste Lösung für das jeweilige Problem, aber um die Frage nach dem Poster zu erklären, sollte es ausreichen.

M Ciel
quelle
0

Eine stabile Sortierung gibt immer dieselbe Lösung (Permutation) bei derselben Eingabe zurück.

Zum Beispiel wird [2,1,2] unter Verwendung einer stabilen Sortierung als Permutation [2,1,3] sortiert (zuerst ist Index 2, dann Index 1, dann Index 3 in der sortierten Ausgabe). Dies bedeutet, dass die Ausgabe immer auf die gleiche Weise gemischt wird. Andere nicht stabile, aber immer noch korrekte Permutation ist [2,3,1].

Die schnelle Sortierung ist keine stabile Sortierung, und die Permutationsunterschiede zwischen denselben Elementen hängen vom Algorithmus für die Auswahl des Pivots ab. Einige Implementierungen werden zufällig ausgewählt, und dies kann zu einer schnellen Sortierung führen, die unterschiedliche Permutationen bei derselben Eingabe mit demselben Algorithmus ergibt.

Ein stabiler Sortieralgorithmus ist deterministisch notwendig.

Luka Rahne
quelle
2
Das bedeutet Stabilität nicht. Siehe en.wikipedia.org/wiki/Sorting_algorithm#Stability
Luís Oliveira
Ich sollte den letzten Satz korrigieren, da eine nicht stabile Sortierung auch unter derselben Implementierung eine andere Lösung ausgeben kann, wobei jede stabile Sortierung dieselbe Lösung ausgibt.
Luka Rahne
1
Warum -1? Kann jemand bitte darauf hinweisen, was hier falsch ist? Dies ist nicht die stabile Sortierung, sondern die Eigenschaft der stabilen Sortierung.
Luka Rahne
Ob die Sortierung deterministisch ist oder nicht, bestimmt nicht, ob sie stabil ist. Ich kann einen nicht stabilen deterministischen Sortieralgorithmus schreiben, indem ich ein anderes Bindungsunterbrechungsverhalten definiere (indem ich beispielsweise nicht wichtige Teile subortiere). Eine stabile Sortierung impliziert insbesondere, dass die vorsortierte relative Reihenfolge der Elemente beibehalten wird, wenn Bindungen sortiert werden. Beispiel für eine Ausgabe einer stabilen Art : sort([(5,3),(1,5),(3,3),(1,3)], x) => [(1,5),(1,3),(3,3),(5,3)]. Ich kann eine deterministische Sortierung vornehmen, die immer (deterministisch) ausgibt. [(1,3),(1,5),(3,3),(5,3)]Dies ist jedoch keine stabile Sortierung.
Cowbert
@cowbert Es ist mehr Aussage über nette Eigenschaft, die jede stabile Sorte hat. Dies ist unabhängig davon, welcher stabile Sortieralgorithmus oder welche Implementierung verwendet wird, jedes Mal, wenn das gleiche Ergebnis erzielt wird. Es ist schwieriger, solche Eigenschaften bei verschiedenen nicht stabilen Sortierimplementierungen beizubehalten.
Luka Rahne
0

Einige weitere Beispiele für den Grund für den Wunsch nach stabilen Sorten. Datenbanken sind ein häufiges Beispiel. Nehmen Sie den Fall einer Transaktionsdatenbank, die Nachname, Vorname, Kaufzeitpunkt, Artikelnummer und Preis enthält. Angenommen, die Datenbank ist normalerweise nach Datum und Uhrzeit sortiert. Dann wird eine Abfrage durchgeführt, um eine sortierte Kopie der Datenbank nach Nachname zu erstellen, da eine stabile Sortierung die ursprüngliche Reihenfolge beibehält, obwohl der Vergleich der Anfrage nur Nachname beinhaltet, werden die Transaktionen für jeden Nachnamen durchgeführt in Datenreihenfolge sein.

Ein ähnliches Beispiel ist klassisches Excel, bei dem die Sortierung auf drei Spalten gleichzeitig beschränkt ist. Um 6 Spalten zu sortieren, wird eine Sortierung mit den niedrigstwertigen 3 Spalten durchgeführt, gefolgt von einer Sortierung mit den höchstwertigen 3 Spalten.

Ein klassisches Beispiel für eine stabile Radix-Sortierung ist ein Kartensortierer, der zum Sortieren nach einem Feld mit numerischen Spalten der Basis 10 verwendet wird. Die Karten werden von der niedrigstwertigen bis zur höchstwertigen Ziffer sortiert. Bei jedem Durchgang wird ein Kartenspiel gelesen und entsprechend der Ziffer in dieser Spalte in 10 verschiedene Fächer aufgeteilt. Dann werden die 10 Kartenfächer der Reihe nach wieder in den Eingabetrichter gelegt ("0" -Karten zuerst, "9" -Karten zuletzt). Dann wird ein weiterer Durchgang durch die nächste Spalte durchgeführt, bis alle Spalten sortiert sind. Tatsächliche Kartensortierer haben mehr als 10 Fächer, da eine Karte 12 Zonen enthält, eine Spalte leer sein kann und ein falsch gelesenes Fach vorhanden ist. Zum Sortieren von Buchstaben sind 2 Durchgänge pro Spalte erforderlich, 1. Durchgang für Ziffer, 2. Durchgang für die Zone 12 11.

Später (1937) gab es Kartensammelmaschinen, mit denen zwei Kartenspiele durch Vergleichen von Feldern zusammengeführt werden konnten. Die Eingabe bestand aus zwei bereits sortierten Kartenspielen, einem Master-Deck und einem Update-Deck. Der Collator führte die beiden Decks zu einem neuen Materialfach und einem Archivfach zusammen, das optional für Master-Duplikate verwendet wurde, sodass das neue Master-Fach nur bei Duplikaten über Aktualisierungskarten verfügt. Dies war wahrscheinlich die Grundlage für die Idee hinter der ursprünglichen Zusammenführungssorte (von unten nach oben).

rcgldr
quelle