Sphärische Algorithmen im Vakuum sind großartig. Gehen wir jedoch vom Himmel auf die sündige Erde hinunter und sehen, wie sich all diese theoretische Schönheit in der Praxis bewähren wird.
Die Analyse der nächsten Klassenklasse endet mit Tests für Klassensorten. Heute werden wir Sortierbörsen (nicht im Sinne des Wegwerfens, sondern im Sinne des Testens) sortieren. Sorten anderer Klassen werden später ausgeführt.
Im heutigen Rennen:
Schwächste Gruppe
Diese Algorithmen beanspruchen aufgrund der drückenden Zeitkomplexität nichts. Wir testen sie nur als Referenz.

Dumme Sorte

Träge Sortierung

Dumme Sortierung
Noch interessanter ist nicht nur, wie gut sie sind, sondern auch, wie schlecht sie im Geschäft sind und welcher von ihnen der schlechteste ist.
Hauptgruppe
Hier versammelten sich Austauschsortierungen a la O (
n 2 ). Zwergsortierung (und ihre Optimierung) + alle Arten von Variationen der Blasensortierung.

Zwergsort

Zwergsortierung (optimiert)

Blasensortierung

Cocktailsortierung

Seltsam-gerade Sortierung
Dies ist der interessanteste Teil der heutigen Messungen. Unter den Vertretern der Hauptgruppe wird der hartnäckigste Kampf erwartet.
Stärkste Gruppe
Einer der Sorten der Blase - Sortierung nach einem Kamm - gelang es, die O (
n 2 ) -Sperre zu überwinden und mit der Zeit das respektable O (
n log n ) zu erreichen. In unserer Konkurrenz hat das schnelle Sortieren einen würdigen Rivalen. Probieren Sie auch die
neu erfundene k-Sortierung aus , eine Variation der schnellen Sortierung.

Haarbürste sortieren

Schnelle Sortierung

K Sortierung
Die Stärksten sind übrigens nicht nur miteinander vergleichbar. Bei einigen Datensätzen wird die Hauptgruppe in einem ernsthaften Wettbewerb stehen.
Quellcode
Python Exchange-Sortierungendef stooge_rec(data, i = 0, j = None): if j is None: j = len(data) - 1 if data[j] < data[i]: data[i], data[j] = data[j], data[i] if j - i > 1: t = (j - i + 1) // 3 stooge_rec(data, i, j - t) stooge_rec(data, i + t, j) stooge_rec(data, i, j - t) return data def stooge(data): return stooge_rec(data, 0, len(data) - 1) def slow_rec(data, i, j): if i >= j: return data m = (i + j) // 2 slow_rec(data, i, m) slow_rec(data, m + 1, j) if data[m] > data[j]: data[m], data[j] = data[j], data[m] slow_rec(data, i, j - 1) return data def slow(data): return slow_rec(data, 0, len(data) - 1) def stupid(data): i, size = 1, len(data) while i < size: if data[i - 1] > data[i]: data[i - 1], data[i] = data[i], data[i - 1] i = 1 else: i += 1 return data def gnome(data): i, size = 1, len(data) while i < size: if data[i - 1] <= data[i]: i += 1 else: data[i - 1], data[i] = data[i], data[i - 1] if i > 1: i -= 1 return data def gnome_opt(data): i, j, size = 1, 2, len(data) while i < size: if data[i - 1] <= data[i]: i, j = j, j + 1 else: data[i - 1], data[i] = data[i], data[i - 1] i -= 1 if i == 0: i, j = j, j + 1 return data def bubble(data): changed = True while changed: changed = False for i in range(len(data) - 1): if data[i] > data[i+1]: data[i], data[i+1] = data[i+1], data[i] changed = True return data def shaker(data): up = range(len(data) - 1) while True: for indices in (up, reversed(up)): swapped = False for i in indices: if data[i] > data[i+1]: data[i], data[i+1] = data[i+1], data[i] swapped = True if not swapped: return data def odd_even(data): n = len(data) isSorted = 0 while isSorted == 0: isSorted = 1 for i in range(1, n - 1, 2): if data[i] > data[i + 1]: data[i], data[i + 1] = data[i + 1], data[i] isSorted = 0 for i in range(0, n - 1, 2): if data[i] > data[i + 1]: data[i], data[i + 1] = data[i + 1], data[i] isSorted = 0 return data def comb(data): gap = len(data) swaps = True while gap > 1 or swaps: gap = max(1, int(gap / 1.25))
Zeit
Die Zeit wird überall in Sekunden gemessen, die auf Mikrosekunden genau sind.
Wenn eine Packung Arrays (von zehn, hundert oder sogar einer Million Stück) sofort dem Algorithmus zugeführt wird, wird die Gesamtzeit angezeigt.
Eisen ist mein treuer alter Laptop, der bessere Zeiten kannte. Möglicherweise funktioniert also alles viel schneller für Sie.
Das Schlimmste vom Schlimmsten
Sofort mit Außenstehenden umgehen. Für sie werden Arrays für 40/50/60 Elemente mit Zufallszahlen von 0 bis 9 vorbereitet.
| Typ = zufällig, eindeutig = falsch, min = 0, max = 9, Anzahl = 1 |
---|
Größe |
---|
40 | 50 | 60 |
---|
Python | Php | Python | Php | Python | Php |
---|
 | 0,004 | 0,001 | 0,005 | 0,003 | 0,007 | 0,004 |
