本文参考了http://www.cppblog.com/humanchao/archive/2008/04/17/47357.aspx
问题1:如何判断单链表有环
2:如果有环,在哪里有环的开始点
3 判断两个链表是否相交
问题一:
设置两个指针(fast, slow),初始值都指向头,slow每次前进一步,fast每次前进二步,如果链表存在环,则fast必定先进入环,而slow后进入环,两个指针必定相遇。(当然,fast先行头到尾部为NULL,则为无环链表)程序如下:LOOP_2
问题二:
二、找到环的入口点
当fast若与slow相遇时,slow肯定没有走遍历完链表,而fast已经在环内循环了n圈(1<=n)。假设slow走了s步,则fast走了2s步(fast步数还等于s 加上在环上多转的n圈),设环长为r,则:
2s = s + nr
s= nr
设整个链表长L,入口环与相遇点距离为x,起点到环入口点的距离为a。
a + x = nr
a + x = (n – 1)r +r = (n-1)r + L - a
a = (n-1)r + (L – a – x)
(L – a – x)为相遇点到环入口点的距离,由此可知,从链表头到环入口点等于(n-1)循环内环+相遇点到环入口点,于是我们从链表头、与相遇点分别设一个指针,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。在函数的 LOOP_2
问题三:如果2个链表相交,可以判断最后元素相交否,如相交一定,相等;否则不等。程序如loop()。还可以把链head_1的尾和head_2的头相连,通过判断是否有环,来判断是否相交,找到环的入口点,找到2个链的交点 代码如 LOOP2
// 最短摘要的生成.cpp : 定义控制台应用程序的入口点。
//
/*author:songzhengchao
time:2013/11/6*/
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
/*define the data struct for link */
typedef struct node
{
struct node *next;
int value;
}NODE;
/*construct the link head_1 1-->2-->6-->7-->8
head_2 3-->4-->6-->7-->8
*/
void make(NODE * &head_1,NODE * &head_2)
{
int i;
NODE *pre_1=head_1;
NODE *p;
for(i=1;i<=2;i++)
{
p=new NODE;
p->next=NULL;
p->value=i;
pre_1->next=p;
pre_1=p;
}
NODE *pre_2=head_2;
NODE *q;
for(i=3;i<=4;i++)
{
q=new NODE;
pre_2->next=q;
q->value=i;
q->next=NULL;
pre_2=q;
}
NODE *pre=new NODE ;
for(i=6;i<=8;i++)
{
NODE *r=new NODE;
r->next=NULL;
r->value=i;
if(i==6)
{
q->next=p->next=r;
pre=r;
}else
{
pre->next=r;
pre=r;
}
}
}
/*打印元素*/
void print(NODE *head)
{
NODE *p=head->next;
while(p!=NULL)
{
cout<<p->value<<" ";
p=p->next;
}
cout<<"---end---"<<endl;
}
/*方法一 :如有相交,最后一个元素一定相等*/
bool loop(NODE *head_1,NODE *head_2)
{
NODE *p=head_1;
NODE *q=head_2;
while(p->next)
{
p=p->next;
}
while(q->next)
{
q=q->next;
}
if(q==p){
cout<<"exist the loop"<<endl;
return true;
}else
{
cout<<"can't exist loop"<<endl;
return false;
}
}
/*方法二:将一个串 head_1的尾部接入到head_2的头部**/
bool LOOP_2(NODE *head_1,NODE *head_2)
{
NODE *p=head_1;
while(p->next)
{
p=p->next;
}
NODE *q=head_2;
p->next=q;
int flag=0;//判断是否有环的标志
NODE *fast,*slow;
fast=slow=head_1;
while(fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast)
{
flag=1;
break;
}
}
/*下面求交点,即环的开始点*/
if(flag)
{
slow=head_1;
while(slow!=fast)
{
slow=slow->next;
fast=fast->next;
}
cout<<"相遇的节点为---->"<<slow->value<<endl;
cout<<"exist loop "<<endl;
return true;
}
else{
cout<<"isn't exist loop"<<endl;
return false;}
}
int _tmain(int argc, _TCHAR* argv[])
{
NODE *head_1=new NODE;
NODE *head_2=new NODE;
head_1->next=NULL;
head_2->next=NULL;
make(head_1,head_2);
print(head_2);
loop(head_1,head_2);
LOOP_2(head_1,head_2);
return 0;
}