單向鏈表當中的環路判別問題

來源:互聯網
上載者:User

有一個單向鏈表,如何判定這個鏈表當中是否包含有環路,以及如何定位環路在鏈表當中的開始點呢?

關於第一個問題,網路上可以搜尋到,用兩個指標來遍曆這個單向鏈表,第一個指標p1,每次走一步;第二個指標p2,每次走兩步;  當p2 指標追上 p1的時候,就表明鏈表當中有環路了。

關於這個解法最形象的比喻就是在操場當中跑步,速度快的會把速度慢的扣圈

可以證明,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 "iostream.h"
#include "memory.h"
#include "new.h"
class CList {
public:
 int nData;
 CList * pNext;
} * pRoot = NULL;

const int size = sizeof(CList) / sizeof(int);
int  buffer[101*size];
bool Init(int n)
{
    pRoot = (CList*)buffer;
 if ( n<1 && n>98 )  return false;
 CList * pTemp = NULL;
 for ( int i=0; i<101; i++ ) {
    pTemp = new (buffer+i*size) CList();
    pTemp->nData = i;
    pTemp->pNext = (CList *)(buffer + (i+1)*size);
 };
 pTemp->pNext = (CList *) (buffer + n*size);
 return true;
}

void ClearCircle(CList * pRoot)
{
 CList * p1, * p2;
 p1 = p2 = pRoot;
 do {
     p2 = p2->pNext->pNext;
  p1 = p1->pNext;
 } while ( p2!=NULL && p1!=p2);
 if ( p1 == p2 ) {
  p2 = pRoot;
  while (1) {
   p2 = p2->pNext;
   if ( p1->pNext == p2 ) break;
   p1 = p1->pNext;
  }
  p1->pNext = NULL;
 }
}

main()
{
    CList * pList = pRoot;
 if (Init(21) )
 {
  cout << "Before clear:!" << "/r/n";
  pList = pRoot;
  for ( int i=0; i<104; i++)
  {
   cout << pList->nData << "/r/n";
   pList = pList->pNext;
  }
  ClearCircle(pRoot);
 }
 cout << "After clear:" << "/r/n";
 pList = pRoot;
 while (pList) {
  cout << pList->nData << "/r/n";
  pList = pList->pNext;
 }
 return 0;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.