判斷單鏈表是否有環

2021-07-01 22:01:37 字數 2564 閱讀 1948

給定乙個單鏈表,只給出頭指標h:

1、如何判斷是否存在環?

2、如何知道環的長度?

3、如何找出環的連線點在**?

4、帶環鍊錶的長度是多少?

解法:

1、對於問題1,使用追趕的方法,設定兩個指標slow、fast,從頭指標開始,每次分別前進1步、2步。如存在環,則兩者相遇;如不存在環,fast遇到null退出。

2、對於問題2,記錄下問題1的碰撞點p,slow、fast從該點開始,再次碰撞所走過的運算元就是環的長度s。

3、問題3:有定理:碰撞點p到連線點的距離=頭指標到連線點的距離,因此,分別從碰撞點、頭指標開始走,相遇的那個點就是連線點。(證明在後面附註)

4、問題3中已經求出連線點距離頭指標的長度,加上問題2中求出的環的長度,二者之和就是帶環單鏈表的長度

void isloop(llink head)

}if(!loop)

cout<<"thislink has not loop\n";

else

while(p!=r);

--loopcount;

while(p!=q)//得到環的入口結點,同時計算得到非環的結點數

--nonloop;

cout<<"\nstartof loop:"cout<<"\ncountof nonloop: "<

<<"\ncount of loop:"<

<<"\ncount of linknode:"<}}

判斷是否存在環的程式:

bool i***itsloop(slist *head)   

return !(fast == null || fast->next == null); } 

尋找環連線點(入口點)的程式:

slist* findloopport(slist *head) 

if (fast == null || fast->next == null) 

return null; 

slow = head; 

while (slow != fast) 

return slow; } 

亦可以用類似與hash表的方法,即設立乙個陣列,將鍊錶結點中的值做陣列下標,當賦值衝突時就是環的接入點

boolisloop(llink p)

a[p->data]=-1;

++n;

p=p->next;

}return false;

}llink creatlinkloop()

//建立乙個有環的鍊錶

cin.clear();

cin.sync();

srand(time(0));

q->next=findnode(head,rand()%n);//隨機產生環的接入點

return head;

}llink findnode(llink head,int n)//找出鍊錶中的第n個結點

附註

問題2的證明如下:

鍊錶形狀類似數字 6 。

假設甩尾(在環外)長度為 a(結點個數),環內長度為 b 。

則總長度(也是總結點數)為 a+b 。

從頭開始,0 base 編號。

將第 i 步訪問的結點用 s(i) 表示。i = 0, 1 ...

當 i<a 時,s(i)=i ;

當 i≥a 時,s(i)=a+(i-a)%b 。

分析追趕過程:

兩個指標分別前進,假定經過 x 步後,碰撞。則有:s(x)=s(2x)

由環的週期性有:2x=tb+x 。得到 x=tb 。

另,碰撞時,必須在環內,不可能在甩尾段,有 x>=a 。

連線點為從起點走 a 步,即 s(a)。

s(a) = s(tb+a) = s(x+a)。

得到結論:從碰撞點 x 前進 a 步即為連線點。

根據假設易知 s(a-1) 在甩尾段,s(a) 在環上,而s(x+a) 必然在環上。所以可以發生碰撞。

而,同為前進 a 步,同為連線點,所以必然發生碰撞。

綜上,從 x點和從起點同步前進,第乙個碰撞點就是連線點。

假設單鏈表的總長度為l,頭結點到環入口的距離為a,環入口到快慢指標相遇的結點距離為x,環的長度為r,慢指標總共走了s步,則快指標走了2s步。另外,快指標要追上慢指標的話快指標至少要在環裡面轉了一圈多(假設轉了n圈加x的距離),得到以下關係:

s = a + x;

2s = a + nr + x;

=>a + x = nr;

=>a = nr - x;

由上式可知:若在頭結點和相遇結點分別設一指標,同步(單步)前進,則最後一定相遇在環入口結點,搞掂!

判斷單鏈表是否有環

1 如何判斷乙個鍊錶是不是這類鍊錶?2 如果鍊錶為存在環,如果找到環的入口點?解答 一 判斷鍊錶是否存在環,辦法為 設定兩個指標 fast,slow 初始值都指向頭,slow每次前進一步,fast每次前進二步,如果鍊錶存在環,則fast必定先進入環,而slow後進入環,兩個指標必定相遇。當然,fas...

判斷單鏈表是否有環

鍊錶結構 struct list 1 判斷單鏈表是否有環 採用追趕法,設定兩個指標p和q,從煉表表頭開始,p每一步走兩個節點,q每一步走乙個節點,如果鍊錶有環則p和q必相遇。如下 判斷鍊錶是否有環,時間複雜度o n 空間複雜度o 1 list hasloopinlist list head else...

判斷單鏈表是否有環

1 如何判斷乙個鍊錶是不是這類鍊錶?2 如果鍊錶為存在環,如果找到環的入口點?解答 一 判斷鍊錶是否存在環,辦法為 設定兩個指標 fast,slow 初始值都指向頭,slow每次前進一步,fast每次前進二步,如果鍊錶存在環,則fast必定先進入環,而slow後進入環,兩個指標必定相遇。當然,fas...