【问题标题】:Deleting a node from linked list in C从C中的链表中删除一个节点
【发布时间】:2011-02-20 08:31:22
【问题描述】:

我的问题是从链表中删除一个节点。

我有两个结构:

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 并执行删除,但是当第一个元素被删除时它会崩溃。请询问更多信息。我可能会用很不整洁的词。

【问题讨论】:

  • 您的第二个代码 sn-p 缩进很尴尬。你能解决这个问题吗?
  • 很抱歉。我会解决的。

标签: c list linked-list


【解决方案1】:

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

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

【讨论】:

  • @LuckySlevin:我明白了,但是您需要在取消引用之前为指针分配一个有效地址。
【解决方案2】:

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

【讨论】:

  • 听起来很有道理,你的意思是我也得为inner_list再做一个删除函数?
  • @LuckySlevin:是的,当您释放结构outer_list 时,您只是删除了指针inner_list * head,而不是指针指向的内存。尽管我认为这不是您现在看到的问题。如果您使用的是 Linux,我建议您使用 Valgrind 来查找内存泄漏。
  • 问题是经过一些测试,删除第一个节点使程序崩溃:S。例如我正在删除“aaa”,如果它是列表的第一个节点,程序就会崩溃。
【解决方案3】:

您正在检查单词的 if 条件是否应该如下:

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

?

【讨论】:

  • 它已经修复了。我想我在复制到这里时犯了一个错误。非常感谢。
【解决方案4】:

试试这个(只适用于外部列表,它不会释放内部列表):

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

【讨论】:

  • 不错。您可以通过将第一个 if 更改为 if( ... != 0) 并在继续下一项后使用 continue 来整理代码 - 整个事情将变得不那么嵌套。
  • 问题是经过一些测试,删除第一个节点使程序崩溃:S。例如我正在删除“aaa”,如果它是列表的第一个节点,程序就会崩溃。
  • 我猜问题是函数没有修改列表的头部。
  • 我的想法和尖牙一样。我想知道测试删除第一个节点多少次?不止一次吗?我认为问题在于您正在使用该方法删除列表中的第一个节点,并且您正在尝试更新“头”,这是一个指针参数。从 delnode 退出时,调用者仍会认为“head”参数(或调用者给它的任何指针)仍指向原始 head(您刚刚释放)。
【解决方案5】:

FIX#1(可选) - 初始化所有变量是一个好习惯。请注意,在这种特定情况下,由于您已经处理了 head 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;
    }
}

【讨论】:

  • 效果很好,除非删除的节点是第一个节点。删除第一个节点会使程序崩溃:S.
  • 我看不出它应该崩溃的任何原因。尝试在“返回”之前放置一个 printf ,看看它是否能达到那么远。顺便说一句,“计数”变量有什么作用?它在本节中被完全忽略,可能在其他地方很重要..
  • 不,我会在最后处理计数。它默认为零。没有任何关联。问题是当我尝试在删除后显示列表时出现错误。也许我调用了错误的函数:S。外部列表 *p; //p 用于附加函数等 //then delnode(p,word);//要搜索的单词 display(p);//显示从 p 开始的列表
  • 我想我会打开另一个关于显示功能的问题。这个问题的标题必须改变。我会发布链接。
【解决方案6】:

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

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

【讨论】:

  • delnode(&mylist,wordtoDelete);它解决了删除头的问题。还有一个问题,我现在将更新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-06
  • 2017-10-21
  • 2013-08-30
  • 2019-05-10
相关资源
最近更新 更多