从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 。 我尝试了下面的代码来做到这一点。 但在找到并删除后,我正在丢失列表。 我不知道出了什么问题。 请注意,outer_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链表的一个元素,让我们用outer_list * p指出它 – 这个aaa也可以在inner_list链表中。 (它可以在p-> head或另一个内部列表中。)现在,又是棘手的部分。 我尝试使用outer_list删除应用相同的规则,但每当我删除inner_list的head元素时,它都会给出错误。 这是我尝试过的:

 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); } 

这里我试图发送节点并检查outer_list元素的所有inner_lists并执行删除但是当第一个元素被删除时它会崩溃。 请询问进一步的信息。 我可能会用非常不整洁的词。

FIX#1(可选) – 初始化所有变量是一个好习惯。 请注意,在这个特定的情况下,因为你已经处理了头部secanrio然后你应该没有问题因为稍后设置为临时,但仍然..

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; } } 

有一个很大的问题,如果你最终需要删除外部列表的第一个元素,你永远不会传回列表的新头。 您的原始代码需要更改如下(还包括所有其他好的建议):

 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 

在取消引用它之前, m指针未设置为任何有效地址,并且程序运行未定义的行为。

为了修复你的实现,使用两个指针 – 一个指向当前元素,另一个指向前一个指针,并在遍历列表时更新它们。 你必须将零和一元的案件视为特殊情况 – 小心。

我认为你没有释放你的inner_list 。 你会得到内存泄漏。

您检查单词的if条件不应该是以下内容:

 if(strcmp(temp->word, num)==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); }