單向鍊錶判環系列問題及C 實現

2021-08-18 04:10:05 字數 1780 閱讀 8104

問題描述:

關於單向鍊錶判環,有一系列問題,首先

1、給定乙個單向鍊錶,判別鍊錶中是否存在環路?

2、如果存在環路,怎麼知道環路的長度?

3、如果存在環路,鍊錶中環的入口點在哪兒?

4、引申問題:如何求兩個單向鍊錶的第乙個公共子節點?

解答:

1、判斷單向鍊錶是否有環路,乙個直觀的想法是遍歷鍊錶的每乙個結點,並判斷每個結點位址是否和前方出現過結點位址相同,這種辦法需要額外增加乙個變數來儲存已經出現過的結點位址,時間複雜度最差也會達到o(n2),單向鍊錶判環還有更簡單的辦法。

分別定義slow,fast兩個結點指標指向煉表頭結點,每次令slow指標向後移動乙個結點,fast指標向後移動兩個結點,如果鍊錶中存在環路,那麼兩個指標一定會在某乙個結點相遇,且此時slow指標還未遍歷完鍊錶,為什麼呢?

簡單想想,fast指標每次向後移動兩步,slow指標每次移動一步,如果鍊錶存在著環路,那麼當兩個指標都進入環路後,fast指標往後數距離slow指標的距離在每一次移動時,都會減1,因為fast指標每次只多移動一步,所以兩個指標也不會錯過相遇的機會。時間複雜度為o(n)。

2、第一問求出存在環路,從一問中的相遇點繼續往後移動,當再次回到相遇點時,得到環路長度。

3、第二問求出環路長度n,重新定義兩個指標p1,p2指向鍊錶頭部,先令p2向後移動n步,再令p1,p2一起向後移動,兩個指標相遇時即到達入口點。為什麼?

反過來想,如果我們需要p1,p2指標在入口點相遇,那麼p2就必須比p1多走n步,因為存在環,這樣p1,p2正好相遇。

4、這個問題由於比較類似,所以記錄在一起,實際上和上面三問沒有關聯,這裡暫時不做**實現。解法:因為單向鍊錶, 所以兩鍊錶一定呈y型,而不是x型。先遍歷一遍兩個鍊錶,求出長鍊錶比短鍊錶長多少n個結點,然後長鍊表指標先移動n步,後一起移動兩個指標,相遇時即為第乙個公共子節點。時間複雜度o(n),不需要額外輔助空間。

具體**如下:

/*單向鍊錶系列問題*/

#include using namespace std;

/*單向鍊錶結點*/

class listnode

};/*解決第乙個問題函式,求是否存在環,如存在,則返回相遇結點*/

listnode* meetnode(listnode* phead)

return null;

}/*解決第二三個問題,求環路長度,並返回環的入口點*/

listnode* entryofloop(listnode* phead, listnode* meetnode)

//求入口點

listnode* p1 = phead;

listnode* p2 = phead;

for (int i = 0; i < count; i++)

p2 = p2->next;

while (p1 != p2)

return p1;

}int main()

p->next = p2;

phead = phead->next;

//執行環路函式

listnode* meetnode = meetnode(phead);

listnode* entrynodeofloop = entryofloop(phead, meetnode);

//輸出入口點值

cout << entrynodeofloop->val << endl;

return 0;

}

以上為c++**,有問題歡迎聯絡博主。

單向鍊錶是否有環問題 C

問題描述 在單向鍊錶中,每個結點都包含乙個指向下乙個結點的指標,最後乙個結點的這個指標被設定為空。但如果把最後乙個結點的指標指向鍊錶中存在的某個結點,就會形成乙個環,在順序遍歷鍊錶的時候,程式就會陷入死迴圈。如何檢測乙個鍊錶中是否有環,如果檢測到環,如何確定環的入口點 即求出環長,環前面的鏈長 一種...

環型單向鍊錶 約瑟夫問題

josephu問 題為 設編號為1,2,n的n個人圍坐 圈,約定編號為k 1 k n 的人從1開始報數,數到 m的那個人出列,它的下一位又從1開始報數,數到m的那個人又出列,依次類推,直到所有人出列為止,由此 產生 乙個出隊編號的序列。用乙個不帶頭結點的迴圈鍊錶來處理josephu問題 先構成 乙個...

c實現單向鍊錶

實現乙個單向鍊錶的 建立 插入 刪除 排序 冒泡 逆向 搜尋中間節點 include include include using namespace std typedef struct student node 建立鍊錶 node create else 4.釋放頭節點 p next null p...