如图,如果单链表有环,则在遍历时,在通过6之后,会重新回到3,那么我们可以在遍历时使用两个指针,看两个指针是否相等。
方法一:使用p、q两个指针,p总是向前走,但q每次都从头开始走,对于每个节点,看p走的步数是否和q一样。如图,当p从6走到3时,用了6步,此时若q从head出发,则只需两步就到3,因而步数不等,出现矛盾,存在环
方法二:使用p、q两个指针,p每次向前走一步,q每次向前走两步,若在某个时候p == q,则存在环。
代码如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define LEN 8 5 typedef struct node* node_t; 6 7 struct node{ 8 char val; 9 struct node *next; 10 }; 11 12 //method 1 13 int has_loop(struct node *head); 14 //method 2 15 int has_loop2(node_t head); 16 17 int main() 18 { 19 node_t* arr = (node_t*)malloc(sizeof(struct node)*LEN); 20 arr[0] = (node_t)malloc(sizeof(struct node)); 21 int i; 22 for(i = 1; i < LEN; i++) 23 { 24 arr[i] = (node_t)malloc(sizeof(struct node)); 25 arr[i - 1]->next = arr[i]; 26 } 27 arr[LEN - 1]->next = NULL; 28 29 //you can add a loop here to test 30 //arr[6]->next = arr[0]; 31 if (has_loop(arr[0])) 32 printf("method1: has loop. "); 33 else 34 printf("method1: has no loop. "); 35 36 if (has_loop2(arr[0])) 37 printf("method2: has loop. "); 38 else 39 printf("method2: has no loop. "); 40 41 return 0; 42 } 43 44 //if two pointer are equal, but they don't have the same steps, then has a loop 45 int has_loop(node_t head) 46 { 47 node_t cur1 = head; 48 int pos1 = 0; 49 while(cur1){ 50 node_t cur2 = head; 51 int pos2 = 0; 52 pos1 ++; 53 while(cur2){ 54 pos2 ++; 55 if(cur2 == cur1){ 56 if(pos1 == pos2) 57 break; 58 else 59 return 1; 60 } 61 cur2 = cur2->next; 62 } 63 cur1 = cur1->next; 64 } 65 return 0; 66 } 67 68 //using step1 and step2 here 69 //if exists a loop, then the pointer which use step2 will catch up with the pointer which uses step1 70 int has_loop2(node_t head) 71 { 72 node_t p = head; 73 node_t q = head; 74 while (p != NULL && q != NULL) 75 { 76 /* 77 p = p->next; 78 if (q->next != NULL) 79 q = q->next->next; 80 if (p == q) 81 return 1; 82 */ 83 //correct it on 17/11/2012 84 p = p->next; 85 q = q->next; 86 if (q != NULL) 87 q = q->next; 88 if (p != NULL && p == q) 89 return 1; 90 } 91 return 0; 92 }