2010-05-17 3 views
3

Моя проблема заключается в удалении узла из связанного списка.Удаление узла из связанного списка в C

У меня есть два: Структуры

typedef struct inner_list 
{ 
int count; 
char word[100]; 
inner_list*next; 
} inner_list; 
typedef struct outer_list 
{ 
char word [100]; 
inner_list * head; 
int count; 
outer_list * next; 
} outer_list; 

Моя проблема заключается в удалении узла из outer_list связанного списка. Например, когда пользователь entered aaa удаляет, delete function should find the node with outer_list->word = aaa and delete this node and reconnect the list again. Я попробовал приведенный ниже код, чтобы сделать это. но после обнаружения и удаления я теряю список. Я не знаю, что случилось. Обратите внимание, что внешний_list также имеет связанный список inner_list внутри.

void delnode(outer_list **head,char num[100])//thanks to both Nir Levy and Jeremy P. 
{ 
    outer_list *temp, *m; 
    m=temp=*head; /*FIX #1*/ 
    while(temp!=NULL) { 
     if(strcmp(temp->word,num)==0) { 
      if(temp==*head) { 
       delinner(temp->head); /* FIX#2 */ 
    *head=temp->next; 

       free(temp); 
       return; 
      } else { 
       delinner(temp->head); /* FIX#2 */ 
    m->next=temp->next; 

       free(temp); 
       return; 
      } 
     } else { 
      m=temp; 
      temp= temp->next; 
     } 
    } 
    printf(" ELEMENT %s NOT FOUND ", num); 
} 
void delinner(inner_list *head) { /* FIX#2 */ 
    inner_list *temp; 
    temp=head; 
    while(temp!=NULL) { 
     head=temp->next; 
     free(temp); 
     temp=head; 
    } 
} 

Теперь моя проблема обновлена. При удалении элемента из внутреннего списка я также пытаюсь удалить один и тот же элемент из inner_list.

Например: aaa - это элемент связанного списка outer_list, и давайте укажем его с помощью external_list * p - Этот aaa также может быть связан также со списком, связанным с inner_list. (он может быть в p-> голове или другом внутреннем списке.) Теперь сложная часть снова. Я попытался применить те же правила с удалением внешнего_имени, но всякий раз, когда я удаляю элемент head_list, он дает ошибку. Вот что я пробовал:

void delnode2(outer_list *up,inner_list **head,char num[100]) 
{ 
    inner_list *temp2,*temp, *m; 
outer_list *p; 
p = up; 

while(p!=NULL){m=temp=temp2=p->head; 
    while(temp!=NULL) { 
     if(strcmp(temp->word,num)==0) { 
      if(temp==(*head)) { 
       *head=temp->next; 

       free(temp); 
       return; 
      } else { 
       m->next=temp->next; 

       free(temp); 
       return; 
      } 
     } else { 
      m=temp; 
      temp= temp->next; 
     } 
    } 
p=p->next; 
} 
    printf(" ELEMENT %s NOT FOUND ", num); 
} 

Здесь я пытаюсь отправить узел и проверить все inner_lists из outer_list элементов и выполнить удаление, однако, когда первый элемент удаляется он выходит из строя. Пожалуйста, запросите дополнительную информацию. Я мог бы использовать очень неопрятные слова.

+2

Вашей второй фрагмент кода неловко отступа. Вы можете это исправить? – Lucas

+0

Извините. Я починю это. – LuckySlevin

ответ

2

FIX # 1 (опционально) - это хорошая практика, чтобы инициализировать все переменные. обратите внимание, что в этом конкретном случае, так как вы управляете головным secanrio, тогда у вас не должно возникнуть проблемы, потому что m устанавливается на temp позже, но все же ..

FIX # 2 - убедитесь, что вы полностью удалили внутренний список до вы освобождаете узел.

Вот код (непроверенные, извините)

void delnode(outer_list *head,char num[100]) 
{ 
    outer_list *temp, *m; 
    m=temp=head; /*FIX #1*/ 
    while(temp!=NULL) { 
     if(strcmp(temp->word,num)==0) { 
      if(temp==head) { 
       head=temp->next; 
       delinner(temp->inner_list); /* FIX#2 */ 
       free(temp); 
       return; 
      } else { 
       m->next=temp->next; 
       delinner(temp->inner_list); /* FIX#2 */ 
       free(temp); 
       return; 
      } 
     } else { 
      m=temp; 
      temp= temp->next; 
     } 
    } 
    printf(" ELEMENT %s NOT FOUND ", num); 
} 
void delinner(inner_list *head) { /* FIX#2 */ 
    inner_list *temp; 
    temp=head; 
    while(temp!=NULL) { 
     head=temp->next; 
     free(temp); 
     temp=head; 
    } 
} 
+0

