it-swarm.com.de

Gibt es schlechtere Sortieralgorithmen als Bogosort (a.k.a Monkey Sort)?

Meine Mitarbeiter haben mich heute Morgen mit einer Diskussion über Sortieralgorithmen in die Zeit meiner Universität zurückversetzt. Wir erinnerten uns an unsere Favoriten wie StupidSort , und einer von uns war sich sicher, dass wir einen Sortieralgorithmus gesehen hatten, der O(n!) war. Das brachte mich dazu, mich nach den "schlechtesten" Sortieralgorithmen umzusehen, die ich finden konnte.

Wir postulierten, dass eine völlig zufällige Sortierung ziemlich schlecht wäre (dh die Elemente zufällig sortieren - ist es in Ordnung? Nein? Erneut zufällig sortieren), und ich sah mich um und fand heraus, dass sie anscheinend BogoSort heißt. oder Monkey Sort oder manchmal nur Random Sort .

Monkey Sort hat anscheinend die schlechteste Fallleistung von O(∞), die beste Fallleistung von O(n) und die durchschnittliche Leistung von O(n·n!).

Gibt es benannte Algorithmen, die eine schlechtere durchschnittliche Leistung haben als O(n·n!)? Oder sind sie einfach alberner als Monkey Sort im Allgemeinen?

163
womp

Aus der Seite David Morgan-Mar 's Esoteric Algorithms: Intelligent Design Sort

Einführung

Intelligent Design Sort ist ein Sortieralgorithmus, der auf der Theorie des intelligenten Designs basiert.

Beschreibung des Algorithmus

Die Wahrscheinlichkeit, dass sich die ursprüngliche Eingabeliste in der exakten Reihenfolge befindet, ist 1/(n!). Es ist so unwahrscheinlich, dass es offensichtlich absurd ist zu sagen, dass dies zufällig passiert ist, also muss es von einem intelligenten Sortierer bewusst in diese Reihenfolge gebracht worden sein. Daher kann man davon ausgehen, dass es bereits in irgendeiner Weise optimal sortiert ist, was unser naives sterbliches Verständnis von "aufsteigender Ordnung" übersteigt. Jeder Versuch, diese Reihenfolge zu ändern, um sie an unsere eigenen Vorurteile anzupassen, würde sie weniger sortiert machen.

Analyse

Dieser Algorithmus ist zeitlich konstant und sortiert die Liste direkt, ohne dass zusätzlicher Speicher erforderlich ist. Tatsächlich erfordert es nicht einmal verdächtiges technologisches Computerzeug. Loben Sie den Sorter!

Feedback

Gary Rogers schreibt:

Wenn Sie die Sortierung zeitlich konstant halten, wird die Leistung von The Sorter beeinträchtigt. Der Sorter existiert außerhalb der Zeit, daher ist die Sortierung zeitlos. Wenn Sie Zeit benötigen, um die Sortierung zu validieren, wird die Rolle des Sortierers beeinträchtigt. Also ... diese besondere Sorte ist fehlerhaft und kann nicht 'The Sorter' zugeordnet werden.

Ketzerei!

424
BioGeek

Vor vielen Jahren habe ich MiracleSort erfunden (aber nie implementiert).

Start with an array in memory.
loop:
    Check to see whether it's sorted.
    Yes? We're done.
    No? Wait a while and check again.
end loop

Schließlich sollten Alpha-Partikel, die Bits in den Speicherchips umdrehen, zu einer erfolgreichen Sortierung führen.

Um eine höhere Zuverlässigkeit zu erzielen, kopieren Sie das Array an einen abgeschirmten Ort und vergleichen Sie die potenziell sortierten Arrays mit dem Original.

Wie können Sie das potenziell sortierte Array mit dem Original vergleichen? Sie sortieren einfach jedes Array und prüfen, ob sie übereinstimmen. MiracleSort ist der naheliegende Algorithmus für diesen Schritt.

EDIT: Genau genommen handelt es sich nicht um einen Algorithmus, da dessen Beendigung nicht garantiert ist. Qualifiziert sich "kein Algorithmus" als "schlechterer Algorithmus"?

