日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

有环单链表

發(fā)布時(shí)間:2024/4/15 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 有环单链表 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? ? ? 單鏈表中可能存在環(huán), 那么如何判斷單鏈表中是否有環(huán)呢?若單鏈表中存在環(huán),怎么樣確定環(huán)的位置?

? ? ? 如果一個(gè)單鏈表中存在環(huán),在遍歷鏈表時(shí),一旦進(jìn)入環(huán),就開始循環(huán)遍歷環(huán)上的節(jié)點(diǎn)。如果只用一個(gè)指針來(lái)遍歷單鏈表,我們無(wú)法判斷單鏈表中是否存在環(huán)。用兩個(gè)指針就可以完成這個(gè)任務(wù)。

? ? ? 設(shè)有兩個(gè)指針p1,p2。初始時(shí)p1和p2均指向鏈表的第一個(gè)節(jié)點(diǎn)。在遍歷過(guò)程中,p1總是移向下一個(gè)節(jié)點(diǎn)(向前移動(dòng)1步),同時(shí)p2總是指向下一個(gè)節(jié)點(diǎn)的后繼節(jié)點(diǎn)(向前移動(dòng)兩步)。如果單鏈表中存在環(huán),p2在遍歷過(guò)程中一定會(huì)與p1指向同一個(gè)節(jié)點(diǎn)(這是一個(gè)相遇問(wèn)題,p2的速度是p1的兩倍,它們一定會(huì)在環(huán)上相遇);否則在遍歷過(guò)程中p2不可能與p1相遇。

? ? ? 圖1中展示了一個(gè)有環(huán)單鏈表。環(huán)外有 n1 個(gè)節(jié)點(diǎn),環(huán)上有 n2 個(gè)節(jié)點(diǎn),環(huán)的入口節(jié)點(diǎn)是 x 。設(shè) p2 和 p1 在 y 節(jié)點(diǎn)處相遇。將環(huán)上的節(jié)點(diǎn)從環(huán)的入口開始沿著鏈表編號(hào),編號(hào)為1, 2, …, n2。 設(shè) y 節(jié)點(diǎn)的編號(hào)為 n3 。則有:

2 *(n1 + k1 * n2 + n3)= n1 + k2 * n2 + n3

? ? ? 其中k1,k2分別是在相遇之前p1,p2各自遍歷環(huán)的次數(shù)。

? ? ? 令 k = k2 - 2 * k1, k >= 1。于是,

n1 = k * n2 – n3 = (k - 1) * n2 + n2 – n3

? ? ? 這就暗示了,如果令p1指向鏈表的第一個(gè)節(jié)點(diǎn),p2指向y節(jié)點(diǎn),p1和p2每次移向下一個(gè)節(jié)點(diǎn)遍歷鏈表,它們會(huì)在x節(jié)點(diǎn)處相遇,即找到了環(huán)的入口。 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

       ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??    ??

圖 1? 有環(huán)單鏈表

?

? ? ? 利用數(shù)組next[]來(lái)表示鏈表,節(jié)點(diǎn)從0開始編號(hào),next[i]代表i節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn),-1標(biāo)識(shí)鏈表的結(jié)尾。例如數(shù)組{1, 2, 3, 4, 5, -1}表示鏈表 0->1->2->3->4->5->-1,這個(gè)鏈表中沒(méi)有環(huán)。數(shù)組 {1, 2, 3, 4, 5, 6, 4} 表示鏈表 0->1->2->4->5->6->4,是一個(gè)有環(huán)的單鏈表。下面是找出鏈表中環(huán)的位置算法的C語(yǔ)言實(shí)現(xiàn):

1 #include <stdio.h> 2 3 int find_circle(int next[], int n) { 4 int p1 = 0, p2 = 0; 5 do { 6 p1 = next[p1]; 7 if (p2 != -1 && next[p2] != -1) { 8 p2 = next[next[p2]]; 9 } else { 10 return -1; 11 } 12 } while (p1 != p2); 13 p1 = 0; 14 do { 15 p1 = next[p1]; 16 p2 = next[p2]; 17 } while (p1 != p2); 18 return p1; 19 } 20 21 int main() { 22 // 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 4 23 int next[7] = {1, 2, 3, 4, 5, 6, 4}; 24 int node = find_circle(next, sizeof(next) / sizeof(int)); 25 if (node != -1) { 26 printf("%d\n", node); 27 } else { 28 printf("no circle\n"); 29 } 30 return 0; 31 }

? ? ? ?這個(gè)算法可應(yīng)用到另一個(gè)問(wèn)題上。 問(wèn)題描述如下:

? ? ? ?有 n 個(gè)整數(shù), 這些整數(shù)的取值范圍為 [1, n-1], 由鴿巢原理可知至少有一個(gè)整數(shù)出現(xiàn)了兩次。 要求找到一個(gè)(只一個(gè))重復(fù)出現(xiàn)的數(shù)字。

? ? ? ?如 {1, 3, 2, 4, 5, 4} 中的 4 和{1, 2, 3, 3, 2}中的 2, 3 均為重復(fù)出現(xiàn)的數(shù)字。

? ? ? ?我們利用find_circle解決這個(gè)問(wèn)題基于這樣一個(gè)觀察,就是一個(gè)滿足題目條件的數(shù)組可以看做多個(gè)循環(huán)單鏈表, 這些鏈表之間可能有公共節(jié)點(diǎn), 我們從任何一個(gè)節(jié)點(diǎn)開始遍歷鏈表都可以找到一個(gè)環(huán)。 從0節(jié)點(diǎn)開始遍歷,環(huán)的入口就是一個(gè)重復(fù)出現(xiàn)的數(shù)字; 從其他節(jié)點(diǎn)開始遍歷則不一定能夠找到重復(fù)數(shù)字。(想一想,為什么?)

? ? ? ?如 {1, 3, 2, 4, 5, 4} 可以看做兩個(gè)鏈表 0->1->3->4->5->4, 2->2?

? ? ? ?如 {1, 2, 3, 3, 2} 可以看做是 0->1->2->3->3, 4->2->3->3?

?

?

?

轉(zhuǎn)載于:https://www.cnblogs.com/william-cheung/p/3757841.html

總結(jié)

以上是生活随笔為你收集整理的有环单链表的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。