步骤如下:
(1)判断两个单链表中是否有环,如果都没有环,则进入(2);如果都有环,则进入(3);如果一个有环,一个没有环,则必然不会相交。
(2)两个链表没环,则判断两个链表中最后一个结点是否相等(不只是值相等,须地址一样);
(3)先用快慢指针计算出一个环的入口结点,在判断此结点是否在另外一个带环链表上。
注意: 两个带环链表如果相交,则在创建2个带环链表时,则2个共同尾结点指向的下一结点应该一样(包括地址)。
代码如下:
// DoubleListCross.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
typedef int type;
using namespace std;
//单链表结点
typedef struct node
{
type data;
struct node *next;
}node,*pNode;
//创建两个无环交叉链表或非交叉链表 a1为L1链表中的数据,长度为n1,m指L1与L2共有结点的长度
void CreateLists(pNode &L1,pNode &L2,type *a1,type *a2,int n1,int n2,int m)
{
L1=(pNode)malloc(sizeof(node));
if(NULL==L1)
{
exit(-1);
}
L2=(pNode)malloc(sizeof(node));
if(NULL==L2)
{
exit(-1);
}
L1->next=NULL; //创建头结点
L2->next=NULL;
pNode temp1=L1;
pNode temp2=L2;
for(int i=0;i<n1-m;i++)
{
pNode p1=(pNode)malloc(sizeof(node));
if(NULL==p1)
{
exit(-1);
}
p1->data=a1[i];
p1->next=NULL;
temp1->next=p1;
temp1=p1;
}
for(int i=0;i<n2-m;i++)
{
pNode p2=(pNode)malloc(sizeof(node));
if(NULL==p2)
{
exit(-1);
}
p2->data=a2[i];
p2->next=NULL;
temp2->next=p2;
temp2=p2;
}
//创建公用结点
for(int i=n2-m;i<n2;i++)
{
pNode p3=(pNode)malloc(sizeof(node));
if(NULL==p3)
{
exit(-1);
}
p3->data=a2[i];
p3->next=NULL;
temp2->next=p3;
temp2=p3;
temp1->next=p3;
temp1=p3;
}
}
//创建2个有环交叉链表 a1为L1链表中的数据,长度为n1,m指L1与L2共有结点的长度 m1为L1入环结点标号
void CreateCircleLists(pNode &L1,pNode &L2,type *a1,type *a2,int n1, int n2, int m, int m1,int m2)
{
L1=(pNode)malloc(sizeof(node));
if(NULL==L1)
{
exit(-1);
}
L2=(pNode)malloc(sizeof(node));
if(NULL==L2)
{
exit(-1);
}
L1->next=NULL; //创建头结点
L2->next=NULL;
pNode temp1=L1;
pNode temp2=L2;
for(int i=0;i<n1-m;i++)
{
pNode p1=(pNode)malloc(sizeof(node));
if(NULL==p1)
{
exit(-1);
}
p1->data=a1[i];
p1->next=NULL;
temp1->next=p1;
temp1=p1;
}
for(int i=0;i<n2-m;i++)
{
pNode p2=(pNode)malloc(sizeof(node));
if(NULL==p2)
{
exit(-1);
}
p2->data=a2[i];
p2->next=NULL;
temp2->next=p2;
temp2=p2;
}
//创建公用结点
for(int i=n2-m;i<n2;i++)
{
pNode p3=(pNode)malloc(sizeof(node));
if(NULL==p3)
{
exit(-1);
}
p3->data=a2[i];
p3->next=NULL;
temp2->next=p3;
temp2=p3;
temp1->next=p3;
temp1=p3;
}
//建立环
pNode p11=L1->next;
pNode p22=L2->next;
for(int i=1;i<m1;i++)
{
p11=p11->next;
}
temp1->next=p11;
for(int j=1;j<m2;j++)
{
p22=p22->next;
}
temp2->next=p22;
}
//打印一个无环链表
void PrintList(pNode L)
{
pNode temp=L->next;
while(NULL!=temp)
{
cout<<temp->data<<" ";
temp=temp->next;
}
cout<<endl;
}
//计算一个无环链表长度
int Len(pNode L)
{
pNode temp=L->next;
int i=0;
while(NULL!=temp)
{
i++;
temp= temp->next;
}
return i;
}
//取一个无环链表中某一结点
pNode GetNode(pNode L,int m)
{
int len=Len(L);
if((m<1)||(m>len))
{
cout<<"Over!"<<endl;
exit(-1);
}
pNode temp=L->next;
for(int i=0;i<m;i++)
{
temp=temp->next;
}
return temp;
}
//判断一个单链表是否有环 如果有环,返回环的入口结点 如果没有环,返回NULL
pNode IsCircle(pNode L)
{
pNode fast=L;
pNode slow=L;
while(fast &&fast->next)
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow)
{
fast=L;
while(fast!=slow)
{
fast=fast->next;
slow=slow->next;
}
return slow;
}
}
return NULL;
}
//计算一个带环链表的长度
int LenCircle(pNode L)
{
pNode p=L->next;
pNode p1=IsCircle(L);//环的入口结点
pNode p2=p1->next;
int i=0;
int j=1;
while(p!=p1)
{
i++;
p=p->next;
}
while(p2!=p1)
{
j++;
p2=p2->next;
}
return i+j;
}
//判断一个环的入口结点是否在另外一条带环链表上
bool IsCircleNode(pNode p,pNode L)
{
pNode temp=L->next;
int len=LenCircle(L);
for(int i=0;i<len;i++)
{
if(temp==p)
{
return true;
}
temp=temp->next;
}
return false;
}
//判断2个无环单链表是否相交 如果相交返回相交点,否则返回NULL
pNode ListCross(pNode L1,pNode L2,int n1, int n2)
{
pNode temp1=L1->next;
pNode temp2=L2->next;
if(GetNode(L1,n1)==GetNode(L2,n2))//判断尾结点相同
{
if(n1>=n2)
{
for(int i=0;i<n1-n2;i++)
{
temp1=temp1->next;
}
}
else
{
for(int i=0;i<n2-n1;i++)
{
temp2=temp2->next;
}
}
while(temp1!=temp2)
{
temp1=temp1->next;
temp2=temp2->next;
}
return temp1;
}
else
{
return NULL;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
type a1[5]={1,2,3,4,5};
type a2[7]={6,7,8,9,3,4,5};
pNode L1=NULL;
pNode L2=NULL;
//CreateLists(L1,L2,a1,a2,5,7,3); 创建两个无环交叉链表
CreateCircleLists(L1,L2,a1,a2,5,7,3,3,5);//创建两个有环交叉链表
pNode p1=IsCircle(L1);
pNode p2=IsCircle(L2);
if((NULL==p1)&&(NULL==p2))//两个表无环
{
pNode temp=ListCross(L1,L2,5,7);
if(NULL==temp)
{
cout<<"两无环链表不相交!"<<endl;
}
else
{
cout<<"两无环链表相交结点为:"<<temp->data<<endl;
}
}
else if((NULL!=p1)&&(NULL!=p2)) //两个表都有环
{
if(IsCircleNode(p1,L2))
{
cout<<"两带环链表相交!"<<endl;
}
else
{
cout<<"两带环链表不相交!"<<endl;
}
}
else
{
cout<<"一个带环链表与一个无环链表一定不相交!"<<endl;
}
return 0;
}
带环相交输出结果:
两个无环相交链表输出结果: