问题一:如何判断一个单链表是否存在循环,链表数目未知,不能破坏链表。
解答:
设定两个指针slow,fast ,其中slow每次向前移动一步,fast每次向前移动两步。那么如果单链表存在环,则slow和fast相遇;否则fast将首先遇到null。
代码:
33 ///判断链表是否有环 34 LinkNode* judgeRing(Linklist list){ 35 LinkNode *fast = list; 36 LinkNode *slow = list; 37 38 if(list == NULL) 39 return NULL; 40 41 while(true){ 42 if(slow->next != NULL && fast->next != NULL && fast->next->next != NULL){ 43 slow = slow->next; 44 fast = fast->next->next; 45 } 46 else 47 return NULL; 48 49 if(fast == slow) 50 return fast; 51 } 52 }
问题二:如何判读问题一中的单链表环长度?
解答:
在环上相遇后,记录第一次相遇点为Pos,之后指针slow继续每次走1步,fast每次走2步,在下次相遇的时候fast比slow正好又多走了一圈,也就是多走的距离等于环长。设从第一次相遇到第二次相遇,设slow走了len步,则fast走了2*len步,相遇时多走了一圈。
所以:环长=len;
代码:
///获取链表环长 55 int getRingLength(LinkNode *meetNode){ 56 int RingLength=0; 57 LinkNode *fast = meetNode; 58 LinkNode *slow = meetNode; 59 for(;;){ 60 fast = fast->next->next; 61 slow = slow->next; 62 RingLength++; 63 if(fast == slow) 64 break; 65 } 66 return RingLength; 67 }
测试代码:
链表如下所示:
具体代码如下(转载):
1 #include <stdio.h> 2 #include <stdlib.h> 3 typedef struct node{ 4 int value; 5 struct node *next; 6 }LinkNode,*Linklist; 7 8 /// 创建链表(链表长度,环节点起始位置) 9 Linklist createList(){ 10 Linklist head = NULL; 11 LinkNode *preNode = head; 12 LinkNode *FifthNode = NULL; 13 for(int i=0;i<6;i++){ 14 LinkNode *tt = (LinkNode*)malloc(sizeof(LinkNode)); 15 tt->value = i; 16 tt->next = NULL; 17 if(preNode == NULL){ 18 head = tt; 19 preNode = head; 20 } 21 else{ 22 preNode->next =tt; 23 preNode = tt; 24 } 25 26 if(i == 3) 27 FifthNode = tt; 28 } 29 preNode->next = FifthNode; 30 return head; 31 } 32 33 ///判断链表是否有环 34 LinkNode* judgeRing(Linklist list){ 35 LinkNode *fast = list; 36 LinkNode *slow = list; 37 38 if(list == NULL) 39 return NULL; 40 41 while(true){ 42 if(slow->next != NULL && fast->next != NULL && fast->next->next != NULL){ 43 slow = slow->next; 44 fast = fast->next->next; 45 } 46 else 47 return NULL; 48 49 if(fast == slow) 50 return fast; 51 } 52 } 53 54 ///获取链表环长 55 int getRingLength(LinkNode *meetNode){ 56 int RingLength=0; 57 LinkNode *fast = meetNode; 58 LinkNode *slow = meetNode; 59 for(;;){ 60 fast = fast->next->next; 61 slow = slow->next; 62 RingLength++; 63 if(fast == slow) 64 break; 65 } 66 return RingLength; 67 } 68 69 ///获取链表头到环连接点的长度 70 int getLenA(Linklist list,LinkNode *meetNode){ 71 int lenA=0; 72 LinkNode *fast = list; 73 LinkNode *slow = meetNode; 74 for(;;){ 75 fast = fast->next; 76 slow = slow->next; 77 lenA++; 78 if(fast == slow) 79 break; 80 } 81 return lenA; 82 } 83 84 ///释放空间 85 int freeMalloc(Linklist list){ 86 LinkNode *nextnode = NULL; 87 while(list != NULL){ 88 nextnode = list->next; 89 free(list); 90 list = nextnode; 91 } 92 } 93 94 int main(){ 95 Linklist list = NULL; 96 LinkNode *meetNode = NULL; 97 int RingLength = 0; 98 int LenA = 0; 99 100 list = createList(); 101 meetNode = judgeRing(list); 102 103 if(meetNode == NULL) 104 printf("No Ring\n"); 105 else{ 106 printf("Have Ring\n"); 107 RingLength = getRingLength(meetNode); 108 LenA = getLenA(list,meetNode); 109 110 printf("RingLength:%d\n",RingLength); 111 printf("LenA:%d\n",LenA); 112 printf("listLength=%d\n",RingLength+LenA); 113 114 freeMalloc(list); 115 } 116 return 0; 117 }
执行结果: