2013-11-25 175 views
1

我已經看過這個話題的其他線程,但沒有能夠使用它們來解決我的問題。從雙向鏈表中刪除一個節點


這是在鏈接列表中的節點的主類定義:

class node { 

public: 

    // default constructor 
    node() {name = ""; prev = NULL; next = NULL;}; 

    // default overloaded 
    node(string s) {name = s; prev = NULL; next = NULL;}; 

    // item in the list 
    string name; 

    // links to prev and next node in the list 
    node * next, * prev; 

}; 

以上是節點類的定義,這是在其產生鏈表另一類使用。鏈表代碼給了我們,我們必須修改,所以我知道它的工作原理。我已經完成並測試了雙向鏈表中新增節點的工作,現在我正在從這個雙向鏈表中刪除節點。

功能刪除一個節點:http://pastebin.com/HAbNRM5W

^這是我需要幫助的代碼中,有太多的重複鍵入


我被我的老師告訴記者,該代碼,問題是行56,它讀取:

tmp->prev = prev; 

我想設置鏈接到前一個節點是正確的。我嘗試使用類似的if/else循環的情況是當前節點是否是列表中的最後一項。如果它是最後一項(又名curr->next = NULL),則不要使用curr->next設置鏈接並停止循環迭代。

任何幫助/想法/建議/反饋將不勝感激!

void linkedList::remove(string s) 
{ 
     bool found = false; 
     node * curr = getTop(), * prev = NULL; 
     node * tmp = new node(); 
     while(curr != NULL) 
     { 
       // match found, delete 
       if(curr->name == s) 
       { 
         found = true; 
         // found at top 
         if(prev == NULL) 
         { 
          node * temp = getTop(); 
          setTop(curr->next); 
          getTop()->prev = NULL; 
          delete(temp); 
         } // end if 
         else 
         { 
          // determine if last item in the list 
          if (curr->next = NULL) 
          { 
           // prev node points to next node 
           prev->next = curr->next; 
           // delete the current node 
           delete(curr); 
          } // end if 
          // if not last item in list, proceed as normal 
          else 
          { 
           // prev node points to next node 
           prev->next = curr->next; 
           // set the next node to its own name 
           tmp = prev->next; 
           // set prev-link of next node to the previous node (aka node before deleted) 
           tmp->prev = prev; 
           // delete the current node 
           delete(curr); 
          } // end else 
         } // end else 
        } // end if 

       // not found, advance pointers 
       if(!found) 
       { 
        prev = curr; 
        curr = curr->next; 
       } // end if 

       // found, exit loop 
       else curr = NULL; 
     } // end while 

     if(found) 
      cout << "Deleted " << s << endl; 
     else 
      cout << s << " Not Found "<< endl; 
} // end remove 
+0

你問的問題到底是什麼? –

+0

zac,我需要此方法來刪除C++中的雙向鏈表的節點。我的講師告訴我「tmp-> prev = prev;」是NULL,如果我修復這一行,代碼/程序應該工作。我無法弄清楚什麼是空/爲什麼它是空的,以便我可以修復它。謝謝。 – user2766542

+0

在你正在進行刪除的地方,對prev,curr和curr-> next(if!null)中的每一個執行打印命名可能是一個好主意。 可以方便地分揀指針混淆。 – RichardPlunkett

回答

1

對於你的代碼,我建議幾件事。隔離代碼以查找具有您正在查找的名稱的節點。刪除方法應該只刪除一個雙向鏈接的節點,只要它給出一個。

我知道你的remove方法需要一個字符串參數,但將它傳遞給另一個函數,並讓該函數返回你正在尋找的節點。

它應該是這個樣子:

Node *cur = find("abcd"); 
Node *prev = cur->prev; 
prev->next = cur->next; 

Node *n = cur->next; 
n->next = cur->prev; 

cur->next = NULL; //or nullptr 
cur->prev = NULL; //or nullptr 

delete cur; 
+0

感謝您的建議和反饋!我同意你關於你的建議,即重寫方法/功能,但大綱/整個程序是由教授作爲單獨鏈接給我們的,我們必須將它轉換爲雙重鏈接。通常,如果我自己在做這件事,我會以另一種方式做到這一點,但在這一點上,它會比我/我有時間去做更多的工作。 – user2766542

+0

@ user2766542 - 難道你只是添加一個私人功能?我不認爲任何教授會禁止額外的私人會員。 對於您的查找函數,您應該使用for循環來自動執行搜索(使用ptr = ptr-> next迭代)。 – AFM

+0

我不知道你如何處理節點的破壞,但我假設你刪除了兩個指針:prev和next。如果是這種情況,您必須明確地將您要刪除的節點的prev和next設置爲NULL或nullptr。 這是因爲如果您不這樣做,您將冒險刪除不僅該節點,而且刪除連接到它的節點! – AFM

1

NULLnullptr

if (curr->next = NULL) { ... 

這是一個任務所取代,你想:

if (curr->next == nullptr) { ... 

在線47我想你說:如果prev == nullptr和next是不nullptr,但你使用

prev->next = curr->next; 

哪一個不行,因爲prev是nullptr。

+0

非常感謝你,我將盡快研究這件事。我不知道如何改變實現,以便prev實際上是前一個節點而不是nullptr。我將立即進行nullptr更改。 – user2766542

+0

我試着將NULL改爲nullptr,但是我的代碼不能編譯。 iostream庫提供對NULL的支持,我不知道關於nullptr。 – user2766542

+0

至於你的第一個答覆的最後部分:我想說,有三個節點:前一個節點,當前節點和下一個節點。如果下一個節點(curr-> next)不是nullptr,則將前一個節點指向該節點(prev-> next = curr-> next)並刪除當前節點。我不知道以前定義爲null/nullptr。我想這是我需要解決的問題。 – user2766542

0

應該像這樣:

prev->next = curr->next; 
prev->next->prev = prev; 
delete (curr); 
+0

哇,真棒,我不知道我可以做一些像「prev-> next-> prev = prev;」 – user2766542

+0

事情是,你根本不需要tmp。 你需要做2個任務,prev需要跳過curr,然後,它現在指出的東西,需要指向它。 – RichardPlunkett

+0

可選地,這第二個可以在if語句中,該檢查prev-> next現在是null_ptr,並且這將減少對上面完全分離的列表結尾的需要。 – RichardPlunkett

0

我在所有不同的條件語句迷路了。所有你需要做的是:

void linkedList::remove(const std::string& s) 
{ 
    node* current = getTop(); // get head node 
    while (current != nullptr) // find the item you are trying to remove 
    { 
     if (current->name == s) 
     { 
      break; // when you find it, break out of the loop 
     } 
    } 

    if (current != nullptr) // if found, this will be non-null 
    { 
     if (current->prev) // if this is not the head node 
     { 
      current->prev->next = current->next; 
     } 
     else 
     { 
      // update head node 
     } 

     if (current->next) // if this is not the tail node 
     { 
      current->next->prev = current->prev; 
     } 
     else 
     { 
      // update tail node 
     } 

     // at this point, current is completely disconnected from the list 
     delete current; 
    } 
}