原文链接:http://www.cppblog.com/zengwei0771/articles/172700.html
题目描述:判断两个单链表是否相交,如果相交,给出相交的第一个点(链表中可能有环的情况下)
这里是①判断单链表是否有环,并求出环的入口点;②判断两个链表是否相交(链表中无环),并求出相交节点 的文章
http://www.cppblog.com/humanchao/archive/2008/04/17/47357.html
分析:
①:判断链表1是否有环,并记录其长度L1,尾节点b1(无环),环入口点a1(有环)
②:判断链表2是否有环,并记录其长度L2,尾节点b2(无环),环入口点a2(有环)
③:若一个有环,另一个没环,则判断不相交,结束
④:若两个都没环,则两个尾节点一点是一样的,所以比较两个尾节点是否相同。若不相同则判断不相交,结束;若相同,则到⑥。
⑤:若两个都有环,有如下图三种情况:a1与a2不相等,且不在一个环中,则不相交,结束;a1等于a2,跳到⑥;a1与a2不相等,但在一个环中,对于链表1来说a1是它的相交首节点,对于链表2来说a2是它的相交首节点。
⑥:对于两个链表重头开始遍历,长链表节点先出发前进(Max(L1,L2)-Min(L1,L2))步,之后两个链表同时前进,每次一步,相遇的第一点即为两个链表相交的第一个点。
代码如下:
typedef struct Node
{
int value;
Node* pNext;
}* List;
Node* IsListCross(List L1, List L2)
{
if (L1 == NULL || L2 == NULL)
{
return NULL;
}
int len1 = 0; //L1的长度
int len2 = 0; //L2的长度
bool L1HasLoop = false; //L1是否有环
bool L2HasLoop = false; //L2是否有环
Node *crossEntry1 = NULL, *crossEntry2 = NULL, *end1 = NULL, *end2 = NULL;
Node *pNode1, *pNode2, *pNode3; //临时节点指针
//①
pNode1 = L1;
pNode2 = L1;
while (pNode2 && pNode2->pNext)
{
len1++;
pNode1 = pNode1->pNext;
pNode2 = pNode2->pNext->pNext;
if (pNode1 == pNode2)
{
L1HasLoop = true;
break;
}
}
if (L1HasLoop)
{
pNode2 = L1;
while (pNode1 != pNode2)
{
len1++;
pNode1 = pNode1->pNext;
pNode2 = pNode2->pNext;
}
crossEntry1 = pNode1;
}
else
{
pNode3 = pNode1;
while (pNode3->pNext)
{
len1++;
pNode3 = pNode3->pNext;
}
end1 = pNode3;
len1++;
}
//②
pNode1 = L2;
pNode2 = L2;
while (pNode2 && pNode2->pNext)
{
len2++;
pNode1 = pNode1->pNext;
pNode2 = pNode2->pNext->pNext;
if (pNode1 == pNode2)
{
L2HasLoop = true;
break;
}
}
if (L2HasLoop)
{
pNode2 = L2;
while (pNode1 != pNode2)
{
len2++;
pNode1 = pNode1->pNext;
pNode2 = pNode2->pNext;
}
crossEntry2 = pNode1;
}
else
{
pNode3 = pNode1;
while (pNode3->pNext)
{
len2++;
pNode3 = pNode3->pNext;
}
end2 = pNode3;
len2++;
}
//③
if (L1HasLoop != L2HasLoop)
{
return NULL;
}
//④
else if (L1HasLoop == false)
{
if (end1 != end2)
{
return NULL;
}
}
//⑤
else
{
//a1 != a2
if (crossEntry1 != crossEntry2)
{
bool onOneLoop = false;
pNode1 = crossEntry1->pNext;
while (crossEntry1 != pNode1)
{
if (pNode1 == crossEntry2)
{
onOneLoop = true;
break;
}
pNode1 = pNode1->pNext;
}
//a1 != a2,且不在一个环中
if (!onOneLoop)
{
return NULL;
}
//a1 != a2,在一个环中
else
{
return crossEntry1;
}
}
}
//⑥
pNode1 = L1;
pNode2 = L2;
int gap;
if (len1 > len2)
{
gap = len1 - len2;
while (gap)
{
pNode1 = pNode1->pNext;
gap--;
}
}
else
{
gap = len2 - len1;
while (gap)
{
pNode2 = pNode2->pNext;
gap--;
}
}
while (pNode1 != pNode2)
{
pNode1 = pNode1->pNext;
pNode2 = pNode2->pNext;
}
return pNode1;
}