1、判断链表是否有环
2、得到环的长度
3、得到环的入口节点
设置两个指针,让一个前进速度快,一个前进速度慢,当两者相遇就说明链表存在环
环的长度由第一次两指针相遇到第二次两指针相遇所循环的次数得出
环的入口节点怎么得出需要证明:假设速度快的节点fast每次走两步用,慢的节点slow每次走一步;
它们俩第一次相遇时fast走了2s步,slow走了s步,入口节点到头节点的距离是a,环长r,a+r为L;
第一次相遇时2s=s+nr;即s=nr,继而推出s=(n-1)r+(L-a);并且由于是第一次相遇,可以推出
slow并没有走完一次环(因为在slow到达环时fast就已经在环内了,fast能追上slow),所以设slow
在环内走了x步,则a+x=(n-1)r+(L-a);a=(n-1)r+(L-a-x);即a的长度等于(n-1)个环的
长度加上第一次相遇时slow没走完的环的剩余长度。所以当两个指针一个从链表的头开始走,一个从slow开始走,两者相遇的时候该节点就是环的入口节点。
#include <iostream>
using namespace std;
typedef struct node
{
int x;
node *next;
}list;
bool isLoop(list *a);
int LpLength(list *a);
list *LoopEntrance(list *a);
int main(int argc, char *argv[])
{
return 0;
}
bool isLoop(list *a) //判断是否存在环
{
list *fast = a;
list *slow = a;
while (fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
return true;
}
return false;
}
int LpLength(list *a) //得到环的长度
{
if (!isLoop(a))
return 0;
list *fast = a;
list *slow = a;
int flag = 0;
int length = 0;
while (fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
flag++;
if (flag == 1)
length++;
if (flag == 2)
break;
}
return length;
}
list *LoopEntrance(list *a) //得到环的入口节点地址
{
if (!isLoop(a))
return NULL;
list *fast = a;
list *slow = a;
while (fast != NULL & fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
break;
}
slow = a;
while (slow != fast)
{
slow = slow->next;
fast = fast->next;
}
return slow;
}