1.链表的相交问题:
链表的相交基本就上面俩种情况;但是对于这俩种情况来说,处理的方法都是想相同的
(1)如何判断是否有交点:
这就比较简单了,只需要定义一个指针,一直让他指到链表的最后一个节点,再来判断俩个指针是否相等。如果相等的话说明俩个链表一定是有交点的(不存在有交点但是最后一个节点不相同的问题,因为这是单链表,每个节点只能保存下一个节点的地址,不能保存俩个节点的地址)。
(2)如果有交点,返回相交的节点:
分别求出俩个链表的有效长度的差值n,然后定义指针p指向长链表,让p=p->next执行n次,在定义指针q指向短链表,俩个指针一起向后走,当他们相等的时候也就是相交的节点。
代码实现:
List* Intersect(List& Phead1, List& Phead2)
{
if (Phead1.next == nullptr || Phead2.next == nullptr)
{
return nullptr;
}
int len1 = 0;
int len2 = 0;
List* p = Phead1.next;
List* q = Phead2.next;
for (p; p != nullptr; p = p->next)
{
++len1;
}
for (q; q != nullptr; q = q->next)
{
++len2;
}
if (p != q) //判断是否相交
{
return nullptr;
}
int n = len1 > len2 ? len1 - len2 : len2 - len1;
if (len1 > len2) //找到相交节点
{
p = &Phead1;
q = &Phead2;
for (int i = 0; i < n; ++i)
{
p = p->next;
}
while (1)
{
p = p->next;
q = q->next;
if (p == q)
{
return p; //return q也是一样的
}
}
}
if (len1 < len2)
{
p = &Phead1;
q = &Phead2;
for (int i = 0; i < n; ++i)
{
q = q->next;
}
while (1)
{
p = p->next;
q = q->next;
if (p == q)
{
return p; //return q也是一样的
}
}
}
}
2.链表环问题
判断链表是否有环,如果有的话返回入环节点:
判断是否有环,可以使用快慢指针,定义俩个指针,p, q。p每次往后走俩步,q走一步。如果链表有环的环,那么这俩个指针一定会相交。如果没有环,那么p一定是先走到终点的,也就是最后一个节点:
那找到相交节点后,就需要计算入环节点了。这里需要一些计算:
我们设A到B的距离为x,也就是绿色的距离
B到C的距离为y,C到B的距离为z;由于他是单链表,所以从B到C和从C到B并不相同。
但由于我们需要求的是x;并且快指针所走的距离是慢指针的2倍
即ptwo=2pone;
所以:x+n*(y+z)+y=2x+2x+2*(n-k)*(y+z)
化简:x+y=2x+2y+(2*(n-k)-n)(y+z)
x+y=(2k-n)(y+z)
x=(2k-n)(y+z)-y
x=(2k-n-1)(y+z)+z;
这时候我们可以看到,2k-n-1一定是个整数,并且大于等于0;
所以说,x这段距离等于整数倍的环(y+z)再加上z
也就是说用俩个速度一样的指针,一个从A开始跑,一个从C开始跑
A跑到B的时候刚好另一个指针也跑到B
所以就能求出来入环的节点了
代码实现:
List* loop(List& phead)
{
List* pone = &phead;
List* ptwo = &phead;
while (1)
{
pone = pone->next;
ptwo = ptwo->next->next;
if (ptwo == nullptr || ptwo->next == nullptr)
{
return nullptr;
}
else if (pone == ptwo)
{
break;
}
}
pone = &phead;
while (1)
{
if (pone == ptwo)
{
break;
}
pone = pone->next;
ptwo = ptwo->next;
}
return pone;
}
以上就是单链表的相交问题和环问题。
感谢观看!