problem
Implement an algorithm that detects whether there is a single ring linked list, even if there is obtained the inlet ring ring.
analysis
Determine whether the ring: the speed of the pointer method (also called "Tortoise and the Hare"), each move a pointer slow, fast moving pointer every two, if there is a ring, they will meet.
Ring seeking entry: meet the arrival position, the head block pointer movement position of the pointer, every time a mobile, the position is both meet again the inlet ring.
why?
(First "borrowed" a map
The first time meet, slow down the pointer $ x + k $, fast walking pointer $ x + k + mr $ ($ r $ is the length of the loop, $ m \ geq 1 $),
And because the fast speed of the pointer is twice slower pointer, the $ 2 (x + k) = x + k + mr $.
即 $x = mr-k$($m \geq 1$),
Slow pointer has $ k $, the block pointer is set to 0, the step further over $ X $, they will meet the inlet ring.
#include <stdio.h> #include<stdbool.h> typedef struct node { int value; struct node *next; } node; bool ll_has_cycle(node *head) { if (head == NULL) return false; node* har = head; node* tor = head; while (1) { if (tor->next != NULL) tor = tor->next; else return false; if (har->next != NULL && har->next->next != NULL) har = har->next->next; else return false; if (tor == har) return true; } } int find_cycle_entrance(node *head) { if (head == NULL) return -1; node* har = head; node* tor = head; while (1) { if (tor->next != NULL) tor = tor->next; else return -1; if (har->next != NULL && har->next->next != NULL) har = har->next->next; else return -1; if (tor == har) { har = head; while(har != tor) { har = har->next; tor = tor->next; } return har->value; } } } void test_ll_has_cycle(void) { int i; node nodes[25]; //enough to run our tests for (i = 0; i < sizeof(nodes) / sizeof(node); i++) { nodes[i].next = 0; nodes[i].value = i; } nodes[0].next = &nodes[1]; nodes[1].next = &nodes[2]; nodes[2].next = &nodes[3]; printf("Checking first list for cycles. There should be none, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[0]) ? "a" : "no"); printf("Entranc:%d\n", find_cycle_entrance(&nodes[0])); nodes[4].next = &nodes[5]; nodes[5].next = &nodes[6]; nodes[6].next = &nodes[7]; nodes[7].next = &nodes[8]; nodes[8].next = &nodes[9]; nodes[9].next = &nodes[10]; nodes[10].next = &nodes[4]; printf("Checking second list for cycles. There should be a cycle, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[4]) ? "a" : "no"); printf("Entranc:%d\n", find_cycle_entrance(&nodes[4])); nodes[11].next = &nodes[12]; nodes[12].next = &nodes[13]; nodes[13].next = &nodes[14]; nodes[14].next = &nodes[15]; nodes[15].next = &nodes[16]; nodes[16].next = &nodes[17]; nodes[17].next = &nodes[14]; printf("Checking third list for cycles. There should be a cycle, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[11]) ? "a" : "no"); printf("Entranc:%d\n", find_cycle_entrance(&nodes[11])); nodes[18].next = &nodes[18]; printf("Checking fourth list for cycles. There should be a cycle, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[18]) ? "a" : "no"); printf("Entranc:%d\n", find_cycle_entrance(&nodes[18])); nodes[19].next = &nodes[20]; nodes[20].next = &nodes[21]; nodes[21].next = &nodes[22]; nodes[22].next = &nodes[23]; printf("Checking fifth list for cycles. There should be none, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[19]) ? "a" : "no"); printf("Entranc:%d\n", find_cycle_entrance(&nodes[19])); printf("Checking length-zero list for cycles. There should be none, ll_has_cycle says it has %s cycle\n", ll_has_cycle(NULL) ? "a" : "no"); printf("Entranc:%d\n", find_cycle_entrance(NULL)); } int main() { test_ll_has_cycle(); return 0; }
Reference Links: https://blog.csdn.net/qq_36781505/article/details/91401474