289
Keith Thompson

Quantum Bogosort

Ein Sortieralgorithmus, der davon ausgeht, dass die Vielwelteninterpretation der Quantenmechanik korrekt ist:

  1. Überprüfen Sie, ob die Liste sortiert ist. Wenn nicht, zerstöre das Universum.

Am Ende des Algorithmus wird die Liste in dem einzigen verbleibenden Universum sortiert. Dieser Algorithmus benötigt im schlimmsten Fall O(N) und im Durchschnitt O(1) Zeit. Tatsächlich beträgt die durchschnittliche Anzahl der durchgeführten Vergleiche 2: Es gibt eine 50% ige Chance, dass das Universum beim zweiten Element zerstört wird, eine 25% ige Chance, dass es beim dritten Element zerstört wird und so weiter.

128
BioGeek

Ich bin überrascht, dass noch niemand von Schlafort gesprochen hat ... Oder habe ich es nicht bemerkt? Sowieso:

#!/bin/bash
function f() {
    sleep "$1"
    echo "$1"
}
while [ -n "$1" ]
do
    f "$1" &
    shift
done
wait

beispielverwendung:

./sleepsort.sh 5 3 6 3 6 3 1 4 7
./sleepsort.sh 8864569 7

In Bezug auf die Leistung ist es schrecklich (vor allem das zweite Beispiel). Fast 3,5 Monate warten, um 2 Zahlen zu sortieren, ist ein bisschen schlecht.

55
Kw4s

Jingle Sort, wie beschrieben hier .

Sie geben jeden Wert in Ihrer Liste an Weihnachten einem anderen Kind. Kinder, die schreckliche Menschen sind, werden den Wert ihrer Gaben vergleichen und sich entsprechend sortieren.

55
Curtis Lassam

Ich hatte einen Dozenten, der einmal vorschlug, ein zufälliges Array zu generieren, zu überprüfen, ob es sortiert ist und dann zu überprüfen, ob die Daten mit den zu sortierenden Arrays übereinstimmen.

Bester Fall O(N) (erstes Mal Baby!) Schlimmster Fall O (Nie)

47
Daniel

Wenn Sie den Algorithmus in irgendeiner Weise aussagekräftig halten, ist O(n!) die schlechteste Obergrenze, die Sie erreichen können.

Da das Prüfen jeder Möglichkeit, dass Permutationen eines Satzes sortiert werden, Schritte n! Erfordert, können Sie nichts Schlimmeres tun.

Wenn Sie mehr Schritte ausführen, hat der Algorithmus keinen wirklich nützlichen Zweck. Ganz zu schweigen vom folgenden einfachen Sortieralgorithmus mit O(infinity):

list = someList
while (list not sorted):
    doNothing
30
Yuval Adam

Sie sollten sich mit dem spannenden Gebiet Pessimalalgorithmen und Simplexitätsanalyse befassen. Diese Autoren arbeiten an dem Problem, eine Sortierung mit einem pessimalen Best-Case zu entwickeln (Ihr Bogosort-Best-Case ist Omega (n), während Slowsort (siehe Papier) eine nicht-polynomielle Best-Case-Zeitkomplexität aufweist).

19
Derrick Turk

Bogobogosort. Ja, das ist eine Sache. nach Bogobogosort, du Bogosort das erste Element. Überprüfen Sie, ob dieses eine Element sortiert ist. Als ein Element wird es sein. Dann fügst du das zweite Element hinzu und Bogosort diese beiden, bis es sortiert ist. Dann fügen Sie ein weiteres Element hinzu, dann Bogosort. Fügen Sie weitere Elemente und Bogosorting hinzu, bis Sie alle Elemente fertiggestellt haben. Dies war so konzipiert, dass es vor dem Tod des Universums mit keiner größeren Liste zum Erfolg kam.

17
Playnwinplayer

Hier sind 2 Sorten, die ich mir mit meinem Mitbewohner in der Schule ausgedacht habe

1) Überprüfen Sie die Reihenfolge 2) Vielleicht ist ein Wunder passiert, gehen Sie zu 1