---|
 | 0,007 | 0,009 | 0,018 | 0,009 | 0,018 | 0,023 |
---|
 | 0,02 | 8.26647 | 0,053 | 20.8722 | 0,12901 | 45,9786 |
---|
Dumme Sortierung ist eine Größenordnung schneller als alberne Sortierung, und dumme Sortierung ist eine Größenordnung schneller als träge. Es gibt nichts mehr zu sehen.
Mittlerer Bauer
Um den Durchschnitt zu überprüfen, wurden Packungen mit einhundert Arrays mit jeweils 100 Elementen (eindeutige Nummern von 100 bis 999) sowie Packungen mit zehn Arrays mit jeweils 1000 Elementen (eindeutige Nummern von 1000 bis 9999) generiert.
Es werden zufällige Arrays, fast sortierte Arrays und Arrays in umgekehrter Reihenfolge vorbereitet.
Mittelgewicht: Zufällig
| Typ = zufällig, eindeutig = Wahr |
---|
Größe (min bis max) × Anzahl |
---|
100 (100 bis 999) × 100 | 1000 (1000 bis 9999) × 10 |
---|
Python | Php | Python | Php |
---|
 | 0,14101 | 0,18901 | 1,59109 | 1,7251 |
---|
 | 0,20601 | 0,22301 | 2.33013 | 2,09712 |
---|
 | 0,15301 | 0,22901 | 1,6711 | 2.23613 |
---|
 | 0,21601 | 0,26402 | 2,55515 | 2,73116 |
---|
 | 0,16701 | 0,33402 | 1,7251 | 3.13218 |
---|
Etwa die gleichen Ergebnisse für alle. Python-Implementierungen arbeiten etwas schneller als PHP.
Middles: Fast sortiert
| Typ = fast, eindeutig = Wahr |
---|
Größe (min bis max) × Anzahl |
---|
100 (100 bis 999) × 100 | 1000 (1000 bis 9999) × 10 |
---|
Python | Php | Python | Php |
---|
 | 0,009 | 0,005 | 0,009 | 0,005 |
---|
 | 0,009 | 0,014 | 0,01 | 0,014 |
---|
 | 0,01 | 0,01 | 0,011 | 0,008 |
---|
 | 0,011 | 0,008 | 0,013 | 0,008 |
---|
 | 0,011 | 0,017 | 0,013 | 0,017 |
---|
Alle haben die gleichen Ergebnisse, plus oder minus. Aus dem Interessanten: Teilweise Datenbestellungen verbessern die Leistung aller Algorithmen dutzende Male.
Mitte: Rückseite
| Typ = umgekehrt, eindeutig = wahr |
---|
Größe (min bis max) × Anzahl |
---|
100 (100 bis 999) × 100 | 1000 (1000 bis 9999) × 10 |
---|
Python | Php | Python | Php |
---|
 | 0,26801 | 0,35902 | 3.10018 | 3.4292 |
