如何判斷鍊錶中有無環
單向鍊錶中有環的話,如果我們對此鍊錶進行遍歷,則將無窮盡。因此有必要判斷乙個單向鍊錶是否有環。
假如乙個單向鍊錶中存在環,如下圖:(乙個小矩形代表鍊錶中的乙個節點)
虛線箭頭代表中間有無數節點。
先說演算法,然後再來證明演算法的正確性。
以下演算法可以判斷乙個單向鍊錶中是否有環(不討論詳細資料結構,只簡要說明。設結點的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...