您的位置:首页 > 编程语言

编程判断两个链表是否相交

2015-01-11 19:41 232 查看
《编程之美》3.6节:判断两个链表是否相交

问题:给出两个单项链表的头指针,判断这两个链表是否相交,假设都不带环。

解法:遍历第一个链表至尾节点,然后遍历第二个链表,如果尾节点和刚才相同,则说明相交,否则不想交。

代码:

#include<iostream>
using namespace std;

struct Node
{
Node *next;
int data;
Node(int d=0,Node *n=NULL):next(n),data(d){}
};

bool isCrossList(Node *firstList,Node *secondList)
{
if(firstList==nullptr || secondList==nullptr)
return false;
Node *curr=firstList;
while(curr->next!=nullptr)
curr=curr->next;
Node *tail=curr;
curr=secondList;
while(curr->next!=nullptr)
curr=curr->next;
if(curr==tail)
return true;
else
return false;
}

int main()
{
Node *firstList=new Node(0);
Node *cross;
Node *curr=firstList;
for(int i=1;i<10;i++)
{
curr->next=new Node(i);
if(i==5)
cross=curr->next;
curr=curr->next;
}
Node *secondList=new Node(0);
curr=secondList;
for(int i=1;i<5;i++)
{
curr->next=new Node(i);
curr=curr->next;
}
curr->next=cross;

bool result=isCrossList(firstList,secondList);
cout<<result<<endl;

system("pause");
return 0;
}

扩展问题一:如果链表可能有环,上面代码如何修改?

解法:先找出第一个链表的环的入口节点first,然后找出第二个链表的环的入口节点second,如果相同,则肯定相交。如果不相同则令curr=second->next,然后curr!=second,即遍历一遍第二个链表的环,如果有curr==first,则证明相交,否则不想交。

扩展问题二:求出两个链表相交的第一个节点?

解法:分两种情况,一种是没有环,两链表相交,把链表尾节点的下一个节点指向第二个链表的头结点,那么这个问题便转换成了求一个带环链表的环的入口节点。第二种情况是两链表有环且相交,此时求出两个链表分别的环的入口节点first和second,如果不相同则第二个链表的入口节点就是所求;如果相同,则把first->next=nullptr,即把链表的环断开,然后根据无环的相交链表求相交的节点即可,即情况一。

代码:

#include<iostream>
using namespace std;

struct Node
{
Node *next;
int data;
Node(int d=0,Node *n=NULL):next(n),data(d){}
};

bool hasLoop(Node *head)
{
if(head==nullptr || head->next==nullptr)
return false;
Node *slow=head->next;
Node *fast=head->next->next;
while(fast!=nullptr && fast->next!=nullptr)
{
if(fast==slow)
return true;
slow=slow->next;
fast=fast->next->next;
}
return false;
}

Node * firstCrossNode(Node *head)
{
Node *slow=head->next;
Node *fast=head->next->next;
while(fast!=nullptr && fast->next!=nullptr)
{
if(fast==slow)
{
slow=head;
break;
}
slow=slow->next;
fast=fast->next->next;
}
while(slow!=fast)
{
slow=slow->next;
fast=fast->next;
}
return slow;
}

bool isCrossListNoLoop(Node *firstList,Node *secondList)
{
if(firstList==nullptr || secondList==nullptr)
return false;
Node *curr=firstList;
while(curr->next!=nullptr)
curr=curr->next;
Node *tail=curr;
curr=secondList;
while(curr->next!=nullptr)
curr=curr->next;
if(curr==tail)
return true;
else
return false;
}

bool isCrossListHasLoop(Node *firstList,Node *secondList)
{
Node *first=firstCrossNode(firstList);
Node *second=firstCrossNode(secondList);
if(first==second)
return true;
Node *curr=second->next;
while(curr!=second)//只需要判断这两个环是不是一个环就行了
{
if(curr==first)
return true;
curr=curr->next;
}
return false;
}

bool isCrossList(Node *firstList,Node *secondList)
{
bool firstLoop=hasLoop(firstList),secondLoop=hasLoop(secondList);
if(firstLoop && !secondLoop)//第一个有环第二个没环,肯定不相交
return false;
else if(firstLoop)//如果都有环
return isCrossListHasLoop(firstList,secondList);
else//如果两个都没环,调用常规程序解即可
return isCrossListNoLoop(firstList,secondList);
}

Node *twoListFirstCrossNodeNoLoop(Node *firstList,Node *secondList)
{
Node *curr=secondList;
while(curr->next!=nullptr)
curr=curr->next;
Node *tail=curr;
tail->next=secondList;
Node *firstCross=firstCrossNode(firstList);
tail->next=nullptr;
return firstCross;
}

Node *twoListFirstCrossNodeHasLoop(Node *firstList,Node *secondList)
{
Node *first=firstCrossNode(firstList);
Node *second=firstCrossNode(secondList);
if(first!=second)//返回secondList接入firstList的第一个节点
return second;
else//如果first==second则有两种情况:一是两个链表在第一个链表环的入口处相交,另一种情况是在环的外面相交
{	//不论是哪种情况,都需要在链表入口的地方拆断链表,然后按没有环的情况处理即可
Node *temp=first->next;
first->next=nullptr;
Node *result=twoListFirstCrossNodeNoLoop(firstList,secondList);
first->next=temp;
return result;
}
}

Node *twoListFirstCrossNode(Node *firstList,Node *secondList)
{
if(!isCrossList(firstList,secondList))//如果不相交
return nullptr;
bool firstLoop=hasLoop(firstList);//如果相交,那么两个链同时有环或者无环
if(firstLoop==false)//如果无环
return twoListFirstCrossNodeNoLoop(firstList,secondList);
else
return twoListFirstCrossNodeHasLoop(firstList,secondList);

}

int main()
{
Node *firstList=new Node(0);
Node *cross;
Node *curr=firstList;
for(int i=1;i<10;i++)
{
curr->next=new Node(i);
if(i==5)
cross=curr->next;
curr=curr->next;
}
curr->next=cross->next->next;
Node *secondList=new Node(0);
curr=secondList;
for(int i=1;i<5;i++)
{
curr->next=new Node(i);
curr=curr->next;
}
curr->next=cross;
bool result=isCrossList(firstList,secondList);
cout<<result<<endl;

cout<<twoListFirstCrossNode(firstList,secondList)->data<<endl;

system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: