¿Cuál es una buena explicación del algoritmo de Floyd y el algoritmo de Brent para la búsqueda de ciclos?

La detección de ciclos en Wikipedia tiene una excelente analogía para esto, basada en la fábula de la carrera entre la tortuga y la liebre. Tenga en cuenta que a menudo hay dos etapas para un algoritmo de búsqueda de ciclo; primero, detecta un ciclo (al encontrar dos índices [matemática] i, j [/ matemática] tal que [matemática] x_i = x_j [/ matemática]), y luego, tal vez, desee encontrar valores mínimos [matemática] \ mu, \ lambda [/ math] tal que [math] x_ {i + k \ lambda} = x_i [/ ​​math] para todos los números naturales [math] k [/ math] y [math] i \ geq \ mu [ /matemáticas]. Centrémonos en la parte de detección; Una vez que haya encontrado un ciclo, es mucho más fácil encontrar los valores mínimos.

La estrategia es primero poner en marcha la ‘liebre’, que revisará los datos rápidamente, y detrás de él, la ‘tortuga’, que examinará los datos más lentamente. Si la tortuga y la liebre alguna vez están de acuerdo, has detectado un ciclo.

El algoritmo de Floyd es el más simple. Comience la tortuga y la liebre en la posición cero, luego, en cada iteración, deje que la tortuga avance un paso y la liebre avance dos pasos. En cada iteración, usted compara [matemáticas] x_i [/ ​​matemáticas] y [matemáticas] x_ {2i} [/ matemáticas]. Si existe un ciclo, entonces eventualmente obtendrá un valor [math] i \ geq \ mu [/ math] y la diferencia entre las posiciones de liebre y tortuga (que también es [math] i [/ math]) será divisible por [math] \ lambda [/ math]. En cada paso, debe iterar la función tres veces; una vez para la tortuga, dos veces para la liebre.

El algoritmo de Brent procede de manera un poco diferente; esta vez, dejamos que la tortuga se siente a una potencia de 2, y la liebre se escapa a la siguiente potencia de 2. En cada iteración interna, la tortuga está en [matemáticas] 2 ^ n [/ matemáticas] mientras que la liebre está en [ matemáticas] 2 ^ n + i [/ matemáticas]. Una vez que la liebre llega a [matemáticas] 2 ^ {n + 1} [/ matemáticas], restablecemos la tortuga a ese punto. Nuevamente, si existe un ciclo, eventualmente lo detectaremos. Los beneficios son esta vez, solo necesita aplicar la función una vez en cada paso; además, una vez que [math] 2 ^ n \ geq \ mu [/ math], la liebre encontrará [math] \ lambda [/ math] directamente, en lugar de posiblemente un múltiplo. Incluso si tiene que buscar más a través de los datos, el algoritmo de Brent requerirá menos evaluaciones funcionales que las de Floyd.

Aquí hay una explicación del algoritmo de búsqueda del ciclo de Floyd:

Detecta un bucle en una lista vinculada y encuentra el nodo donde comienza el bucle.

Algoritmo:

1. Inicialice dos referencias: una referencia lenta ‘S’ y una referencia rápida ‘F’ al comienzo de la lista

2. Mueva ‘S’ hacia adelante un nodo a la vez y mueva ‘F’ hacia adelante dos nodos a la vez.

3. Si en algún momento, la referencia ‘S’ y la referencia ‘F’ apuntan al mismo nodo de la lista, entonces sabemos que hay un bucle en la lista, de lo contrario, devolveremos nulo diciendo que no hay bucle.

4. Después de detectar el bucle en el paso 3, retrocedemos la referencia ‘S’ al inicio de la lista nuevamente y mantenemos ‘F’ en el mismo punto de encuentro.

5. Ahora, esta vez, movemos tanto ‘S’ como ‘F’ hacia adelante un nodo a la vez hasta que se encuentren.

6. El nodo donde se encuentran es el inicio del ciclo.

Consulte el enlace de arriba para ver el código, la explicación en video y los ejemplos.

Espero que esto ayude.