探究單向鏈表逆置轉向及檢查成環的問題

假設鏈表節點的數據結構爲:

typedef struct node 
{
  int data;
  struct node* next;
}ListNode,*pListNode;

要求實現將一個單向鏈表逆置並檢測如果鏈表成環返回FALSE,從參數返回新的鏈表頭。

BOOL Reverse(pListNode& head);

這個問題看似簡單,實際上太能發揮了。首先因爲是單向鏈表,next不能簡單的改變方向,要記錄下即將被斷開的節點,而即將被斷開的節點它的next也是同樣的問題。再者就是要如何檢測有環。

單看逆置問題,通常的方法應該要用到3個指針:當前的p,下一個q,下一個的下一個head。 記下第三個指針,用第二個指向第一個,然後後移一步重複動作直到q沒有下一個,再封口。

{
  if (head != NULL && head->next != NULL)
  {
    pListNode p = head;
    pListNode q = head->next;
    p->next = NULL;
    while (q->next != NULL)
    {
      head = q->next;
      q->next = p;
      p = q;
      q = head;
    }
    head->next = p;
  }
  return;   //此法未處理成環問題
}

單看檢測成環問題,需要兩個指針,一個向後一次移動一步,一個向後一次移動兩步。假如他們能夠相遇就是成環,他們任意一個走完鏈表都不成環。

{
  if( head==NULL)return;
  pListNode step1 = head;
  pListNode step2 = head;
  while(step1->next)
  {
    step1 = step1->next;
    if(step2->next)step2 = step2->next;
    else return TRUE;  //不成環
    if(step2->next)step2 = step2->next;
    else return TRUE;  //不成環
    if(step1==step2)return FALSE;
  }
  return TRUE; //不成環
}

以上兩種方法都單獨解決了部分問題,能不能同時解決兩個問題呢?
於是我想到了遞歸。且不說它的弊端,單就解決問題而言是可行的。

BOOL Reverse(pListNode& head)  //不能處理成環檢測
{
    pListNode p = head;
    if(p->next)
    {
      head = p->next;
      Reverse(head);
      p->next->next = p;
    }
    else
    {
      return FALSE;
    }
    return FALSE;
}

這個方法的問題是沒法處理成環的問題。 在遞歸的背景下,解決成環的思路就想到如何標記一下處理過的node。於是我想到一個另類的做法。使用一個輔助結構體記錄前後兩個節點,把節點本身的next標爲’1’,如果處理過程中發現next爲1就是成環啦。

struct aid
{
  struct node* left;
  struct node* next;
};
BOOL Reverse(pListNode& head) //同時處理逆置和環檢測
{
    if(!head)return FALSE;
    pListNode p = head;
    if(p->next)
    {
      if(p->next==1)return TRUE;  //成環
      aid *a = new aid;
      a->left = p;
      a->right = p->next;
      head = p->next;
      p->next = 1;
      if(Reverse(head)==TRUE)
      {
        delete a;
        return TRUE;
      }
      a->right->next = a->left;
      a->left->next = 0;
      delete a;
    }
    else
    {
      return FALSE;
    }
    return FALSE;
}

注意,以上代碼都沒有實測!請以思路爲主自行參考嘗試實現。

發佈了24 篇原創文章 · 獲贊 7 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章