參考資料:
1. 維基百科
判圈演算法&redirect=no
2. floyd判圈演算法(floyd cycle detection algorithm),又稱龜兔賽跑演算法(tortoise and hare algorithm),該演算法由美國科學家羅伯特·弗洛伊德發明。
可以在有限狀態機、迭代函式或者鍊錶上判斷是否存在環,以及求出該環的起點與長度的演算法。
如果存在環,那麼
從同乙個起點(即使這個起點不在某個環上)處,同時開始以不同速度前進的2個指標
必定會在某個時刻相遇。
(1)求環
初始狀態下,假設已知某個起點
節點為節點s。現設兩個指標t和h,將它們均指向s。
同時讓t和h往前推進,h的速度為t的2倍),直到h無法前進,即到達某個沒有後繼的節點時,就可以確定從s出發不會遇到環。反之當t與h再次相遇時,就可以確定從s出發一定會進入某個環,設其為環c。(h和t推進的步數差是環長的倍數)
(2)求環的長度
上述演算法剛判斷出存在環c時,t和h位於同一節點,設其為節點m。僅需令h不動,而t不斷推進,最終又會返回節點m,統計這一次t推進的步數,就是環c的長度。
(3)求環的起點
為了求出環c的起點,只要令h仍均位於節點m,而令t返回起點節點s。隨後,同時讓t和h往前推進,且速度相同。持續該過程直至t與h再一次相遇,此相遇點就是環c的乙個起點。
why?
假設出發起點到環起點的距離為m,已經確定有環,環的周長為n,(第一次)相遇點距離環的起點的距離是k。那麼當兩者相遇時,慢指標(t)移動的總距離i = m + a * n + k,快指標(h)的移動距離為2i,2i = m + b * n + k。其中,a和b分別為t和h在第一次相遇時轉過的圈數。讓兩者相減(快減慢),那麼有i = (b - a) * n。即i是圈長度的倍數。
將乙個指標移到
出發起點
s,另乙個指標仍呆在相遇節點m處兩者同時移動,每次移動一步。當第乙個指標前進了m,即到達環起點時,另乙個指標距離鍊錶起點為i + m。考慮到i為圈長度的倍數,可以理解為指標從鍊錶起點出發,走到環起點,然後繞環轉了幾圈,所以第二個指標也必然在環的起點。即兩者相遇點就是環的起點。
1 t := &s
2 h := &s //令指標t和h均指向起點節點s。
3 repeat
4 t := t->next
5 h := h->next
6 if h is not null //要注意這一判斷一般不能省略
7 h := h->next
8 until t = h or h = null
9 if h != null //如果存在環的話
10 n := 0
11 repeat //求環的長度
12 t := t->next
13 n := n+1
14 until t = h
15 t := &s //求環的乙個起點
16 while t != h
17 t := t->next
18 h := h->next
19 p := *t
(1)時間複雜度
注意到當指標t到達環c的乙個起點節點p時(此時指標h顯然在環c上),之後指標t最多僅可能走1圈。若設節點s到p距離為
(2)空間複雜度
僅需要創立指標t、指標h,儲存環長n、環的乙個起點p。空間複雜度為
應用
對於有限狀態機與鍊錶,可以判斷從某個起點開始是否會返回到訪問過執行過程中的某個狀態和節點。
對於迭代函式,可以判斷其是否存在週期,以及求出其最小正週期。
Floyd判圈演算法(龜兔賽跑演算法)
一 演算法簡述 floyd判圈演算法 floyd cycle detection algorithm 又稱龜兔賽跑演算法 tortoise and hare algorithm 是乙個可以在有限狀態機 迭代函式或者鍊錶上判斷是否存在環,以及判斷環的起點與長度的演算法。二 基本思路 在某種關係下,頂點...
Floyd判圈演算法
參考 判斷鍊錶中是否有環 大概就是說兩個指標首先都指向鍊錶的首部,然後乙個每次走一步,乙個每次走兩步,如果有環,那麼慢的肯定能夠追上快的,否則快的就會先到達終點。求環的長度 兩個指標重合時,快的停止,慢的每次走一步,計算圈的長度。求環的起點 if head null slowptr slowptr ...
floyd判圈演算法
floyd判圈演算法又稱龜兔賽跑演算法 兩個指標 p1,p2 p1 每次向後跳一次 p2 每次向後跳兩次 顯然,如果 p1,p2 相遇才有環 現在我們想求環長和環的起點.設起點到環的距離為 len 環的起點離相遇點距離 rem 設兩個指標分別走了 p,q 步 那麼,p len rem a l,q l...