演算法整理 快慢指標 鍊錶的環檢測

2021-10-14 16:25:35 字數 2018 閱讀 6123

鍊錶是程式設計中最常見的資料結構,當我們遍歷鍊錶時如果鍊錶中存在閉環(如下圖),會造成無限迴圈的情況。為了解決這個問題我們需要在遍歷之前對鍊錶做環檢測。

我們設定兩個指標如下圖

然後快指標每次移動兩個節點,慢指標每次移動乙個節點,就像兩個人在操場上跑,乙個跑得快乙個跑得慢,那麼如果一直跑下去兩人總會相遇。當兩個指標相遇就代表鍊錶存在閉環。此時的**實現應該是這樣的:

linkednode

*checkcycle()

}return

nullptr

;}

這個時候我們已經可以確定鍊錶是否有閉環,那麼在進一步我們還可以找到閉環的入口。就是上圖6的節點。

如下圖所示,設煉表中環外部分的長度為 l。指標進入環後,又走了 e的距離與 fast 相遇。此時,fast 指標已經走完了環的 n 圈,環長c。由於我們設定快指標是慢指標的2倍速度。因此有:r+e=n*c,演算過程如下:

由以上結果可知:如果此時第三個指標以和慢指標一樣的速度從煉表頭開始出發,它和慢指標一定會在c點相遇,那麼可以得知它們的第一次相遇點就是環入口。進一步完善上面的**:

linkednode

*checkcycle()

std::cout <<

"環入口值: "

<< fast-

>value << std::endl;

return fast;}}

return

nullptr

;}

/*

list的單向鍊錶實現

*/template

<

class

t>

class

linkednode

linkednode()

};template

<

class

t>

class

linkedlist

// 尾插法

bool

add(linkednode

*node)

temp-

>next = node;

return

true;}

bool

add(t t)

intsize()

linkednode

*temp;

temp =

this

->head;

int size =0;

while

(temp !=

nullptr

)return size;

} linkednode

*checkloop()

std::cout <<

"環入口值: "

<< fast-

>value << std::endl;

return fast;}}

return

nullptr;}

// 遍歷操作

void

foreach

(void

(*fun)

(t item,

int index)

)const

}// 對映操作

template

<

typename v>

linkedlist

map(v(

*fun)

(t item,

int index)

)return newlist;}}

;

鍊錶快慢指標

public listnode removenthfromend listnode head,int n 為了找到要刪除的節點的前乙個節點,所以此處讓fast.next null while fast.next null 此時head為倒數第n個節點的前乙個節點。slow.next slow.nex...

快慢指標判斷鍊錶是否有環

關於鍊錶是否有環,其實是一系列問題,主要包括以下幾個 使用快慢指標fast和slow,fast每次走兩步,slow每次走一步,如果有環,肯定會相遇,如果沒有,則指標fast遇到null退出。追及相遇問題。在環上相遇後,記錄第一次相遇點為pos,之後指標slow繼續每次走1步,fast每次走2步。在下...

鍊錶演算法 檢測環

給定乙個單鏈表,判斷其中是否有環,已經是乙個比較老同時也是比較經典的問題,在網上蒐集了一些資料,然後總結一下大概可以涉及到的問題,以及相應的解法。首先,關於單鏈表中的環,一般涉及到一下問題 1.給乙個單鏈表,判斷其中是否有環的存在 2.如果存在環,找出環的入口點 3.如果存在環,求出環上節點的個數 ...