---|
 | 0,39602 | 0,45303 | 4.49726 | 4.19524 |
---|
 | 0,22701 | 0,38402 | 2.48114 | 3.64421 |
---|
 | 0,30202 | 0,42603 | 3.34419 | 4,17524 |
---|
 | 0,30402 | 0,64404 | 3,36519 | 6.22036 |
---|
Es gibt eine interessante Schlussfolgerung: Die umgekehrte Reihenfolge wirkt sich nicht so stark auf die Geschwindigkeit aus, die im Vergleich zur Zufallszahl nur zweimal gesunken ist.
Mitte: Binär
| Typ = zufällig, eindeutig = falsch, min = 0, max = 1 |
---|
Größe × Anzahl |
---|
100 × 100 | 1000 × 10 |
---|
Python | Php | Python | Php |
---|
 | 0,073 | 0,094 | 0,81105 | 0,86905 |
---|
 | 0,10401 | 0,11301 | 1.16307 | 1,06606 |
---|
 | 0,08801 | 0,12901 | 0,86405 | 1.18207 |
---|
 | 0,11501 | 0,15001 | 1.30107 | 1.41608 |
---|
 | 0,11401 | 0,25801 | 1.31908 | 2.46314 |
---|
Von mehr oder weniger interessant: Wenn Sie anstelle von Zahlen von 100 bis 9999 Nullen und Einsen sortieren, werden die Geschwindigkeitsanzeigen nicht viel wachsen.
Champions
Die Hauptintrige dabei ist, ob das Sortieren mit einem Kamm und das K-Sortieren das Fasten vom Sockel drücken können.
Champions: Zufällig
Um dies herauszufinden, bilden wir Pakete mit zufälligen Arrays: 10 Teile mit 10.000 Elementen und 10 Teile mit 100.000 Elementen. Ich wollte den Eingabealgorithmen Millionäre geben, aber der Laptop zog nicht. Entweder ist nicht genügend RAM vorhanden, dann ist die Rekursionstiefe zu groß.
| Typ = zufällig, eindeutig = falsch, Anzahl = 10 |
---|
Größe (min bis max) |
---|
10000 (von 10000 bis 99999) | 100000 (von 100000 bis 999999) |
---|
Python | Php | Python | Php |
---|
 | 0,80205 | 0,63104 | 10.4506 | 8.24647 |
---|
 | 0,47703 | 1.64009 | 6.65138 | 26.5435 |
---|
 | 0,90005 | 2.18613 | 15.8089 | 29.4867 |
---|
Die Python K-Sortierung ist langsamer und PHP ist schneller als die schnelle Sortierung.
Das Sortieren des Kamms im Vergleich zum schnellen sieht solide aus, obwohl es in allen Tests (und in diesen und den folgenden) für alle Datensätze schlechter ist.
Es gibt jedoch Kämme und einen wichtigen unbestreitbaren Vorteil. Es hat keine Rekursion und verarbeitet daher im Gegensatz zu seinen Kollegen erfolgreich Arrays von Millionen von Elementen.
Sonderfälle
Obwohl Champions hunderte Male schneller sind als durchschnittliche Bauern, zeigen die Sortierungen bei bestimmten Datensätzen einfacher, dass sie nicht leicht zu nähen sind.
Sonderfälle: Fast sortiert
Versuchen wir es mit fast sortierten Arrays. Nehmen Sie einfach eine größere Größe als die, die für die durchschnittlichen Bauern getestet wurden.
Ein Paket von 10 Arrays mit jeweils 10 Tausend und ein Paket von 10 Arrays mit jeweils 100 Tausend Elementen.
| Typ = fast, eindeutig = Falsch |
---|
Größe (min bis max) × Anzahl |
---|
10000 (von 10000 bis 99999) × 10 | 100000 (von 100000 bis 999999) × 10 |
---|
Python | Php | Python | Php |
---|
 | 0,43202 | 0,058 | 0,81705 | 0,58003 |
