¿Cómo encuentra un ciclo en una lista “simple” usando solo dos punteros?

Las respuestas de los demás fueron totalmente correctas. Sin embargo, me gustaría ofrecer una forma más intuitiva de entender este problema (al menos para mí)

– Piensa en una carrera entre una tortuga y una liebre en un campo de atletismo
– Suponga que la liebre corre mucho más rápido que la tortuga.
– Si ambos siguen corriendo infinitamente, pronto la liebre estará 1 ronda por delante de la tortuga.

Ahora piense en el problema de la lista circular

– si tienes 1 puntero se mueve a baja velocidad (la tortuga)
– el otro a mayor velocidad (la liebre)
– entonces, si la lista es realmente circular (como el campo de seguimiento), la más rápida estará 1 vuelta por delante de la más lenta, es decir, el puntero 2 se volverá a encontrar.

Editar: quiero decir, el más rápido será 1 ronda por delante del más lento pronto. Si los 2 siguen corriendo, esa diferencia aumentará

Como ya se mencionó, un puntero atraviesa un nodo por paso y el otro atraviesa 2 nodos por paso. Puedes echar un vistazo al código.

  #include 

 usando el espacio de nombres estándar;

 nodo de estructura {
   datos int;
   struct node * next;  
 };

 inserción vacía (nodo de estructura ** cabeza, datos int) {
     struct node * temp = (struct node *) malloc (sizeof (struct node));
     temp -> datos = datos;
     temp -> siguiente = (* cabeza);

     (* cabeza) = temp;
 }

 impresión nula (nodo de estructura * cabeza) {
     if (cabeza == NULL)
         regreso;
     struct node * temp = head;
     while (temp! = NULL) {
         printf ("% d", temp-> datos);
         temp = temp-> siguiente;
     }
 }

 vacío make_loop (nodo de estructura ** cabeza) {
	 if (* head == NULL)
		 regreso;
	 struct node * current, * temp;
	 actual = * cabeza;
	 int k;
	 while (k <3 && current! = NULL) {
		 actual = actual -> siguiente;
		 k ++;
	 }
	 temp = actual;
	 while (actual-> siguiente! = NULL)
		 actual = actual-> siguiente;
	 actual-> siguiente = temp;
 }

 vacío check_loop (estructura nodo * cabeza) {
	 struct node * slow = head, * fast = head;
	 while (fast && slow && fast-> next) {
		 rápido = rápido-> siguiente-> siguiente;
		 lento = lento-> siguiente;
		 if (rápido == lento) {
			 printf ("el bucle existe \ n");
			 regreso;
		 }
	 }
 }

 int main () {
     struct node * head = NULL;
     inserto (y cabeza, 10);
     inserto (y cabeza, 11);
     inserto (y cabeza, 12);
     inserto (y cabeza, 13);
     inserto (y cabeza, 130);
     inserto (& cabeza, 123);
     inserto (& cabeza, 133);
     inserto (& cabeza, 134);
     // print (cabeza);
     make_loop (& head);
     check_loop (cabeza);
     devuelve 0;
 } 

Un puntero atraviesa 1 nodo por paso. El otro atraviesa 2 nodos por paso. Se encuentran si y solo si existe un ciclo.