如何判斷單鏈表是否出現環

2021-07-10 03:29:10 字數 1105 閱讀 9208

如何判斷鍊錶中有無環

單向鍊錶中有環的話,如果我們對此鍊錶進行遍歷,則將無窮盡。因此有必要判斷乙個單向鍊錶是否有環。

假如乙個單向鍊錶中存在環,如下圖:(乙個小矩形代表鍊錶中的乙個節點)

虛線箭頭代表中間有無數節點。

先說演算法,然後再來證明演算法的正確性。

以下演算法可以判斷乙個單向鍊錶中是否有環(不討論詳細資料結構,只簡要說明。設結點的next域為指向下一結點的指標):

/*  鍊錶的頭指標為h  */

if((null == h) || (null == h->next)) /* 頭指標為空或者鍊錶中只有乙個節點,則無環,退出*/

p = q = h; /* 設p和q 指標,均指向頭結點*/

while(1)

if(p == q) /* 鍊錶中有環*/

} 可以看出,以上演算法設定了兩個指標p和q,他們分別以速度為1和2前進,如果到某一次迴圈發現他們相等,即都指向同一結點(空節點除外,以後討論的節點都不包含空節點),則說明這個單向鍊錶中存在迴圈。否則就是沒有迴圈。

我們注意到,指標p和q分別以速度為1和2前進。如果以其它速度前進是否可以呢?

下面我主要討論這個問題。

假設p和q分別以速度為v1和v2前進。如果有環,設指標p和q第一次進入環時,他們相對於環中第乙個節點的偏移位址分別為a和b(可以把偏移位址理解為節點個數)。如上圖。

這樣,可以看出,鍊錶有環的充要條件就是某一次迴圈時,指標p和

q的值相等,就是它們相對環中首節點的偏移量相等。

我們設環中的結點個數為n,程式迴圈了m次。

由此可以有下面等式成立:(mod(n)即對n取餘)

(a+m*v1)mod(n) = (b+m*v2) mod(n)

設等式左邊mod(n)的最大整數為k1,等式右邊mod(n)的最大整數為k2,則

(a+m*v1)-k1*n = (b+m*v2)-k2*n

m= |((k2-k1)*n+a-b)/( v2-v1)|       ①

如果是等式①成立,就要使迴圈次數m為一整數。顯然如果v2-v1為1,則等式成立。

這樣p和q分別以速度為v1和v2且|v2-v1|為1時,按以上演算法就可找出鍊錶中是否有環。

如何判斷單鏈表是否存在環

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

如何判斷單鏈表是否存在環

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

判斷單鏈表是否有環

1 如何判斷乙個鍊錶是不是這類鍊錶?2 如果鍊錶為存在環,如果找到環的入口點?解答 一 判斷鍊錶是否存在環,辦法為 設定兩個指標 fast,slow 初始值都指向頭,slow每次前進一步,fast每次前進二步,如果鍊錶存在環,則fast必定先進入環,而slow後進入環,兩個指標必定相遇。當然,fas...