步驟如下:
(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;
}
帶環相交輸出結果:
兩個無環相交鏈表輸出結果: