it-swarm.com.de

Welcher Sortieralgorithmus eignet sich am besten für meist sortierte Daten?

Welcher Sortieralgorithmus eignet sich am besten für meist sortierte Daten?

166
graphics

Basierend auf der hochwissenschaftlichen Methode des Betrachtens animierte GIFs Ich würde sagen, dass Insertion- und Bubble-Sortierungen gute Kandidaten sind.

251
Tom Ritter

Nur noch wenige Artikel => INSERTION SORT

Artikel sind meistens schon sortiert => INSERTION SORT

Besorgt über Worst-Case-Szenarien => HEAP SORT

Interessiert an einem guten Durchschnittsergebnis => QUICKSORT

Gegenstände werden aus einem dichten Universum gezogen => EIMERSORTIERUNG

Wünschen Sie so wenig Code wie möglich zu schreiben => INSERTION SORT

103
Jiaji Li

timsort

Timsort ist "ein adaptives, stabiles, natürliches Mergesort" mit " übernatürlicher Leistung auf vielen Arten von teilweise geordneten Arrays (kleiner als lg (N!) Vergleiche nötig und nur N-1) ". Pythons integrierte Funktion sort() verwendet diesen Algorithmus seit einiger Zeit, anscheinend mit guten Ergebnissen. Es wurde speziell entwickelt, um teilweise sortierte Teilsequenzen in der Eingabe zu erkennen und zu nutzen, die häufig in realen Datensätzen auftreten. In der realen Welt sind Vergleiche oft viel teurer als das Austauschen von Elementen in einer Liste, da in der Regel nur Zeiger ausgetauscht werden, was Timsort sehr oft zu einer hervorragenden Wahl macht. Wenn Sie jedoch wissen, dass Ihre Vergleiche immer sehr billig sind (z. B. das Schreiben eines Spielzeugprogramms zum Sortieren von 32-Bit-Ganzzahlen), gibt es andere Algorithmen, die wahrscheinlich eine bessere Leistung erbringen. Der einfachste Weg, Timsort zu nutzen, ist natürlich die Verwendung von Python, aber da Python Open Source ist, können Sie den Code möglicherweise auch ausleihen. Alternativ enthält die obige Beschreibung mehr als genug Details um eine eigene Implementierung zu schreiben.

30
zaphod

Einfügesortierung mit folgendem Verhalten:

  1. Für jedes Element k in Slots 1..n, überprüfe zuerst, ob el[k] >= el[k-1]. Wenn ja, gehe zum nächsten Element. (Überspringen Sie natürlich das erste Element.)
  2. Wenn nicht, benutze die binäre Suche in den Elementen 1..k-1, um den Einfügeort zu bestimmen, und scooten Sie dann die Elemente darüber. (Sie können dies nur tun, wenn k>T wobei T ein Schwellenwert ist; mit kleinem k ist das übertrieben.)

Diese Methode führt die geringste Anzahl von Vergleichen durch.

19
Jason Cohen

Versuchen Sie es nach innen. http://en.wikipedia.org/wiki/Introsort

Es basiert auf Quicksort, vermeidet jedoch das schlimmste Verhalten, das Quicksort bei nahezu sortierten Listen hat.

Der Trick ist, dass dieser Sortieralgorithmus die Fälle erkennt, in denen Quicksort in den Worst-Case-Modus wechselt und auf Heap- oder Merge-Sortierung umschaltet. Nahezu sortierte Partitionen werden durch eine nicht aktive Partitionsmethode erkannt, und kleine Partitionen werden mithilfe der Einfügesortierung behandelt.

Sie erhalten den besten aller gängigen Sortieralgorithmen für den Preis von mehr Code und Komplexität. Und Sie können sicher sein, dass Sie niemals in den schlimmsten Fall geraten Verhalten, egal wie Ihre Daten aussehen.

Wenn Sie ein C++ - Programmierer sind, überprüfen Sie Ihren std :: sort-Algorithmus. Möglicherweise wird die introspektive Sortierung bereits intern verwendet.

11

Splaysort ist eine obskure Sortiermethode basierend auf splay trees , einer Art adaptiver Binärbaum. Splaysort eignet sich nicht nur für teilweise sortierte Daten, sondern auch für teilweise rücksortierte Daten oder Daten, die eine bereits vorhandene Reihenfolge haben. Es ist O(nlogn) im allgemeinen Fall und O(n) im Fall, in dem die Daten auf irgendeine Weise sortiert sind (vorwärts, rückwärts, Orgelpfeife usw.).

