2014-10-28 63 views
0

這個函數應該從鏈表中移除元素。然而,目前它完成了這項工作,通過進一步的測試,我發現在使用該功能約2-3次後出現分段錯誤。例如,可以說listA包含1 2 3 4 4 5,當我做remove listA 4然後打印listA的元素時,輸出應該是1 2 3 5,它是。但是,當我在列表中多次使用1-2次刪除功能時,它會停止工作,並且不斷收到分段錯誤。我不知道爲什麼..任何幫助將不勝感激!函數不能多次工作?

void mylist::remove(int z) 
      {  
       Node *currP, *prevP; 

       prevP = NULL; 
       for (currP = head; 
        currP != NULL; 
        prevP = currP, currP = currP->next) { 

       if (currP->key == z) { 
        if (prevP == NULL) { 
        head = currP->next; 
        } else{ 
        prevP->next = currP->next; 
        } 
        delete currP; 
        currP=prevP; 
        numberofnodes--; 
       } 
       } 
       return; 
     } 
+0

你已經接近精確了,但是:*「當我在列表中多次使用1-2次刪除功能時,它會停止工作」*放下了球。看看[「最小,完整,可驗證示例」](http://stackoverflow.com/help/mcve)。顯示您的確切輸入,以及編譯任何人都可以複製的程序 - 粘貼到編譯器(「完成」)並且可以重複(「可驗證地」)給出錯誤的輸出。測試基本案例,例如從包含1的列表中刪除「1」。您可能在過程中發現自己的問題... – HostileFork 2014-10-28 06:39:24

+0

只需修改for循環中的update語句,僅當它不是NULL時才從currP訪問下一個元素。 – 2014-10-28 07:20:41

回答

2

由於prevP將爲空,因此您不處理第一個節點表單列表被刪除的情況。刪除currP後,您正在分配currP=prevP;。在下一次迭代中,當prevP = currP, currP = currP->next將被執行用於下一個循環迭代時,它將導致分段錯誤。在轉移到下一個迭代的for循環是不正確

void mylist::remove(int z) 
     {  
      Node *currP, *prevP, *temp; 

      prevP = NULL; 
      currP = head; 
      while(currP != NULL){ 

      if (currP->key == z) { 
       if (prevP == NULL) { 
       head = currP->next; 
       } else{ 
       prevP->next = currP->next; 
       } 
       temp = currP; 
       currP = currP->next; 
       delete temp; 
       numberofnodes--; 
      } 
      else 
      { 
       prevP = currP; 
       currP = currP->next; 
      } 
      } 
      return; 
    } 
0

delete currP; currP = prevP;

這是導致分段錯誤,在第一次迭代prevP爲空,所以如果在迭代prevP不是空的情況下執行。

+0

好吧,有道理。我將如何改變我的代碼來做到這一點?不確定。 – sam696969 2014-10-28 06:44:34

+0

prevPcurrentP; 刪除currP; – 2014-10-28 06:57:24

1

請考慮當您刪除列表中的第一個條目時會發生的情況:您設置了head = currP->next但您將prevP保留爲NULL。當代碼變爲currP=prevP時,currP變爲NULL,然後在迭代中嘗試訪問currP->next時會出現錯誤。你需要重新組織你的循環來避免這種情況。

1

您的指針管理:

您可以使用while循環來代替,等等。當currP在刪除第一個項目時設置爲NULL時,您將在for循環的迭代增量步驟中取消引用NULL。

老實說,for循環首先並不是這個算法最熱門的主意,但是如果你真的想用最小的努力做到這一點,指針指針解決方案可以簡化這項任務:

void mylist::remove(int z) 
{ 
    Node **pp = &head; 
    while (*pp) 
    { 
     if ((*pp)->key != z) 
     { 
      pp = &(*pp)->next; 
     } 
     else 
     { 
      Node *victim = *pp; 
      *pp = victim->next; 
      delete victim; 
      --numberofnodes; 
     } 
    } 
} 

如何使用

指針到指針pp持有指針我們感興趣的檢查匹配的地址。這最初保存着head指針的地址。

Node **pp = &head; 

每一次非比賽我們移動到當前節點的next指針的地址:

if ((*pp)->key != z) 
{ 
    pp = &(*pp)->next; 
} 

但是,當我們發現一個匹配的指針值誰的地址在pp舉行保存到臨時:

Node *victim = *pp; 

然後指針(其可以是head指針,如果這是列表中的第一項),更新爲指向節點的next指針值。

*pp = victim->next; 

最後,丟棄現在未鏈接的節點。

delete victim; 

注:

NO運動next當我們放棄比賽。我們已經通過加載*pp,並在刪除之前將其指針值保存在其自己的next指針中移動到那裏。此外,它是(很顯然)關鍵head指針爲空,如果列表爲空,最後一個節點next指針是NULL終止列表。標準鏈表的東西,我知道,但它很重要,因此提到。

祝你好運。

1

考慮在列表中刪除1。 prevP = NULL; 然後你刪除currP並用prevP分配它,巫婆是NULL。 此循環結束。 然後它轉到以下部分:prevP = currP,currP = currP-> next; 後一種情況下的問題,因爲currP是NULL。您正在訪問NULL-> next。