單鏈表有環判斷,環節點、倆鏈表相交

【摘要】有一個單鏈表,其中可能有一個環,也就是某個節點的next指向的是鏈表中在它以前的節點,這樣在鏈表的尾部造成一環。oop

1、如何判斷一個鏈表是不 是這類鏈表?spa

2、若是鏈表爲存在環,若是找到環的入口點?指針

擴展:判斷兩個單鏈表是否相交,若是相交,給出相交的第一個點。it


1).
有一個單鏈表,其中可能有一個環,也就是某個節點的next指向的是鏈表中在它以前的節點,這樣在鏈表的尾部造成一環。
問題:
1
、如何判斷一個鏈表是否是這類鏈表?
2
、若是鏈表爲存在環,若是找到環的入口點?
解答:
1、判斷鏈表是否存在環,辦法爲:
設置兩個指針(fast, slow),初始值都指向頭,slow每次前進一步,fast每次前進二步,若是鏈表存在環,則fast一定先進入環,而slow後進入環,兩個指針一定相遇。(固然,fast先行頭到尾部爲NULL,則爲無環鏈表)程序以下:
bool IsExitsLoop(slist * head)
{
slist * slow = head ,  * fast = head;
while  ( fast  &&  fast -> next )
{
slow  =  slow -> next;
fast  =  fast -> next -> next;
if  ( slow  ==  fast )  break ;
}
return   ! (fast  ==  NULL  ||  fast -> next  ==  NULL);
}
2、找到環的入口點
fast若與slow相遇時,slow確定沒有走遍歷完鏈表,而fast已經在環內循環了nast

slist *  FindLoopPort(slist * head)
{
slist * slow  =  head,  * 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;
擴展


fast = head; //slow  =  head;
while  (slow  !=  fast)
{
slow  =  slow -> next;
fast  =  fast -> next;
}
return  fast;
}

附一種易於理解的解釋:

一種On)的辦法就是(搞兩個指針,一個每次遞增一步,一個每次遞增兩步,若是有環的話二者必然重合,反之亦然):
關於這個解法最形象的比喻就是在操場當中跑步,速度快的會把速度慢的扣圈
能夠證實,p2追遇上p1的時候,p1必定尚未走完一遍環路,p2也不會跨越p1多圈才追上
咱們能夠從p2p1的位置差距來證實,p2必定會遇上p1可是不會跳過p1
由於p2每次走2步,而p1走一步,因此他們之間的差距是一步一步的縮小,43210的時候就重合了
根據這個方式,能夠證實,p2每次走三步以上,並不總能加快檢測的速度,反而有可能判別不出有環
既然可以判斷出是不是有環路,那改如何找到這個環路的入口呢?
解法以下: p2按照每次2步,p1每次一步的方式走,發現p2p1重合,肯定了單向鏈表有環路了
接下來,讓p2回到鏈表的頭部,從新走,每次步長不是走2了,而是走1,那麼當p1p2再次相遇的時候,就是環路的入口了。
這點能夠證實的:
p2p1第一次相遇的時候,假定p1走了n步驟,環路的入口是在p步的時候通過的,那麼有
p1
走的路徑:p+c n         cp1p2相交點,距離環路入口的距離
p2
走的路徑:p+c+k*L = 2*n   L爲環路的周長,k是整數
顯然,若是從p+c點開始,p1再走n步驟的話,還能夠回到p+c這個點
同時p2從頭開始走的話,通過n步,也會達到p+c這點
顯然在這個步驟當中p1p2只有前p步驟走的路徑不一樣,因此當p1p2再次重合的時候,必然是在鏈表的環路入口點上。



擴展問題:
判斷兩個單鏈表是否相交,若是相交,給出相交的第一個點(兩個鏈表都不存在環)。
比較好的方法有兩個:
1、將其中一個鏈表首尾相連,檢測另一個鏈表是否存在環,若是存在,則兩個鏈表相交,而檢測出來的依賴環入口即爲相交的第一個點。
2、若是兩個鏈表相交,那個兩個鏈表從相交點到鏈表結束都是相同的節點,咱們能夠先遍歷一個鏈表,直到尾部,再遍歷另一個鏈表,若是也能夠走到一樣的結尾點,則兩個鏈表相交。
這時咱們記下兩個鏈表length,再遍歷一次,長鏈表節點先出發前進(lengthMax-lengthMin)步,以後兩個鏈表同時前進,每次一步,相遇的第一點即爲兩個鏈表相交的第一個點。循環

 

鏈表相交必有相同的結束節點。遍歷

相關文章
相關標籤/搜索