如何判断一个链表是否有环,并求出环的起始点。
第一种解法set,set容器默认去重,当循环遍历查询当前节点是否保存到set容器中,如果存在就直接返回直接输出当前节点的数据值,如果不存在则将当前节点直接插入set容器中
#include <iostream>
#include<set>
using namespace std ;
struct node
{
int data ;
struct node *next ;
};
typedef struct node *PLIST;
typedef struct node NODE;
PLIST createList_link()
{
PLIST head=new struct node;
head->next=NULL;
return head ;
}
void insertTail(PLIST llist,int x)
{
PLIST tail=llist->next;
PLIST temp=new struct node;
temp->data=x;
temp->next=NULL;
if(tail==NULL)
{
llist->next=temp;
return;
}
else
{
while(tail->next!=NULL)
{
tail=tail->next;
}
}
tail->next=temp;
}
void finishCircle(PLIST head,int num)
{
PLIST p=head->next,q,r;
while(p!=NULL)
{
if(p->data==num)
{
q=p;
break;
}
p=p->next;
}
while(p->next!=NULL)
{
p=p->next;
}
p->next=q;
}
void printList_link(PLIST head)
{
for(PLIST p=head->next;p!=NULL;p=p->next){
cout<<p->data<<" ";
}
cout<<endl;
}
int main()
{
//begin 生成链表
int arr[]={3,324,34,23,12,45,34};
PLIST head=createList_link();
for(int i=0;i<7;i++)
{
insertTail(head,arr[i]);
}
finishCircle(head,34);
// printList_link(head);
//end
set<PLIST> s;
PLIST p=head->next;
while(p!=NULL)
{
if(s.count(p)==0)
s.insert(p);
else
break;
p=p->next;
}
cout<<p->data;
return 0;
}
第二种解法,双指针法,一个指针的移动速度为1,另一个指针的移动速度为2,设链表无环长度为x,环链表长度为y,设两指针在m处相遇,则有方程x+k1y+m=2(x+m+k2y),m=(2*k2-k1)y-x,其实说明当两个指针相遇时,距离环起点长度只有x,恰好等于无环长度的距离
#include <iostream>
#include<set>
using namespace std ;
struct node
{
int data ;
struct node *next ;
};
typedef struct node *PLIST;
typedef struct node NODE;
PLIST createList_link()
{
PLIST head=new struct node;
head->next=NULL;
return head ;
}
void insertTail(PLIST llist,int x)
{
PLIST tail=llist->next;
PLIST temp=new struct node;
temp->data=x;
temp->next=NULL;
if(tail==NULL)
{
llist->next=temp;
return;
}
else
{
while(tail->next!=NULL)
{
tail=tail->next;
}
}
tail->next=temp;
}
void finishCircle(PLIST head,int num)
{
PLIST p=head->next,q,r;
while(p!=NULL)
{
if(p->data==num)
{
q=p;
break;
}
p=p->next;
}
while(p->next!=NULL)
{
p=p->next;
}
p->next=q;
}
void printList_link(PLIST head)
{
for(PLIST p=head->next;p!=NULL;p=p->next){
cout<<p->data<<" ";
}
cout<<endl;
}
int main()
{
//begin 生成链表
int arr[]={3,324,34,23,12,45,34};
PLIST head=createList_link();
for(int i=0;i<7;i++)
{
insertTail(head,arr[i]);
}
finishCircle(head,34);
// printList_link(head);
//end
PLIST n1,n2,n3;
n1=head->next;
n2=head->next;
n3=head->next;
n1=n1->next;
n2=n2->next->next;
while(n1!=n2)
{
n1=n1->next;
n2=n2->next->next;
}
while(n3!=n1)
{
n3=n3->next;
n1=n1->next;
}
cout<<n3->data;
return 0;
}