und

1) überprüfe, ob es in Ordnung ist, wenn nicht 2) setze jedes Element in ein Paket und bringe es von einem entfernten Server zu dir zurück. Einige dieser Pakete werden in einer anderen Reihenfolge zurückgegeben. Fahren Sie mit Schritt 1 fort

16
Seth

Es gibt eine Sorte, die Bogobogosort heißt. Zuerst werden die ersten beiden Elemente überprüft und falsch sortiert. Als nächstes werden die ersten 3 überprüft, falsch sortiert und so weiter. Sollte die Liste zu irgendeinem Zeitpunkt nicht in Ordnung sein, startet sie neu, indem die ersten 2 erneut falsch sortiert werden. Regulärer Bogosort hat eine durchschnittliche Komplexität von O (N!), Dieser Algorithmus hat eine durchschnittliche Komplexität von O (N! 1! 2! 3! ... N!) Für 20 Elemente dauert dieser Algorithmus im Durchschnitt 3,930093 * 10 ^ 158 Jahre und liegt damit weit über dem vorgeschlagenen Hitzetod des Universums (falls er auftritt) von 10 ^ 100 Jahren, während die Sortierung beim Zusammenführen etwa 0,0000004 Sekunden dauert, bei der Blasensortierung 0,0000016 Sekunden, und Bogosort dauert 308 Jahre, 139 Tage, 19 Stunden, 35 Minuten, 22,306 Sekunden, vorausgesetzt, ein Jahr ist 365,242 Tage und ein Computer führt 250.000.000 32-Bit-Ganzzahloperationen pro Sekunde aus. Edit2: Dieser Algorithmus ist nicht so langsam wie die "Algorithmus" -Wunder-Sortierung, die wahrscheinlich, wie diese Sortierung, den Computer in das Schwarze Loch saugen lässt, bevor er 20 Elemente erfolgreich sortiert, aber wenn dies der Fall wäre, würde ich eine durchschnittliche Komplexität schätzen von 2 ^ (32 (die Anzahl der Bits in einer 32-Bit-Ganzzahl) N) (die Anzahl der Elemente) (eine Zahl <= 10 ^ 40 Jahre, da die Schwerkraft die Alpha-Bewegung der Chips beschleunigt, und es gibt 2 ^ N Zustände, die 2 ^ 640 * 10 ^ 40 oder ungefähr 5,783 * 10 ^ 216,762162762 Jahre sind, obwohl, wenn die Liste sortiert anfängt, ihre Komplexität nur O (N) ist, schneller als die Zusammenführungssortierung, Das ist auch im schlimmsten Fall nur N log N. Edit3: Dieser Algorithmus ist tatsächlich langsamer als die Wundersorte, da die Größe sehr groß wird, sagen wir 1000, da mein Algorithmus eine Laufzeit von 2,83 * 10 ^ 1175546 Jahren hätte, während die Der Algorithmus für die Wundersortierung hätte eine Laufzeit von 1,156 * 10 ^ 9657 Jahren.

14
bacca2002

Es gibt immer den Bogobogosort (Bogoception!). Es führt Bogosort für immer größere Teilmengen der Liste aus und beginnt dann von vorne, wenn die Liste jemals nicht sortiert wurde.

for (int n=1; n<sizeof(list); ++n) {
  while (!isInOrder(list, 0, n)) {
    shuffle(list, 0, n);
  }
  if (!isInOrder(list, 0, n+1)) { n=0; }
}
14
IceMetalPunk

1 Legen Sie Ihre Artikel zum Sortieren auf Karteikarten
2 Werfen Sie sie an einem windigen Tag, eine Meile von Ihrem Haus entfernt, in die Luft.
2 Werfen Sie sie in ein Lagerfeuer und bestätigen Sie, dass sie vollständig zerstört sind.
3 Überprüfen Sie Ihren Küchenboden auf die richtige Bestellung.
4 Wiederholen Sie diesen Vorgang, wenn die Reihenfolge nicht korrekt ist.

Bestes Szenario ist O (∞)

Bearbeiten oben basierend auf der scharfsinnigen Beobachtung von KennyTM.

10
Patrick Karcher

Das "Was möchten Sie es sein?" Sortieren

  1. Notieren Sie die Systemzeit.
  2. Sortieren Sie mit Quicksort (oder einem anderen vernünftigen Wert) und lassen Sie dabei den letzten Tausch aus.
  3. Notieren Sie die Systemzeit.
  4. Berechnen Sie die benötigte Zeit. Erweiterte Präzisionsarithmetik ist eine Voraussetzung.
  5. Warten Sie die erforderliche Zeit.
  6. Führen Sie den letzten Tausch durch.

Es kann nicht nur jeden denkbaren Wert von O(x) unendlich implementieren, die benötigte Zeit ist auch nachweislich korrekt (wenn Sie so lange warten können).

9
david.pfx

Nichts kann schlimmer sein als die Unendlichkeit.

7

Segmente von π

Angenommen, π enthält alle möglichen endlichen Zahlenkombinationen. Siehe math.stackexchange question

  1. Bestimmen Sie die Anzahl der benötigten Stellen anhand der Größe des Arrays.
  2. Verwenden Sie Segmente von π-Stellen als Indizes, um zu bestimmen, wie das Array neu angeordnet werden soll. Wenn ein Segment die Größengrenzen für dieses Array überschreitet, passen Sie den π-Dezimalversatz an und beginnen Sie von vorne.
  3. Überprüfen Sie, ob das neu geordnete Array sortiert ist. Wenn es woot ist, passen Sie den Offset an und fangen Sie von vorne an.
5
CrashCodes

Bozo-Sortierung ist ein verwandter Algorithmus, der überprüft, ob die Liste sortiert ist, und, falls nicht, zwei Elemente nach dem Zufallsprinzip vertauscht. Es hat die gleichen besten und schlechtesten Fallleistungen, aber ich würde intuitiv erwarten, dass der durchschnittliche Fall länger als Bogosort ist. Es ist schwierig, Daten zur Leistung dieses Algorithmus zu finden (oder zu produzieren).

5
tloflin

Eine Worst-Case-Performance von O (∞) könnte es nicht einmal zu einem Algorithmus nach some machen.

Ein Algorithmus besteht nur aus einer Reihe von Schritten, und Sie können immer noch Schlimmeres tun, indem Sie ihn ein wenig optimieren, um die gewünschte Ausgabe in mehr Schritten als bisher zu erzielen. Man könnte das Wissen über die Anzahl der Schritte, die in den Algorithmus eingegeben wurden, absichtlich beenden und die korrekte Ausgabe erst dann erzeugen, wenn X Anzahl der Schritte ausgeführt wurde. Das X könnte sehr gut in der Größenordnung von O (n2) oder O (nn!) oder was auch immer der Algorithmus tun wollte. Dies würde effektiv sowohl die Best-Case- als auch die durchschnittlichen Fallgrenzen erhöhen.

Aber Ihr Worst-Case-Szenario kann nicht übertroffen werden :)

