一般判断两个单链表是否相交的题目描述有以下几种:
(1)如何判断两个单链表是否相交
(2)如何判断两个单链表无环
(3)两个单链表的第一个公共节点
思路分析:
单链表相交是指两个链表存在完全重合的部分(注意,不是交叉到一个点)。
<1> 第一种思路:最常用的方法,即利用链表相交的性质,如果两个链表相交,那么两个链表从相交点到链表结束都是相同的节点,必然是Y字形,所以判断两个链表的最后一个节点是不是相同即可。即先遍历一个链表,直到尾部,再遍历另外一个链表,如果也可以走到同样的结尾点,则两个链表相交,这时记下两个链表的长度length,再遍历一次,长链表节点先出发前进(lengthMax - lengthMin)步,之后两个链表同时前进,每次一步,相遇的第一个节点即为两个链表相交的第一个节点。
<2> 第二种思路:将这两个链表首尾相连(即第一个链表的首部和第二个链表的尾部相连),然后检测这个链表是否存在环,如果存在,则两个链表相交,而检测出来的依赖环入口即为相交的第一个点。
本文主要探讨第一种思路的实现,具体如下:
// 链表节点定义如下
typedef struct node
{
int data;
struct node *next;
} NODE;
// intersect [ˌɪntəˈsekt] vt.(指线条、道路等)相交,交叉;
// 判断两个单链表是否相交
bool IsIntersect(NODE *list1, NODE *list2, NODE *&value)
{
value = NULL; // 假设相交,将相交的第一个节点初始化为NULL。
if (list1 == NULL || list2 == NULL)
return false;
NODE *temp1 = list1;
NODE *temp2 = list2;
int size1 = 0; // 记录链表1的长度
int size2 = 0; // 记录链表2的长度
while (temp1->next)
{
temp1 = temp1->next;
++size1;
}
while (temp2->next)
{
temp2 = temp2->next;
++size2;
}
if (temp1 == temp2) // 若两个链表相交,那么两个链表的最后一个节点一定相同。
{
if (size1 > size2)
while (size1 - size2 > 0) // 长链表先出发前进(size1 - size2)步
{
list1 = list1->next;
--size1;
}
if (size2 > size1)
while (size2 - size1 > 0)
{
list2 = list2->next;
--size2;
}
while (list1 != list2) // 两个链表同时前进,每次一步,相遇的第一个节点,即为两个链表相交的第一个节点。
{
list1 = list1->next;
list2 = list2->next;
}
value = list1;
return true;
}
else
return false;
}