Ausgehend von diesem Zitat von Skeet:
Es ist keine Art zu mischen, die ich mag, hauptsächlich mit der Begründung, dass es O (n log n) ist, ohne guten Grund, wenn es einfach ist, ein O (n) Mischen zu implementieren. Der Code in der Frage "funktioniert", indem er jedem Element eine zufällige ( hoffentlich eindeutige! ) Nummer gibt und die Elemente dann nach dieser Nummer ordnet.
Ich werde ein wenig den Grund für das hoffentlich Einzigartige erklären !
Nun aus dem Enumerable.OrderBy :
Diese Methode führt eine stabile Sortierung durch. Das heißt, wenn die Schlüssel zweier Elemente gleich sind, bleibt die Reihenfolge der Elemente erhalten
Dies ist sehr wichtig! Was passiert, wenn zwei Elemente dieselbe Zufallszahl "erhalten"? Es kommt vor, dass sie in derselben Reihenfolge bleiben, in der sie sich im Array befinden. Was ist nun die Möglichkeit dafür? Es ist schwierig, genau zu berechnen, aber es gibt das Geburtstagsproblem , das genau dieses Problem ist.
Ist es jetzt real? Ist es wahr?
Wie immer schreiben Sie im Zweifelsfall einige Programmzeilen: http://pastebin.com/5CDnUxPG
Dieser kleine Codeblock mischt ein Array von 3 Elementen eine bestimmte Anzahl von Malen, wobei der Fisher-Yates-Algorithmus rückwärts und der Fisher-Yates-Algorithmus vorwärts ausgeführt wird (auf der Wiki- Seite gibt es zwei Pseudocode-Algorithmen ... Sie erzeugen Äquivalente Ergebnisse, aber eines wird vom ersten bis zum letzten Element ausgeführt, während das andere vom letzten bis zum ersten Element ausgeführt wird), der naive falsche Algorithmus von http://blog.codinghorror.com/the-danger-of-naivete/ und unter Verwendung des .OrderBy(x => r.Next())
und die .OrderBy(x => r.Next(someValue))
.
Nun Random.Next ist
Eine 32-Bit-Ganzzahl mit Vorzeichen, die größer oder gleich 0 und kleiner als MaxValue ist.
also ist es gleichbedeutend mit
OrderBy(x => r.Next(int.MaxValue))
Um zu testen, ob dieses Problem besteht, können wir das Array vergrößern (etwas sehr Langsames) oder einfach den Maximalwert des Zufallszahlengenerators verringern ( int.MaxValue
keine "spezielle" Zahl ... Es ist einfach eine sehr große Zahl). Wenn der Algorithmus nicht durch die Stabilität von verzerrt ist, sollte letztendlich OrderBy
jeder Wertebereich das gleiche Ergebnis liefern.
Das Programm testet dann einige Werte im Bereich von 1 bis 4096. Wenn man das Ergebnis betrachtet, ist es ziemlich klar, dass der Algorithmus für niedrige Werte (<128) sehr voreingenommen ist (4-8%). Mit 3 Werten benötigen Sie mindestens r.Next(1024)
. Wenn Sie das Array größer machen (4 oder 5), r.Next(1024)
reicht es nicht einmal aus. Ich bin kein Experte für Mischen und Mathematik, aber ich denke, dass Sie für jedes zusätzliche Bit der Länge des Arrays 2 zusätzliche Bits des Maximalwerts benötigen (da das Geburtstagsparadoxon mit dem sqrt (numvalues) verbunden ist) Wenn der Maximalwert 2 ^ 31 ist, sollten Sie in der Lage sein, Arrays mit bis zu 2 ^ 12/2 ^ 13 Bits (4096-8192 Elemente) zu sortieren.