Was ist der schnellste Sortieralgorithmus für ein Array von ganzen Zahlen?

55

Ich bin während meines Gymnasialstudiums auf viele Sortieralgorithmen gestoßen. Ich weiß jedoch nie, welche (für ein zufälliges Array von ganzen Zahlen) die schnellste ist. Meine Fragen sind also:

  • Welches ist der schnellste derzeit bekannte Sortieralgorithmus?
  • Ist es theoretisch möglich, dass es noch schnellere gibt? Also, was ist die geringste Komplexität beim Sortieren?
gen
quelle
7
Was meinst du mit "schnell"? Was möchten Sie messen?
Raphael
2
Was bedeutet "zufällige Anordnung von ganzen Zahlen"? Zufällig mit welcher Distribution? Gleichverteilung? Gaußsche? Abhängig von der Verteilung sind möglicherweise bessere Laufzeitalgorithmen als erwarten. O(nLogn)
Bakuriu
@gen Werfen Sie einen Blick auf Radix sort. Die korrekte Implementierung hat zum Beispiel für Int32 eine O (n) -Komplexität.
dieser
Werfen Sie einen Blick auf die Art Benchmark
Adriann
1
@ Gen: In Bezug auf Asymptotika? Dann ist es ganz einfach: Wählen Sie einen der -Algorithmen. Beachten Sie, dass dies möglicherweise nichts mit (durchschnittlicher) realer Leistung zu tun hat. Dies kann in dieser Hinsicht eine lohnende Lektüre sein. ΘΘ(nlogn)
Raphael

Antworten:

42

Im Allgemeinen gibt es die -Sortierungsalgorithmen wie Einfügesortierung, Blasensortierung und Auswahlsortierung, die Sie normalerweise nur unter bestimmten Umständen verwenden sollten. Quicksort, das im schlimmsten Fall aber häufig mit guten Konstanten und Eigenschaften ist und als Allzweck-Sortierverfahren verwendet werden kann; die -Algorithmen wie Merge-Sort und Heap-Sort, die auch gute Allzweck-Sortieralgorithmen sind; und den - oder linearen Sortieralgorithmus für Listen mit ganzen Zahlen, z. B. Radix, Bucket und Zählsortierungen, der je nach Art der ganzen Zahlen in Ihren Listen geeignet sein kann.O(n2)O(n2)O(nLogn)O(nLogn)O(n)

Wenn die Elemente in Ihrer Liste so beschaffen sind, dass Sie nur die Gesamtordnungsbeziehung zwischen ihnen kennen, haben optimale Sortieralgorithmen die Komplexität . Dies ist ein ziemlich cooles Ergebnis, für das Sie online problemlos Details finden sollten. Die linearen Sortieralgorithmen nutzen mehr Informationen über die Struktur der zu sortierenden Elemente als nur die Gesamtordnungsbeziehung zwischen den Elementen.Ω(nLogn)

Noch allgemeiner hängt die Optimalität eines Sortieralgorithmus stark von den Annahmen ab, die Sie über die Art der zu sortierenden Listen treffen können (sowie von dem Maschinenmodell, auf dem der Algorithmus ausgeführt wird, was selbst ansonsten zu einer schlechten Sortierung führen kann) Algorithmen sind die beste Wahl. Erwägen Sie die Blasensortierung auf Maschinen mit einem Band zur Speicherung. Je stärker Ihre Annahmen sind, desto mehr Ecken kann Ihr Algorithmus abschneiden. Unter sehr schwachen Annahmen darüber, wie effizient Sie die "Sortierbarkeit" einer Liste bestimmen können, kann die optimale Worst-Case-Komplexität sogar Sein .Ω(n!)

Diese Antwort befasst sich nur mit Komplexitäten. Die tatsächlichen Laufzeiten von Implementierungen von Algorithmen hängen von einer Vielzahl von Faktoren ab, die in einer einzigen Antwort nur schwer zu berücksichtigen sind.

Patrick87
quelle
Ich denke, einige dieser sollte ? OΩ
Raphael
1
@Raphael Meh. Ich denke, die meisten von ihnen sind sowieso . Ich nehme an, die Untergrenze ist wahrscheinlich besser gerendert . Ich werde ein paar davon ändern, die am sinnvollsten sind. ΘΩ
Patrick87
7
Ich stimme @Raphael bekommt eine Polizei hat : PΩ
Realz Slaw
2
@ RealzSlaw: Ich würde es stolz tragen. :]
Raphael
1
@gen Weitere Informationen finden Sie unter stackoverflow.com/a/3274203 . Grundsätzlich gilt: Wenn einzelne Datensätze sehr umfangreich sind und nicht über einen Direktzugriff gespeichert werden und die Datenmenge so ist, dass sie an Ort und Stelle erstellt werden muss, ist die Blasensortierung der richtige Weg. Diese Umstände sind heutzutage in der Regel selten, können aber dennoch auftreten.
Patrick87
16