4
Anurag
Recursive Bogosort (probably still O(n!){
if (list not sorted)
list1 = first half of list.
list 2 = second half of list.
Recursive bogosort (list1);
Recursive bogosort (list2);
list = list1 + list2
while(list not sorted)
    shuffle(list);
}
3
user3667082

Mein Lieblingsalgorithmus für langsames Sortieren ist das Stooge-Sortieren:

void stooges(long *begin, long *end) {
   if( (end-begin) <= 1 ) return;
   if( begin[0] < end[-1] ) swap(begin, end-1);
   if( (end-begin) > 1 ) {
      int one_third = (end-begin)/3;
      stooges(begin, end-one_third);
      stooges(begin+one_third, end);
      stooges(begin, end-one_third);
   }
}

Die Komplexität im schlimmsten Fall ist O(n^(log(3) / log(1.5))) = O(n^2.7095...).

Ein anderer langsamer Sortieralgorithmus heißt tatsächlich slowsort!

void slow(long *start, long *end) {
   if( (end-start) <= 1 ) return;
   long *middle = start + (end-start)/2;
   slow(start, middle);
   slow(middle, end);
   if( middle[-1] > end[-1] ) swap(middle-1, end-1);
   slow(start, end-1);
}

Dieser nimmt im besten Fall O(n ^ (log n)) ... sogar langsamer als stoogesort.

3
Ben Goldberg

Diese Seite ist eine interessante Lektüre zum Thema: http://home.tiac.net/~cri_d/cri/2001/badsort.html

Mein persönlicher Favorit ist Tom Duffs Sillysort:

/*
 * The time complexity of this thing is O(n^(a log n))
 * for some constant a. This is a multiply and surrender
 * algorithm: one that continues multiplying subproblems
 * as long as possible until their solution can no longer
 * be postponed.
 */
void sillysort(int a[], int i, int j){
        int t, m;
        for(;i!=j;--j){
                m=(i+j)/2;
                sillysort(a, i, m);
                sillysort(a, m+1, j);
                if(a[m]>a[j]){ t=a[m]; a[m]=a[j]; a[j]=t; }
        }
}
2
fsanches

Doppelte Bogosort

Bogosort zweimal und vergleichen Sie die Ergebnisse (nur um sicherzugehen, dass sie sortiert sind), wenn Sie es nicht noch einmal tun

2
Viktor Mellgren

Bei einem Punkt, an dem ich gerade gearbeitet habe, werden zwei zufällige Punkte ausgewählt. Wenn sie in der falschen Reihenfolge sind, wird der gesamte Unterbereich zwischen ihnen umgekehrt. Ich habe den Algorithmus auf http://richardhartersworld.com/cri_d/cri/2001/badsort.html gefunden, der besagt, dass der Durchschnittsfall wahrscheinlich irgendwo bei O (n ^ 3) oder O (liegt. n ^ 2 log n) (er ist sich nicht wirklich sicher).

Ich denke, es könnte möglich sein, es effizienter zu machen, weil ich denke, es könnte möglich sein, die Umkehroperation in O(1) Zeit zu machen.

Eigentlich habe ich gerade gemerkt, dass das alles, was ich sage, zu dem Ergebnis führen würde, dass ich gerade gemerkt habe, dass die Datenstruktur, die ich mir vorgenommen habe, den Zugriff auf die zufälligen Elemente auf O (log n) setzt und feststellt, ob sie bei O (n) umgekehrt werden müssen ).

