Pathologische Sortierung

15

Pathologische Sortierung

Ihr Chef hat verlangt, dass Sie einen Sortieralgorithmus entwickeln, um die Leistung Ihrer Unternehmensanwendung zu verbessern. Nachdem Sie den Antrag geschrieben haben, wissen Sie, dass Sie ihn wahrscheinlich nicht wesentlich schneller machen können. Um Ihren Chef nicht zu enttäuschen, haben Sie sich entschlossen, einen neuen Algorithmus zu entwickeln, der noch besser funktioniert als das Sortieren bestimmter Datensätze. Natürlich können Sie nicht klar machen, dass der Algorithmus nur in einigen Fällen funktioniert, und Sie möchten ihn so dunkel wie möglich gestalten.

Ziel dieses Wettbewerbs ist es, eine Sortierroutine in der Sprache Ihrer Wahl zu schreiben, die bei bestimmten Datensätzen eine bessere Leistung als bei anderen erzielt und wiederholbare Ergebnisse liefert. Je genauer die Klassifizierung ist, die die Geschwindigkeit bestimmt, desto besser. Der Algorithmus muss in irgendeiner Weise sortieren, sodass ein Algorithmus, der davon abhängt, dass die Daten bereits vollständig sortiert sind (wie bei einem Algorithmus, der nichts tut), oder ein Algorithmus, der davon abhängt, dass die Daten vollständig in umgekehrter Reihenfolge sortiert sind, beide ungültig sind. Der Sortieralgorithmus muss alle Datensätze korrekt sortieren.

Geben Sie nach der Vorstellung Ihrer Routine eine Erklärung an, warum dies nur für bestimmte Datensätze funktioniert, und führen Sie Testläufe für mindestens einen Satz guter (schneller) und einen Satz schlechter (langsamer) Daten durch. Hier geht es darum, Ihrem Chef zu beweisen, dass Sie auf eine bessere Sortiermethode gestoßen sind, sodass mehr Testdaten besser sind. Natürlich zeigen Sie Ihrem Chef nur die Testergebnisse aus den guten Daten, sodass der Fehler in den erforderlichen Testdaten nicht zu offensichtlich sein kann. Falls für Ihre Sprache zutreffend, zeigen Sie bitte, dass Ihr Algorithmus schneller ist als der in Ihrer Sprache integrierte Sortieralgorithmus.

Beispielsweise könnte man einen Einfügungssortierungsalgorithmus einreichen, wobei die guten Daten Daten sind, die bereits nahezu sortiert sind, und die schlechten Daten vollständig zufällige Daten sind, da die Einfügungssortierung bei nahezu sortierten Daten gegen O (n) geht. Dies ist jedoch nicht sehr gut, da mein Chef wahrscheinlich bemerken würde, dass alle Testdaten von Anfang an fast sortiert sind.

Dies ist ein , daher gewinnt die Antwort mit den meisten Stimmen nach 7 Tagen (21. Mai).

Wenn mich niemand schlägt, möchte ich eine Community-Wiki-Antwort einreichen, die gleichmäßig verteilte Datensätze nutzt.

Millinon
quelle
Möglicherweise nützliche / interessante Ressource für diejenigen, die sich dieser Frage nähern: "Psychic Sorting Algorithms" (Haftungsausschluss: Der Autor dieses Artikels und ich stehen uns sehr nahe. :-P)
Dr. Rebmu

Antworten:

9

Es ist eine ziemlich lange Zeit her, aber ich erinnere mich, dass wir in Algorithmus 101 einen Sortieralgorithmus gelernt haben, der Zufallsgenerierung verwendete. Ich war kein sehr guter Schüler und kann mich nicht wirklich erinnern, wie es gelaufen ist oder warum es im Durchschnitt schnell funktioniert hat.

Trotzdem habe ich beschlossen, dass dieses Problem eine Lösung erfordert, die Randomisierung verwendet, was hoffentlich im Durchschnitt zu meinen Gunsten funktioniert.

import random

def arrayIsSorted (arr) :
    for i in range(len(arr)-1) :
        if arr[i]>arr[i+1] : return False
    return True

def rSort (arr) :
    random.seed (42)
    counter = 0
    while not arrayIsSorted(arr) :
        random.shuffle (arr)
        counter+=1
    print ("Sorted in %d iterations." % counter)
    return arr

Da echte Randomisierung wichtig ist, stelle ich sicher, dass der RNG die Antwort auf das Leben, das Universum und alles enthält. Nach einigem Testen stellte sich heraus, dass dies ein kluger Schachzug war! Überprüfen Sie, wie schnell diese 2 völlig willkürlichen Listen sortiert werden:

rSort ([6,1,4,2,3,7,5])
rSort ([8,9,6,1,4,7,2,3,5])

Beides wird in nur 1 Iteration sortiert - eine schnellere Funktion kann man sich nicht wünschen!

Zugegeben, einige andere Listen führen zu etwas schlechteren Ergebnissen ...

rSort ([5,1,4,2,3,7,6])
rSort ([8,9,6,1,4,7,2,5,3])