Die Antwort lautet, wie so oft, "es kommt darauf an". Es hängt von Dingen wie (a) wie groß die ganzen Zahlen sind, (b) ob das Eingabearray ganze Zahlen in zufälliger Reihenfolge oder in nahezu sortierter Reihenfolge enthält, (c) ob der Sortieralgorithmus stabil sein muss oder nicht, sowie andere Faktoren, (d) ob die gesamte Liste der Nummern in den Speicher passt (In-Memory-Sortierung im Vergleich zur externen Sortierung) und (e) den Computer, auf dem Sie sie ausführen.

In der Praxis ist der Sortieralgorithmus in der Standardbibliothek Ihrer Sprache wahrscheinlich ziemlich gut (nahezu optimal), wenn Sie eine speicherinterne Sortierung benötigen. Verwenden Sie daher in der Praxis einfach die von der Standardbibliothek bereitgestellte Sortierfunktion und messen Sie die Laufzeit. Nur wenn Sie feststellen, dass (i) das Sortieren einen großen Teil der Gesamtlaufzeit ausmacht und (ii) die Laufzeit inakzeptabel ist, sollten Sie sich die Mühe machen, mit dem Sortieralgorithmus herumzuspielen. Wenn diese beiden Bedingungen tun halten, dann können Sie auf die spezifischen Aspekte Ihrer bestimmten Domain suchen und mit anderen schnellen Sortieralgorithmen experimentieren.

In der Praxis ist der Sortieralgorithmus jedoch realistisch gesehen selten ein wesentlicher Leistungsengpass.

DW
quelle
9

Beantworten Sie außerdem Ihre zweite Frage

Ist es theoretisch möglich, dass es noch schnellere gibt?
Also, was ist die geringste Komplexität beim Sortieren?

Für die allgemeine Sortierung beträgt die Komplexität des vergleichsbasierten Sortierproblems Ω (n log n) . Es gibt einige Algorithmen, die eine Sortierung in O (n) durchführen, aber alle basieren auf Annahmen über die Eingabe und sind keine Allzweck-Sortieralgorithmen.

Grundsätzlich ergibt sich die Komplexität aus der minimalen Anzahl von Vergleichen, die zum Sortieren des Arrays erforderlich sind (log n steht für die maximale Höhe eines binären Entscheidungsbaums, der beim Vergleichen der einzelnen Elemente des Arrays erstellt wird).

Den formalen Nachweis für die Sortierung der Komplexität finden Sie hier :

rla4
quelle
3
Diese Antwort ist nicht ganz richtig. ist keine universelle Untergrenze für die Sortierung. Diese Untergrenze gilt nur für vergleichsbasierte Sortierungen, dh Sortieralgorithmen, die nur Vergleiche verwenden. Einige Sortieralgorithmen basieren nicht auf Vergleichen. Die Aussage "Es gibt einige Algorithmen, die in O (n) sortieren, aber alle beruhen auf Annahmen über die Eingabe und sind keine Allzweck-Sortieralgorithmen." könnte ein wenig irreführend sein - seien Sie vorsichtig. Radix-Sort ist ein Allzweck-Sortieralgorithmus (vorausgesetzt, Sie sortieren Ganzzahlen mit fester Breite). Ω(nLogn)
DW
Kommt darauf an, was du mit dem Sortierproblem meinst . Allgemeine vergleichsbasierte Sortierungen sind nicht die einzigen Sortierungsprobleme, die Menschen haben.
Patrick87
1
Das stimmt natürlich. Ich hätte genauer darauf eingehen sollen, danke für den Hinweis. Ich war jedoch ein bisschen neugierig, auf welche anderen Sortierungsansätze (nicht vergleichsbasiert) Sie sich bezogen haben. Radix-Sortierung ist genau die Art von O (n) -Algorithmus, über die ich gesprochen habe - Sie müssen etwas über die Eingabe "annehmen" (Ganzzahlen mit fester Breite). In diesem Sinne handelt es sich nicht um einen Allzweck-Sortieralgorithmus, oder?
rla4
1
@DW: Die Radix-Sortierung sollte nicht als Allzweck-Sortieralgorithmus betrachtet werden, da hierfür Ganzzahlschlüssel mit fester Länge erforderlich sind. ist es sonst nicht sinnvoll. Aber ich verstehe, worum es geht. :) Ich glaube, mein Fehler lag darin, etwas zu sortieren, das verglichen werden kann, anstatt ganzzahlige Zahlen zu sortieren . Sie sind unterschiedliche Probleme und haben unterschiedliche Lösungsmöglichkeiten. Die Frage erwähnt "eine zufällige Anordnung von ganzen Zahlen", aber ich gebe zu, ich habe es als Beispiel genommen und nicht als Einschränkung.
rla4
2
@DavidRicherby, wenn ich nach anderthalb Jahren zurückblicke, stimme ich Ihnen zu. Danke.
DW
3