Der große Vorteil gegenüber der Einfügesortierung besteht darin, dass das Verhalten von O (n ^ 2) nicht wiederhergestellt wird, wenn die Daten überhaupt nicht sortiert werden. Daher müssen Sie nicht unbedingt sicher sein, dass die Daten teilweise sortiert sind, bevor Sie sie verwenden .

Der Nachteil ist der zusätzliche Platzbedarf für die Spreizbaumstruktur sowie der Zeitaufwand für die Erstellung und Zerstörung des Spreizbaums. Abhängig von der Datengröße und der erwarteten Vorsortierung kann sich der Aufwand für die Erhöhung der Geschwindigkeit lohnen.

Ein Artikel über Splaysort wurde in Software - Practice & Experience veröffentlicht.

7
TimB

einfügen oder Shell sortieren!

5
ninesided

Dijkstra's Smoothsort ist eine großartige Sortierung für bereits sortierte Daten. Es ist eine Heapsort-Variante, die im schlechtesten Fall O (n lg n) und im besten Fall O(n) ausgeführt wird. Ich schrieb eine Analyse des Algorithmus, falls Sie neugierig sind, wie es funktioniert.

Natural Mergesort ist eine weitere wirklich gute Variante: Es handelt sich um eine Bottom-Up-Mergesort-Variante, bei der die Eingabe als Verkettung mehrerer verschiedener sortierter Bereiche behandelt und diese dann mithilfe des Merge-Algorithmus zusammengefügt werden. Sie wiederholen diesen Vorgang, bis der gesamte Eingabebereich sortiert ist. Dies wird in der O(n) Zeit ausgeführt, wenn die Daten bereits sortiert sind und im schlimmsten Fall O (n (n lg n)). Es ist sehr elegant, obwohl es in der Praxis nicht so gut ist wie andere adaptive Sorten wie Timsort oder Smoothsort.

5
templatetypedef

Wenn Elemente bereits sortiert sind oder nur wenige Elemente vorhanden sind, ist dies der perfekte Anwendungsfall für die Einfügesortierung!

4
Roger

Die Einfügungssortierung benötigt die Zeit O (n + die Anzahl der Inversionen).

Eine Inversion ist ein Paar (i, j) so dass i < j && a[i] > a[j]. Das heißt, ein Paar in der falschen Reihenfolge.

Ein Maß für "fast sortiert" ist die Anzahl der Inversionen - man könnte "fast sortierte Daten" verwenden, um Daten mit wenigen Inversionen zu bezeichnen. Wenn man weiß, dass die Anzahl der Inversionen linear ist (zum Beispiel haben Sie gerade O(1) Elemente an eine sortierte Liste angehängt), nimmt die Sortierung der Einfügung O(n) Zeit.

3
Jonas Kölker

Ich werde nicht so tun, als ob ich hier alle Antworten hätte, da ich denke, dass es erforderlich sein könnte, die Algorithmen zu codieren und sie mit repräsentativen Datenproben zu vergleichen, um die tatsächlichen Antworten zu erhalten. Aber ich habe den ganzen Abend über diese Frage nachgedacht, und hier ist, was mir bisher eingefallen ist, und einige Vermutungen darüber, was wo am besten funktioniert.

Sei N die Anzahl der Elemente insgesamt, M die Anzahl der nicht in Reihenfolge befindlichen Elemente.

Die Blasensortierung muss bewirken, dass 2 * M + 1 alle N Elemente durchläuft. Wenn M sehr klein ist (0, 1, 2?), Wird dies meiner Meinung nach sehr schwer zu übertreffen sein.

Wenn M klein ist (beispielsweise weniger als log N), weist die Einfügesortierung eine hervorragende durchschnittliche Leistung auf. Es sei denn, es gibt einen Trick, den ich nicht sehe, der im schlimmsten Fall sehr schlecht abschneidet. (Richtig? Wenn der letzte Artikel in der Bestellung zuerst kommt, müssen Sie, soweit ich sehen kann, jeden einzelnen Artikel einfügen, der die Leistung beeinträchtigt.) Ich schätze, es gibt einen zuverlässigeren Sortieralgorithmus dafür Fall, aber ich weiß nicht, was es ist.

Wenn M größer ist (etwa gleich oder größer als log N), ist die introspektive Sortierung mit ziemlicher Sicherheit die beste.

