A partir de esta cita de Skeet:
No es una forma de barajar que me gusta, sobre todo porque es O (n log n) sin ninguna razón cuando es fácil implementar una baraja O (n). El código en la pregunta "funciona" básicamente dando un número aleatorio (¡con suerte único! ) A cada elemento, luego ordenando los elementos de acuerdo con ese número.
¡Seguiré explicando un poco la razón de lo que es de esperar único!
Ahora, desde el Enumerable.OrderBy :
Este método realiza una ordenación estable; es decir, si las claves de dos elementos son iguales, se preserva el orden de los elementos
¡Esto es muy importante! ¿Qué sucede si dos elementos "reciben" el mismo número aleatorio? Sucede que permanecen en el mismo orden en que están en la matriz. Ahora, ¿cuál es la posibilidad de que esto suceda? Es difícil calcular exactamente, pero existe el problema de cumpleaños que es exactamente este problema.
Ahora, ¿es real? ¿Es verdad?
Como siempre, en caso de duda, escriba algunas líneas de programa: http://pastebin.com/5CDnUxPG
Este pequeño bloque de código baraja una serie de 3 elementos una cierta cantidad de veces usando el algoritmo de Fisher-Yates hecho hacia atrás, el algoritmo de Fisher-Yates hecho hacia adelante (en la página wiki hay dos algoritmos de pseudocódigo ... Producen equivalentes resultados, pero uno se realiza del primer al último elemento, mientras que el otro se realiza del último al primer elemento), el ingenuo algoritmo incorrecto de http://blog.codinghorror.com/the-danger-of-naivete/ y el uso de .OrderBy(x => r.Next())
y el .OrderBy(x => r.Next(someValue))
.
Ahora, Random.Next es
Un entero con signo de 32 bits que es mayor o igual a 0 y menor que MaxValue.
entonces es equivalente a
OrderBy(x => r.Next(int.MaxValue))
Para probar si este problema existe, podríamos agrandar la matriz (algo muy lento) o simplemente reducir el valor máximo del generador de números aleatorios ( int.MaxValue
no es un número "especial" ... Es simplemente un número muy grande). Al final, si el algoritmo no está sesgado por la estabilidad del OrderBy
, entonces cualquier rango de valores debería dar el mismo resultado.
Luego, el programa prueba algunos valores, en el rango de 1 ... 4096. Mirando el resultado, está bastante claro que para valores bajos (<128), el algoritmo es muy sesgado (4-8%). Con 3 valores necesitas al menos r.Next(1024)
. Si hace que la matriz sea más grande (4 o 5), incluso r.Next(1024)
no es suficiente. No soy un experto en barajar y en matemáticas, pero creo que por cada bit adicional de longitud de la matriz, necesitas 2 bits adicionales de valor máximo (porque la paradoja del cumpleaños está conectada al sqrt (valores numéricos)), entonces que si el valor máximo es 2 ^ 31, diré que debería poder ordenar matrices de hasta 2 ^ 12/2 ^ 13 bits (4096-8192 elementos)