Diese werden in 4.176 bzw. 94.523 Iterationen sortiert, was tatsächlich mehr als eine Sekunde dauert ... aber lassen Sie uns diese Tatsache einfach für uns behalten, um niemanden davon abzulenken, wie erstaunlich dieser Algorithmus ist!

Bearbeiten:

Ich wurde gebeten, die Effizienz meines Algorithmus auf einer Liste mit 100 Elementen zu beweisen.

rSort ([70, 6, 52, 97, 85, 61, 62, 48, 30, 3, 11, 88, 39, 91, 98, 8, 54, 92, 44, 65, 69, 21, 58, 41, 60, 76, 27, 82, 93, 81, 20, 94, 22, 29, 49, 95, 40, 19, 55, 42, 43, 1, 0, 67, 35, 15, 51, 31, 16, 25, 5, 53, 37, 74, 86, 12, 13, 72, 56, 32, 47, 46, 59, 33, 80, 4, 45, 63, 57, 89, 7, 77, 14, 10, 34, 87, 18, 79, 9, 66, 24, 99, 64, 26, 78, 38, 90, 28, 83, 75, 68, 2, 17, 73, 96, 71, 23, 84, 36, 50])

Auch diese lange und völlig willkürliche Liste wird sofort sortiert! Wahrlich, ich muss über den besten Sortieralgorithmus der Welt gestolpert sein!

Tal
quelle
3
Können wir einige Testergebnisse für etwas größere Datensätze erhalten? Vielleicht eines mit 100 Elementen? ;)
Geobits
@ Geobits Kein Problem, hier ist es :)
Tal
1
@ Geobits Ja, das tut es. Schließlich.
Tal
3
Es ist eine Strecke, aber es könnte argumentiert werden, dass es Bogosort verwendet, der schließlich das Array sortieren wird, wenn genügend Zeit zur Verfügung steht. Ich bin bereit zu wetten, dass "Shuffle and Repeat" als Fehlsortierung qualifiziert ist, wenn auch nicht als gute Sortierung.
Millinon
1
Wenn es sich um zufälliges Mischen handelte, vielleicht. PRNGs haben einen Zyklus, daher kann ich nicht sehen, wie Sie garantieren können, dass alle Permutationen ausprobiert werden.
Geobits
2

Wenn Sie Ihre eigenen Daten erstellen können, ist dies recht einfach: Sie erhalten Daten, die zufällig aussehen, aber einen Schlüssel für eine schnellere Sortierung enthalten. Alle anderen Daten verwenden die ursprüngliche Sortiermethode, sodass die Durchschnittszeiten besser sind.

Eine einfache Möglichkeit besteht darin, sicherzustellen, dass jedes Datenelement einen eindeutigen Schlüssel hat, und dann nur die Schlüssel zu hashen. Nehmen Sie zum Beispiel eine Liste mit den Zahlen von 1-10.000, alle multipliziert mit 16, und mit einer Zufallszahl von 0-15 (siehe fillArray () unten). Sie sehen zufällig aus, aber jeder hat einen eindeutigen sequenziellen Schlüssel. Teilen Sie zum Sortieren durch 16 (in C ist die >> 4 sehr schnell) und platzieren Sie dann die Zahl in einem Array, wobei Sie den resultierenden Schlüssel als Index verwenden. Ein Pass und du bist fertig. Beim Testen stellte ich fest, dass Quicksort bei zehn Millionen Nummern 30-mal langsamer war.

void fillArray(int *a,int len)
{
  for (int i=0;i<len;++i)
    a[i]=(i<<4)|(rand()&0xF);
  // shuffle later
}
void sortArray(int *a,int len)
{
  int key=0;
  int *r=new int[len];
  for (int i=0;i<len;++i)
  {
    key=a[i]>>4;
    r[key]=a[i];
  }
  memcpy(a,r,len*sizeof(int));
  delete[] r;
}
void shuffleArray(int *a,int len)
{
  int swap=0, k=0;
  for (int i=0;i<len;++i)
  {
    k=rand()%len;
    swap=a[k];
    a[k]=a[i];
    a[i]=swap;
  }
}
int qCompare(const void*a,const void*b)
{
  int result=*((int*)a)-*((int*)b);
  return result;
}
void main()
{
  int aLen=10000;
  int *a=new int[aLen];
  srand (time(NULL));
  fillArray(a,aLen);
  // time them
  long t0=0, d0=0, d1=0;
  // qsort
  shuffleArray(a,aLen);
  t0=::GetTickCount();
  qsort(a,aLen,sizeof(int),&qCompare);
  d0=::GetTickCount()-t0;
  // oursort
  shuffleArray(a,aLen);
  t0=::GetTickCount();
  sortArray(a,aLen);
  d1=::GetTickCount()-t0;
  delete[] a;
}

Alles, was einen eindeutigen Schlüssel hat, kann auf diese Weise sortiert werden - wenn Sie den Speicher zum Speichern haben, natürlich. Zum Beispiel verwenden viele Datenbanken eine eindeutige numerische Kunden-ID. Wenn die Liste klein oder sequenziell genug ist, kann sie im Speicher gespeichert werden. Oder eine andere Möglichkeit, einen Datensatz in eine eindeutige Nummer zu übersetzen. Weitere Informationen finden Sie unter Hash Sorts.

Dave P.
quelle