鍊錶環狀檢測主要有三種方法

2021-09-06 21:03:23 字數 2905 閱讀 6001

鍊錶環狀檢測主要有三種方法:

1、追趕法;如 robinzsy。

2、外部記錄法;如improgrammer。

3、內部記錄法(打記號);如viviansnow。

追趕法,利用最大公倍數原理,用2個游標,對鍊錶進行訪問,例如:p1,p2, p1訪問每步向前進1個節點,p2則每次向前前進2個節點,如果有環則p1,p2必會相遇,如果p2先遇到了null節點,則說明沒有環.

關於這個解法最形象的比喻就是在操場當中跑步,速度快的會把速度慢的扣圈可以證明,p2追趕上p1的時候,p1一定還沒有走完一遍環路,p2也不會跨越p1多圈才追上我們可以從p2和p1的位置差距來證明,p2一定會趕上p1但是不會跳過p1的因為p2每次走2步,而p1走一步,所以他們之間的差距是一步一步的縮小,4,3,2,1,0 到0的時候就重合了根據這個方式,可以證明,p2每次走三步以上,並不總能加快檢測的速度,反而有可能判別不出有環

比如,在環的周長l是偶數的時候,初始p2和p1相差奇數的時候,p2每次走三步,就永遠和p1不重合,因為他們之間的差距是: 5, 3 , 1, l-1, l-3

如何找到環路的入口? 是這裡要重點說明的內容:

解法如下: 當p2按照每次2步,p1每次一步的方式走,發現p2和p1重合,確定了單向鍊錶有環路了.接下來,讓p2回到鍊錶的頭部,重新走,每次步長不是走2了,而是走1,那麼當p1和p2再次相遇的時候,就是環路的入口了。這點可以證明的:

在p2和p1第一次相遇的時候,假定p1走了n步驟,環路的入口是在p步的時候經過的,那麼有

p1走的路徑: p+c = n; c為p1和p2相交點,距離環路入口的距離

p2走的路徑: p+c+k*l = 2*n; l為環路的周長,k是整數

顯然,如果從p+c點開始,p1再走n步驟的話,還可以回到p+c這個點, 同時p2從頭開始走的話,經過n不,也會達到p+c這點

顯然在這個步驟當中p1和p2只有前p步驟走的路徑不同,所以當p1和p2再次重合的時候,必然是在鍊錶的環路入口點上。

資料結構-鍊錶環

#include#include#define n 3

typedef int datatype;

typedef struct _node_

linknode,*linklist;

linklist creat_empty_linklist()

int empty_linklist(linklist h)

int lenth_linklist(linklist h)

return len;

}void visit_linklist(linklist h)

printf("\b\b \n");

return ;

}int insert_linklist_1(linklist h,datatype x,int pos)

void insert_linklist_2(linklist h, datatype x)

int delete_linklist_1(linklist h, int pos)

int delete_linklist_2(linklist h, datatype x)

else

}}void clear_linklist(linklist h)

}}void reverse_linklist(linklist h)

}int main()

printf("\b\b \n");

p = h;

printf("my josephus out is : ");

while(p != p->next)

h = p->next;

p->next = h->next;

printf("%d->", h->data);

free(h);

p = p->next;

}printf("%d\n", p->data);

return 0;

}

求有環單鏈表中的環長、環起點、鍊錶長

求有環單鏈表中的環長、環起點、鍊錶長

1.判斷單鏈表是否有環

使用兩個slow, fast指標從頭開始掃瞄鍊錶。指標slow 每次走1步,指標fast每次走2步。如果存在環,則指標slow、fast會相遇;如果不存在環,指標fast遇到null退出。

就是所謂的追擊相遇問題:

2.求有環單鏈表的環長

在環上相遇後,記錄第一次相遇點為pos,之後指標slow繼續每次走1步,fast每次走2步。在下次相遇的時候fast比slow正好又多走了一圈,也就是多走的距離等於環長。

設從第一次相遇到第二次相遇,設slow走了len步,則fast走了2*len步,相遇時多走了一圈:

環長=2*len-len。

3.求有環單鏈表的環連線點位置

第一次碰撞點pos到連線點join的距離=頭指標到連線點join的距離,因此,分別從第一次碰撞點pos、頭指標head開始走,相遇的那個點就是連線點。

在環上相遇後,記錄第一次相遇點為pos,連線點為join,假設頭結點到連線點的長度為lena,連線點到第一次相遇點的長度為x,環長為r。

第一次相遇時,slow走的長度 s = lena + x;

第一次相遇時,fast走的長度 2s = lena + n*r + x;

所以可以知道,lena + x = n*r;  lena = n*r -x;

4.求有環單鏈表的鍊錶長

上述2中求出了環的長度;3中求出了連線點的位置,就可以求出頭結點到連線點的長度。兩者相加就是鍊錶的長度。

程式設計實現:

下面是**中的例子:

具體**如下:

view code

執行結果:

本文**:

參考**:

檢視linux的版本主要有三種方法

檢視linux的版本主要有三種方法 1 登入到伺服器執行 lsb release a 即可列出所有版本資訊,例如 root 3.5.5biz 46 lsb release a lsb version 1.3 distributor id redhatenterpriseas description ...

C String轉int主要有四種方法

string轉int主要有四種方法 1.int.parse 是一種類容轉換 表示將數字內容的字串轉為int型別。如果字串為空,則丟擲argumentnullexception異常 如果字串內容不是數字,則丟擲formatexception異常 如果字串內容所表示數字超出int型別可表示的範圍,則丟擲...

社群接入網主要有三種接入方式

目前的社群接入網主要有三種接入方式 一是普通 線的非對稱數字使用者環路技術 adsl 二是基於光纖ip網的fttb lan技術,三是有線電視的cable modem技術。adsl是中國電信力推的接入方式,採用目前 的雙絞線入戶,免去了重新佈線的問題,優點是採用星型結構,保密性好,安全係數高,可提供5...