Это работает отлично, если только удаленный узел не является первым узлом. Удаление первого узла приведет к сбою программы: S. – LuckySlevin

+0

Я не могу понять, почему он должен упасть. Попытайтесь поставить printf перед «возвратом» и посмотреть, доходит ли он до этого. Кстати, что делает переменная «count»? он полностью игнорируется в этом разделе и может быть важным где-то еще. –

+0

Нет, я буду иметь дело со счетом в конце. он по умолчанию был равен нулю. С ним ничего не связано. Проблема в том, что когда я пытаюсь отобразить список после удаления, он дает ошибку. Возможно, я вызываю функцию неправильно: S. external_list * p; // p используется для добавления функции и т. Д. // затем delnode (p, word); // слово для поиска display (p); // отображение начала списка с p – LuckySlevin

0

m Указатель не установлен на какой-либо действительный адрес, прежде чем вы разыщите его, и ваша программа перейдет в неопределенное поведение.

Для того, чтобы исправить вашу реализацию, используйте два указателя - один на текущий элемент, а другой - на предыдущий, и обновите их оба при перемещении списка. Вам придется рассматривать случаи с нулевыми и одноэлементами как особые - будьте осторожны.

+0

Я думал, что это временный указатель. – LuckySlevin

+0

@LuckySlevin: Я вижу, но перед разыменованием вам нужно назначить действительный адрес указателю. – sharptooth

0

Я не думаю, что вы освобождаете inner_list. Вы получите утечку памяти.

+0

, который звучит разумно. Вы имеете в виду, что я должен сделать еще одну функцию удаления для inner_list тоже? – LuckySlevin

+0

@LuckySlevin: Да, вы удаляете указатель 'inner_list * head', когда вы освобождаете struct' external_list', но не память, на которую указывает указатель. Хотя я не думаю, что это проблема, которую вы сейчас видите. Если вы работаете в Linux, я рекомендую использовать Valgrind для обнаружения утечек памяти. – Lucas

+0

Проблема после некоторых тестов, удаление первого узла приводит к сбою программы: S. например, я удаляю «aaa», и если его первый узел списка, программа сработает. – LuckySlevin

0

Ваш, если условие, которое проверяет на слово, это не должно быть следующее:

if(strcmp(temp->word, num)==0) 

?

+0

было уже исправлено. Наверное, я ошибся, копируя его здесь. Спасибо, жестко. – LuckySlevin

0

попробовать это (только для внешнего списка, он не выпустит внутренний один):

void delnode(outer_list *head,char num[100]) 
{ 
    outer_list *temp, *m. *helper; 
    temp=head; 
    while(temp!=NULL) 
    { 
     if(strcmp(temp->word,num)==0) 
     { 
      if(temp==head) 
      { 
       head=temp->next; 
       free(temp); 
       return; 
      } 
      else 
      { 
       m = temp; 
       temp = temp->next; 
       helper->next = temp; //link the previous item 
       free(m); 
       return; 
      } 
     } 
     else 
     { 
      helper = temp; 
      temp= temp->next; 
     } 

    } 
    printf(" ELEMENT %s NOT FOUND ", num); 
} 
+0

Nice. Вы можете убрать код, изменив первый 'if' на' if (...! = 0) 'и используя' continue' после перехода к следующему элементу - все это станет менее вложенным. – sharptooth

+0

Проблема после некоторых тестов, удаление первого узла приводит к сбою программы: S. например, я удаляю «aaa», и если его первый узел списка, программа сработает. – LuckySlevin

+0

Я думаю, проблема в том, что функция не изменяет голову списка. – sharptooth

1

Там большая проблема в том, что если вы в конечном итоге нужно удалить первый элемент внешнего списка, вы никогда не проходят назад новый глава список.Ваш origuinal кода нуждается в изменении следующим образом (также положить во всех других хороших предложениях):

void delnode(outer_list **tbd,char num[100]) // pass a pointer to tbd 
{ 
    outer_list *temp, *m; 
    temp = *tbd; 
    while(temp!=NULL) 
    { 
     if(strcmp(temp->word,num)==0) 
     { 
      if(temp==*tbd) 
      { 
       // Delete the inner list here 
       *tbd=temp->next; 
       free(temp); 
       return; 
      } 
    // rest of function 

Вы назвали бы это так:

outer_list* myList; 

// lots of code including initialising and adding stuff to the list 

delnode(&mylist, wordtoDelete); // note the '&' sign 
+0

отличный ответ с delnode (& mylist, wordtoDelete); он решил проблему для удаления головы. Там остается одна проблема, теперь я обновляю вопрос. – LuckySlevin

+0

Вопрос обновлен. – LuckySlevin

Смежные вопросы