---|
 | 0,084 | 0,062 | 0,85805 | 0,54003 |
---|
 | 0,11601 | 0,12401 | 1.41908 | 1.36008 |
---|
 | 0,14001 | 0,11901 | 1,83411 | 1.41708 |
---|
 | 0,13801 | 0,23101 | 1,6491 | 2,56915 |
---|
 | ? | 122.088 | ? | ? |
---|
 | 0,71504 | 1,58909 | 9,78356 | 19.4731 |
---|
Eine schnelle Sortierung ist hier überhaupt nicht vorhanden - es war nicht genügend RAM vorhanden. Gleichzeitig werden zufällige Arrays mit 10/100 Tausend Elementen von Quicksort mit einem Knall verarbeitet. k-sort stieß auf ähnliche Probleme und zog in PHP nur 10 Tausendstel. Große, fast sortierte Arrays sind ein entarteter Fall für eine schnelle Sortierung und deren Modifikationen. Aufgrund dieser Anordnung von Elementen teilt die Rekursion das Array für fast jedes Paar benachbarter Elemente in Teile, was zu der maximal möglichen Anzahl von Rekursionsaufrufen führt.
Bei großen Arrays in umgekehrter Reihenfolge ist die Situation übrigens ähnlich. Es tritt das gleiche Problem auf wie bei fast geordneten - der Algorithmus muss sich für jedes Paar benachbarter Elemente selbst aufrufen.
Sortieren nach einem Kamm, obwohl es eineinhalb bis zweimal langsamer als schnell oder k (im Allgemeinen) arbeitet, aber es hat nicht die oben genannten Speicherüberläufe. Keine Rekursion - kein Problem.
Nun, wir stellen fest, dass alle Mittelbauern zusammen die Champions in großen, fast sortierten Reihen überholten. Dann funktionierte das Prinzip: "Leise gehen - du wirst weitermachen."
Sonderfälle: Millionen scharlachrote Rosen kleiner Arrays
Kleine Arrays - das Element der Mittelbauern. Wenn Sie eine große Anzahl kleiner Zahlenmengen verarbeiten müssen, können Sie einen Zeitgewinn erzielen, indem Sie eine „primitive“ Blasen- oder Gnomensorte verwenden. Und verwenden Sie die schnelle Sortierung und ähnliche für größere Aufgaben.
| Typ = zufällig, eindeutig = Wahr |
---|
Größe (min bis max) × Anzahl |
---|
5 (10 bis 99) × 1.000.000 | 10 (10 bis 99) × 1.000.000 |
---|
Python | Php | Python | Php |
---|
 | 11.77267 | 17.888 | 24.29039 | 33.6659 |
---|
 | 12.51872 | 18.165 | 29.33268 | 35.202 |
---|
 | 15.44188 | 17.861 | 30.06672 | 36,7911 |
---|
 | 14.18681 | 19.7831 | 31.65981 | 39.3533 |
---|
 | 13.63978 | 24.3374 | 28.41662 | 52.864 |
---|
 | 14.21881 | 21.1452 | 25.80548 | 32,5419 |
---|
 | 14.58683 | 28.5016 | 24.85942 | 50,3139 |
---|
 | 18.53806 | 30.7238 | 29.6647 | 58.2493 |
---|
Bei Austauschsortierungen ist alles klar. Nun zum wirklich interessanten Teil - Sortieren nach Beilagen.
Referenzen
Excel-Anwendung AlgoLab , mit der Sie Schritt für Schritt die Visualisierung dieser (und nicht nur dieser) Sorten
anzeigen können.
Alle Arrays in Form von JSON sind auch auf der
Google-Festplatte angeordnet .
Wiki -
Dumm / Handlanger , Langsam , Zwerg / Gnom , Blase / Blase , Shaker / Shaker , Ungerade / Gerade , Kamm / Kamm , Schnell / SchnellSerienartikel