Ausnahme: Wenn Sie bereits im Voraus wissen, welche Elemente unsortiert sind, ist es am besten, diese Elemente herauszunehmen, sie nach innen zu sortieren und die beiden sortierten Listen zu einer sortierten Liste zusammenzuführen. Wenn Sie schnell herausfinden könnten, welche Artikel nicht in Ordnung sind, wäre dies auch eine gute allgemeine Lösung - aber ich war nicht in der Lage, einen einfachen Weg zu finden, dies zu tun.

Weitere Überlegungen (über Nacht): Wenn M + 1 <N/M, können Sie die Liste nach einer Anzahl von N/M in einer Reihe durchsuchen, die sortiert sind, und dann diese Laufrichtung erweitern, um die Abweichung zu finden -Auftragspositionen. Das dauert höchstens 2N Vergleiche. Sie können dann die unsortierten Elemente sortieren und eine sortierte Zusammenführung der beiden Listen durchführen. Insgesamt sollten Vergleiche weniger als 4N + M log2 (M) sein, was meiner Meinung nach jede nicht spezialisierte Sortierroutine übertreffen wird. (Noch weiter gedacht: Das ist schwieriger als ich dachte, aber ich denke immer noch, dass es vernünftigerweise möglich ist.)

Eine andere Interpretation der Frage ist, dass es viele nicht ordnungsgemäße Elemente geben kann, diese sich jedoch sehr nahe an der Stelle befinden, an der sie in der Liste aufgeführt sein sollten. (Stellen Sie sich vor, Sie beginnen mit einer sortierten Liste und tauschen jedes andere Element gegen das nächste aus.) In diesem Fall funktioniert die Blasensortierung meiner Meinung nach sehr gut ist. Die Sortierung der Einfügungen funktioniert schlecht, da bei jedem nicht ordnungsgemäßen Artikel eine Einfügung ausgelöst wird. Ich vermute, dass introspektive Art oder so etwas auch gut funktionieren wird.

2
Sol

Wie alle anderen sagten, sei vorsichtig mit naivem Quicksort - das kann eine O (N ^ 2) -Leistung für sortierte oder nahezu sortierte Daten haben. Mit einem geeigneten Algorithmus für die Auswahl des Pivots (entweder zufällig oder Median-of-Three - siehe Auswahl eines Pivots für Quicksort ) funktioniert Quicksort dennoch einwandfrei.

Im Allgemeinen besteht die Schwierigkeit bei der Auswahl von Algorithmen wie Insert Sort darin, zu entscheiden, wann die Daten nicht in der richtigen Reihenfolge vorliegen, sodass Quicksort wirklich schneller ist.

2

Diese nette Sammlung von Sortieralgorithmen für diesen Zweck in den Antworten scheint Gnome Sort zu fehlen, was ebenfalls geeignet wäre und wahrscheinlich den geringsten Implementierungsaufwand erfordert.

1
haraldkl

Wenn Sie eine spezielle Implementierung für das Sortieren von Algorithmen, Datenstrukturen oder anderen Elementen benötigen, die einen Link zu den oben genannten Informationen haben, kann ich Ihnen das ausgezeichnete "Datenstrukturen und Algorithmen" Projekt auf CodePlex empfehlen?

Es hat alles, was Sie brauchen, ohne das Rad neu zu erfinden.

Nur mein kleines Salzkorn.

1
Maxime Rouiller

Bubble-Sortierung ist definitiv der Gewinner Die nächste Sortierung auf dem Radar wäre Insertion-Sortierung.

0
vCillusion

Die Blasensortierung (oder, noch sicherer, die bidirektionale Blasensortierung) ist wahrscheinlich ideal für meist sortierte Listen, obwohl ich wette, dass eine optimierte Kammsortierung (mit einer viel geringeren anfänglichen Lückengröße) etwas schneller wäre, wenn die Liste nicht ' nicht ganz so perfekt sortiert. Die Kammsortierung verschlechtert sich zu einer Blasensortierung.

0
Brian

nun, es hängt vom Anwendungsfall ab. Wenn Sie wissen, welche Elemente geändert werden, ist das Entfernen und Einfügen für mich der beste Fall.

0
Helin Wang

Einfügesortierung ist der beste Fall O(n) bei sortierten Eingaben. Und sie ist bei meist sortierten Eingaben sehr ähnlich (besser als schnelle Sortierung).

0
jjnguy

überlegen Heap versuchen. Ich glaube, es ist die beständigste Art von O (n lg n).

0
Paul Nathan