Usted está buscando un derangement de sus entradas.
En primer lugar, su algoritmo funciona en el sentido de que emite un trastorno aleatorio, es decir, una permutación sin punto fijo. Sin embargo, tiene un defecto enorme (que puede que no te importe, pero vale la pena tener en cuenta): no se pueden obtener algunas alteraciones con tu algoritmo. En otras palabras, da probabilidad cero a algunos posibles trastornos, por lo que la distribución resultante definitivamente no es uniformemente aleatoria.
Una posible solución, como se sugiere en los comentarios, sería el uso de un algoritmo de rechazo:
- recoger una permutación de manera uniforme al azar
- si Hax no hay puntos fijos, devuélvalo
- lo contrario reintento
Asintóticamente, la probabilidad de obtener un desarreglo está cerca de 1/e
= 0,3679 (como se ve en el artículo de Wikipedia). Lo que significa que para obtener un trastorno tendrá que generar un promedio de e
= 2.718 permutaciones, lo cual es bastante costoso.
Una mejor forma de hacerlo sería rechazar en cada paso del algoritmo. En pseudocódigo, algo como esto (suponiendo que la matriz original contiene i
en la posición i
, es decir a[i]==i
):
for (i = 1 to n-1) {
do {
j = rand(i, n) // random integer from i to n inclusive
} while a[j] != i // rejection part
swap a[i] a[j]
}
La principal diferencia con respecto a su algoritmo es que permitimos que j
para ser igual a i
, pero sólo si lo hace no produce un punto fijo Es un poco más largo de ejecutar (debido a la parte de rechazo), y exige que usted pueda verificar si una entrada está en su lugar original o no, pero tiene la ventaja de que puede producir todos los trastornos posibles (de manera uniforme, para ese importar).
Supongo que deberían existir algoritmos de no rechazo, pero creo que son menos directos.
Editar:
Mi algoritmo es realmente malo: usted todavía tiene la oportunidad de acabar con el último punto unshuffled, y la distribución no es al azar en todo, ver las distribuciones marginales de una simulación: ![marginal distributions](https://i.stack.imgur.com/yblIU.png)
Se puede encontrar un algoritmo que produce desarreglos uniformemente distribuidos here, con algún contexto sobre el problema, explicaciones y análisis completos.
Segunda Edición:
realidad su algoritmo se conoce como Sattolo's algorithm, y es conocido para producir todos los ciclos con igual probabilidad. Entonces cualquier desarreglo que no sea un ciclo sino un producto de varios ciclos disjuntos no se puede obtener con el algoritmo. Por ejemplo, con cuatro elementos, la permutación que intercambia 1 y 2, y 3 y 4 es un trastorno, pero no un ciclo.
Si no te importa obtener solo ciclos, entonces el algoritmo de Sattolo es el camino a seguir, en realidad es mucho más rápido que cualquier algoritmo de desarreglo uniforme, ya que no se necesita ningún rechazo.
Coloque cada elemento en otra posición al azar. Hay una pequeña posibilidad de que no puedas encontrar un puesto para el último pero luego vuelves a empezar. – adrianm
https://en.wikipedia.org/wiki/Sattolo's_algorithm – Bergi
Una recurrencia finita demostraría matemáticamente que su algoritmo funciona: al final de la iteración i, el elemento en la posición i ya no es el elemento original. Cuando en la iteración n-2, los datos [n-2] se barajan automáticamente con los datos [n-1]. Por lo tanto, si los datos [n-1] aún conservaban su valor original, se intercambian en la última iteración. Lo mismo ocurre con los datos [n-1]. – Rerito