Given a circular linked list, implement an algorithm which retrns node at the beginning of the loop.
原题如下:
首先先判断一下,链表有没有循环。
我们假设有两个指针,一个指针一次移动一步,另一个指针一次移动两步;如果链表有环,这两个指针必定相交。
//判断有无回环,有则返回两个指针的交点,否则返回NULL
Node * hasLoop(Node *Head)
{
Node *p1=Head;//慢指针
Node *p2=Head;//快指针
while(p2->next!=NULL){
p2=p2->next->next;
p1=p1->next;
if(p1==p2)
return p1;
}
return NULL;
}
再想一下,快指针每次比慢指针多一步;在进入环的那一刻,慢指针走了k步,这时快指针已经比慢指针夺走了k步了。
假设环上有n个结点,快指针要想赶上慢指针,要再走(n-k)步。也就是说它们的相遇点离环的起始点有k步。
这时再把慢指针放到起始点,快指针每次走一步,它们再次相遇的地方就是起始点。
测试代码:
#include<iostream>
using namespace std;
struct Node{
char data;
Node *next;
Node(char i):data(i),next(NULL){};
};
//判断有无回环,有则返回两个指针的交点,否则返回NULL
Node *hasLoop(Node *Head)
{
Node *p1=Head;//慢指针
Node *p2=Head;//快指针
while(p2->next!=NULL){
p2=p2->next->next;
p1=p1->next;
if(p1==p2)
return p1;
}
return NULL;
}
//有环则返回起始点,否则返回NULL
Node *findStart(Node *Head)
{
Node *meet=hasLoop(Head);
if(meet)
while(Head!=meet)
{
Head=Head->next;
meet=meet->next;
}
return meet;
}
int main()
{
Node *Head;
Node *Tail;
Head=Tail=new Node('A');
for(int i=1;i<5;i++)//A->B->C->D->E
{
Node *p=new Node('A'+i);
Tail->next=p;
Tail=p;
}
//E指向C
Tail->next=Head->next->next;
Node *t=findStart(Head);
cout<<t->data<<endl;
//释放结点
return 0;
}