1
AJMansfield

Sie können jeden Sortieralgorithmus verlangsamen, indem Sie Ihren Schritt "Ist es sortiert" nach dem Zufallsprinzip ausführen. So etwas wie:

  1. Erstellen Sie ein Array mit Booleschen Werten in der Größe des Arrays, das Sie sortieren. Setzen Sie sie alle auf false.
  2. Führen Sie eine Iteration von Bogosort aus
  3. Wähle zwei zufällige Elemente.
  4. Wenn die beiden Elemente in Bezug zueinander sortiert sind (i <j && array [i] <array [j]), markieren Sie die Indizes beider Elemente im booleschen Array als true. Beginnen Sie übersinnlich von vorne.
  5. Überprüfen Sie, ob alle Booleschen Werte im Array wahr sind. Wenn nicht, gehe zurück zu 3.
  6. Getan.
1
Brendan Long

Randomsubsetsort.

Wählen Sie bei einem Array mit n Elementen jedes Element mit einer Wahrscheinlichkeit von 1/n aus, ordnen Sie diese Elemente nach dem Zufallsprinzip an und überprüfen Sie, ob das Array sortiert ist. Wiederholen, bis sortiert.

Die erwartete Zeit bleibt dem Leser als Übung.

1

Ja, SimpleSort, theoretisch läuft es in O(-1), aber das ist äquivalent zu O(...9999) , was wiederum äquivalent zu O (∞ - 1) ist, was als es kommt auch gleichbedeutend mit O (∞). Hier ist meine Beispielimplementierung:

/* element sizes are uneeded, they are assumed */
void
simplesort (const void* begin, const void* end)
{
  for (;;);
}
1
Joe D