Der schnellste Ganzzahl-Sortieralgorithmus, der mir im schlimmsten Fall begegnet ist, ist der von Andersson et al. Es hat einen Worst-Case von , der natürlich schneller ist als O ( n log n ) .O(nLogLogn)O(nLogn)

user39994
quelle
2
Das ist sehr interessant, aber Sie müssen mehr Informationen geben. Da Sie erwähnen , nehmen wir an, dass Sie wissen, dass die vergleichsbasierte Sortierung von allgemeinen Ganzzahlen nachweislich Zeit Ω ( n log n ) erfordert . Alles, was asymptotisch schneller ist, muss Annahmen über die Daten treffen: Beispielsweise wird die Radix-Sortierung in linearer Zeit ausgeführt, vorausgesetzt, dass jedes Element des Arrays höchstens eine gewisse Konstante aufweist. Unter welchen Bedingungen sortiert dieser Algorithmus in O ( n log log n ) und wie verhält er sich in der Praxis gegenüber anderen Algorithmen wie QuickSort und Radix Sort? nLognΩ(nLogn)O(nLogLogn)
David Richerby
1

Ich habe die beiden anderen Antworten zum Zeitpunkt des Schreibens durchgelesen, und ich dachte, keine der beiden Antworten hat Ihre Frage angemessen beantwortet. Andere Antworten betrachteten irrelevante Vorstellungen über zufällige Verteilungen und Raumkomplexität, die für ein Abitur wahrscheinlich nicht in Frage kommen. Also hier ist meine Einstellung.

EINn(n-1)EIN(n-1)Ω(n)O(n)Ω(n)

Ω(n)O(n)n2n3n-51n2

bourbaki4481472
quelle
O(n)nlgnn232O(n)O(nlgn)(für Quicksort oder Mergesort) ist der Vergleich in der Praxis nicht ganz so eindeutig: Die in der Big-O-Notation verborgenen Konstanten werden sehr wichtig, und die Konstante für Radix-Sort ist höher als die Konstante für Quicksort oder Mergesort.
DW
lG(n)n
Ω(n)
2
O(wn)www{0,,2w-1}Lognnw=LognnLogn.
David Richerby
1

O(nlOGlOGn)
O(nlOGlOGU)U
der Narr
quelle
0

Log(n!)

Ω(n)

Yves Daoust
quelle
0

Da Sie keine Hardwareeinschränkungen erwähnen und nach "den schnellsten" Ausschau halten, sollten Sie einen der Algorithmen für die parallele Sortierung auswählen, die auf der verfügbaren Hardware und der Art Ihrer Eingaben basieren.

In der Theorie zB quick_sortist O(n log n). Bei pProzessoren sollte dies idealerweise der Fall sein, O(n/p log n)wenn wir es parallel ausführen.

Wikipedia zitieren: Zeitkomplexität von ...

Optimale parallele Sortierung ist O (log n)

In der Praxis ist dies O(log n)aufgrund von Skalierbarkeitsproblemen bei großen Eingabegrößen nicht möglich .

Hier ist der Pseudocode für die parallele Zusammenführungssortierung . Die Implementierung von merge()kann dieselbe sein wie bei der normalen Zusammenführungssortierung:

// Sort elements lo through hi (exclusive) of array A.
algorithm mergesort(A, lo, hi) is
    if lo+1 < hi then  // Two or more elements.
        mid = ⌊(lo + hi) / 2⌋
        fork mergesort(A, lo, mid)
        mergesort(A, mid, hi)
        join
        merge(A, lo, mid, hi)

Siehe auch:

Kashyap
quelle
O(n2)
@ Evil Ja. Quicksort eignet sich nicht für die Parallelverarbeitung. Das ist ein Beispiel. Diejenigen, die verwendet werden sollten, sind in den angegebenen Links aufgeführt.
Kashyap