您的位置:首页 > 其它

判断两个单向链表是否存在环

2014-03-30 15:33 197 查看
今天Mayuyu来带领你们讨论如下三个问题:

(1)如何判断一个单链表是否存在环 ?

(2)如果存在环,如何找到环的入口点?

(3)两个链表中有环时,如何判断相交?

问题一

我们设置两个指针,分别是fast和slow,初始都指向这个单向链表的表头,fast每次走两步,而slow每次走一步,

所以,我们知道如果有环,那么fast先进入环,slow后进入环,在经过若干次这样的步骤,必定会有fast与slow

相遇,那么我们就能判断是否存在环了。如果不存在环,则fast先走到链表尾。

所以我们很容易得到如下代码:

bool isLoop(list *head)
{
list *slow = head;
list *fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast) return true;
}
return false;
}


问题二

上面问题一我们已经能判断一个单向的链表是否存在环,如果一个单向链表存在环,我们如何求它的环入口点?

如下图



首先,我们设head到入口点的距离为

,入口点到相遇点的距离为

,沿着相遇点继续走到入口点的距离为



链表总长度为

,fast指针与slow指针相遇时slow一共走了

步,那么很明显fast就走了

步,相遇时fast比

slow多走了

圈。

所以我们很容易得到

,即


又由于

,所以

,得到:


这个表达式说明从相遇点到入口点的距离与head到入口点的距离取余后是相等的。所以我们可以在相遇点和head处

各设置一个指针,然后同时走,它们会在入口处相遇,这样我们也就能找到这个入口了。

代码如下:

list *FindPort(list *head)
{
list *slow = head;
list *fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast) break;
}
if(fast == NULL || fast-next == NULL)
return NULL;
slow = head;
while(slow != fast)
{
slow = slow->next;
fast = fast->next;
}
return slow;
}


问题三

实际上,我们先要明确一个事实,那就是如果一个单链表有环,另一个单链表没有环,那么这两个单链表一定不会

相交。这是单链表的next指向的唯一性决定的,一个节点不可能有两个或者多个后继分支。

所以,如果是两个有环链表相交,那么它们一定存在一个公共的环,大致如下两个图形:





所以,明确了以上事实之后,我们可以这样来做:

先分别求出这两个有环链表的环的入口点,如果入口点相等,那么说明这两个有环链表就相交了。如果不相等,就有

两种情况:

(1)两个有环链表不相交

(2)它们相交但环入口点不同

那么我们如何判断,这个就比较简单了。

我们设一个环的入口点为port,在另一个环的入口点设置一个指针p往后走,如果一周内出现p->next == port,

那么说明这两个有环链表共环,也就是说相交,否则这两个有环链表不相交。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: