三類情況:
(1)
(2)
(3)
1、遇到這個問題,首先想到的是遍歷鏈表,尋找是否有相同地址,借此判斷鏈表中是否有環。
listnode_ptr current =head->next;
while(current)
{
if(current==head)
{
printf("有環!\n");
return 0;
}
else
{
current=current->next;
}
}
printf("無環!\n");
return 0;
這段代碼滿足了(1)(鏈表無環)、(2)(鏈表頭尾相連)兩類情況,卻沒有將(3)情況考慮在內,如果出現(3)類情況,程序會進入死循環。
2、將(3)考慮在內,首先想到我們可能需要一塊空間來存儲指針,遍歷新指針時將其和儲存的舊指針比對,若有相同指針,則該鏈表有環,否則將這個新指針存下來后繼續往下讀取,直到遇見NULL,這說明這個鏈表無環。
上述方法雖然可行,可是否還有更簡便的算法?
3、假設有兩個學生A和B在跑道上跑步,兩人從相同起點出發,假設A的速度為2m/s,B的速度為1m/s,結果會發生什么?
答案很簡單,A繞了跑道一圈之后會追上B!
將這個問題延伸到鏈表中,跑道就是鏈表,我們可以設置兩個指針,a跑的快,b跑的慢,如果鏈表有環,那么當程序執行到某一狀態時,a==b。如果鏈表沒有環,程序會執行到a==NULL,結束。
listnode_ptr fast=head->next;
listnode_ptr slow=head;
while(fast)
{
if(fast==slow)
{
printf("環!\n");
return 0;
}
else
{
fast=fast->next;
if(!fast)
{
printf("無環!\n");
return 0;
}
else
{
fast=fast->next;
slow=slow->next;
}
}
}
printf("無環!\n");
return 0;
4、關于算法復雜度:
如圖,鏈表長度為n,環節點個數為m,則循環 t=n-m 次時,slow進入環中,此時,我們假設fast與slow相距x個節點,那么,經過t'次循環,二者相遇時,有:
2t'=t'+(m-x) -> t'=m-x -> t'<=m.
因此,總共循環了T=t+t' <= n. 算法復雜度為O(n).