判斷乙個單鏈表是否有環及環的鏈結點

2021-07-10 09:37:39 字數 1888 閱讀 3563

給定乙個單鏈表,只給出頭指標h:

1、如何判斷是否存在環?

2、如何知道環的長度?

3、如何找出環的連線點在**?

4、帶環鍊錶的長度是多少?

解法:

1、對於問題1,使用追趕的方法,設定兩個指標slow、fast,從頭指標開始,每次分別前進1步、2步。如存在環,則兩者相遇;如不存在環,fast遇到null退出。

2、對於問題2,記錄下問題1的碰撞點p,slow、fast從該點開始,再次碰撞所走過的運算元就是環的長度s。

3、問題3:有定理:碰撞點p到連線點的距離=頭指標到連線點的距離,因此,分別從碰撞點、頭指標開始走,相遇的那個點就是連線點。(證明在後面附註)

4、問題3中已經求出連線點距離頭指標的長度,加上問題2中求出的環的長度,二者之和就是帶環單鏈表的長度

判斷是否存在環的程式:

bool i***itsloop(slist *head)  

return !(fast == null || fast->next == null);

}

尋找環連線點(入口點)的程式:

slist* findloopport(slist *head)  

if (fast == null || fast->next == null)

return null;

slow = head;

while (slow != fast)

return slow;

}

附註

問題3的證明如下:

鍊錶形狀類似數字 6 。

假設甩尾(在環外)長度為 a(結點個數),環內長度為 b 。

則總長度(也是總結點數)為 a+b 。

從頭開始,0 base 編號。

將第 i 步訪問的結點用 s(i) 表示。i = 0, 1 ...

當 i<a 時,s(i)=i ;

當 i≥a 時,s(i)=a+(i-a)%b 。

分析追趕過程:

兩個指標分別前進,假定經過 x 步後,碰撞。則有:s(x)=s(2x)

由環的週期性有:2x=tb+x 。得到 x=tb 。

另,碰撞時,必須在環內,不可能在甩尾段,有 x>=a 。

連線點為從起點走 a 步,即 s(a)。

s(a) = s(tb+a) = s(x+a)。

得到結論:從碰撞點 x 前進 a 步即為連線點。

根據假設易知 s(a-1) 在甩尾段,s(a) 在環上,而s(x+a) 必然在環上。所以可以發生碰撞。

而,同為前進 a 步,同為連線點,所以必然發生碰撞。

綜上,從 x點和從起點同步前進,第乙個碰撞點就是連線點。

假設單鏈表的總長度為l,頭結點到環入口的距離為a,環入口到快慢指標相遇的結點距離為x,環的長度為r,慢指標總共走了s步,則快指標走了2s步。另外,快指標要追上慢指標的話快指標至少要在環裡面轉了一圈多(假設轉了n圈加x的距離),得到以下關係:

s = a + x;

2s = a + nr + x;

=>a + x = nr;

=>a = nr - x;

由上式可知:若在頭結點和相遇結點分別設一指標,同步(單步)前進,則最後一定相遇在環入口結點,搞掂!

附圖:

判斷乙個單鏈表是否有環及環

判斷乙個單鏈表是否有環及環的鏈結點 蒙恩的罪人 給定乙個單鏈表,只給出頭指標h 1 如何判斷是否存在環?2 如何知道環的長度?3 如何找出環的連線點在 4 帶環鍊錶的長度是多少?解法 1 對於問題1,使用追趕的方法,設定兩個指標slow fast,從頭指標開始,每次分別前進1步 2步。如存在環,則兩...

判斷乙個單鏈表是否有環及環入口

要求 不允許修改鍊錶結構 時間複雜度o n 空間複雜度o 1 判斷是否有環 如果鍊錶有環,那麼在遍歷時則會陷入死迴圈。使用快慢指標 快指標移動2步,慢指標移動1步 如果走到某一步,快慢指標相遇,則說明有環 環入口點 我們假設鍊錶頭部到環入口距離 len,環入口到快慢指標交匯點的距離為x,環的長度為r...

判斷乙個單鏈表是否有環

一 判斷鍊錶是否存在環 設定兩個指標 fast,slow 初始值都指向頭,slow每次前進一步,fast每次前進二步,如果鍊錶存在環,則fast必定先進入 環,而slow後進入環,兩個指標必定相遇。當然,fast先行頭到尾部為null,則為無環鏈表 程式如下 bool i itsloop listn...