2013-11-25 4 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, - это то, является ли текущий узел последним элементом в списке. если это последний элемент (aka 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 и что если я исправил эту строку, код/​​программа должна работать. Я не могу понять, что такое null/почему оно равно null, чтобы я мог его исправить. Благодарю. – user2766542

+0

В том месте, где вы делаете удаление, может быть неплохо сделать распечатку имени для каждого из prev, curr и curr-> next (if! Null). Может быть удобен для сортировки смешивания указателя. – RichardPlunkett

ответ

1

Для вашего кода я предлагаю несколько вещей. Изолируйте код, чтобы найти узел с именем, которое вы ищете. Метод remove СЛЕДУЕТ удалять только дважды связанный узел при условии, что ему задан один.

Я знаю, что ваш метод 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-> рядом с итерацией). – AFM

+0

Я не знаю, как вы обрабатываете уничтожение узлов, но я предполагаю, что вы удалите два указателя: prev и next. Если это так, вы должны EXPLICITLY установить предыдущий и следующий узел, который вы пытаетесь удалить, в NULL или nullptr. Это связано с тем, что если вы этого не сделаете, вы рискуете удалить не только этот узел, но и узлы, подключенные к нему! – AFM

1

NULL следует заменить nullptr

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

То есть задание, вы хотите:

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

В строке 47 I думаете, что вы говорите: если prev == nullptr, а затем не nullptr, но вы используете

prev->next = curr->next; 

Который не работает с тех пор, как предыдущий является 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

wow, awesome, я понятия не имел, что могу сделать что-то вроде «prev-> next-> prev = prev;» – user2766542

+0

Все дело в том, что вам не нужен tmp вообще. Вам нужно сделать 2 задания, prev должен пропустить ток, а затем, вещь, на которую он указывает сейчас, должен указать на него. – 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; 
    } 
} 
Смежные вопросы