【问题标题】:Delete a node with multiple fields in a single Linked List recursively in C在C中递归删除单个链接列表中具有多个字段的节点
【发布时间】:2020-07-10 02:07:51
【问题描述】:

我正在尝试删除年龄小于给定限制的所有用户节点。问题是这个函数的实现不正确。该算法必须是递归的。

输入示例:

詹妮弗 11 约翰 19 莎拉 17 马克 24

输出示例:

(空) 11 约翰 19 17 马克 24

代码如下:

struct list *delete_node(struct list *l, int limit) {
    if (l != NULL) {
        if (l->age < limit) {
            struct list *tmp;
            tmp = l->next;
            free(l);
        }
        if (l->next != NULL)
            l->next = delete_node(l->next, limit);
        else
            return l;
    }
}

【问题讨论】:

  • 为什么一定要递归?我宁愿把它写成一个循环遍历列表的所有元素,删除那些符合条件的元素。
  • @G.Sliepen 因为这是作业
  • @G.Sliepen 我希望它也可以迭代编写哈哈哈
  • 你设置了tmp = l-&gt;next,但是你再也不会对tmp做任何事情了。此外,return list 不会编译,您可能是指return l。还要考虑这应该在else 分支还是其他地方。
  • @G.Sliepen 对不起,我忘了编辑返回列表(这是一个错字),在我的标准 delete_node 算法中,我在释放 l 后有一个返回 tmp,但现在我不能使用它,因为如果我return tmp 它将(成功)删除匹配的第一个用户。我需要全部删除它们,所以我认为删除 return tmp 是个好主意,但事实并非如此。

标签: c recursion linked-list singly-linked-list function-definition


【解决方案1】:

好像代码少了一行,注释中注明:

    if (l->age < limit){
        struct list* tmp;
        tmp = l->next;
        free(l);
        l = tmp;                   // fix
    }

正如“chqrlie for yellow blockquotes”所回答的那样,还有其他问题,他已经在他的回答中解决了这些问题。您评论说它已解决,但我不知道您的固定代码是否处理所有情况(第一个节点、最后一个节点、相邻节点......)。您可以使用已解决的完整代码更新您的问题。

【讨论】:

  • 解决了!非常感谢!
  • 不,没有解决!该函数在递归调用后不返回任何内容。这是未定义的行为。
  • @rcgldr:恐怕你的版本没有删除连续匹配的节点。
  • @chqrlieforyellowblockquotes - 在对所有情况进行类似排列的测试之前,我复制/粘贴了错误的版本。我最终得到了与您基本相同的代码,只是我没有在 else 上使用大括号。我更新了我的答案以参考您的答案。你得到了我的支持。我们仍然不知道 OP 最终做了什么。之前有评论(现在已删除),我计划一次解决一个问题,等待与 OP 交互。
【解决方案2】:

你的函数有多个问题:

  • 如果lNULL 或者l-&gt;nextNULL,则不会返回任何内容。
  • l 删除节点后无效。您应该在free(l); 之后返回delete_node(tmp, limit)。要拥有单个 return 语句,您可以将 l 设置为此值。

这是修改后的版本:

struct list *delete_node(struct list *l, int limit) {
    if (l != NULL) {
        if (l->age < limit) {
            struct list *tmp;
            tmp = l->next;
            free(l);
            l = delete_node(tmp, limit);
        } else {
            l->next = delete_mode(l->next, limit);
        }
    }
    return l;
}

【讨论】:

    【解决方案3】:

    该函数具有未定义的行为,因为在 l-&gt;next 不等于 NULL 的情况下它不返回任何内容。

    //...
    if (l->next != NULL)
        l->next = delete_node (l->next, limit);
    else
        return l;
    }
    

    也在这段代码中sn-p

    if (l->age < limit){
        struct list* tmp;
        tmp = l->next;
        free(l);
    }
    

    删除指向的内存后,指针l的值无效。

    该功能可以通过以下方式实现

    struct list * delete_node( struct list *l, int limit )
    {
        if ( l != NULL )
        {
            if ( l->age < limit )
            {
                struct list *tmp = l;
                l = l->next;
                free( tmp );
                l = delete_node( l, limit );
            }
            else
            {
                l->next = delete_node( l->next, limit );
            }
        }
    
        return l;
    }
    

    这是一个演示程序。显示列表的函数也写成递归函数。

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    struct list
    {
        int age;
        struct list *next;
    };
    
    struct list * delete_node( struct list *l, int limit )
    {
        if ( l != NULL )
        {
            if ( l->age < limit )
            {
                struct list *tmp = l;
                l = l->next;
                free( tmp );
                l = delete_node( l, limit );
            }
            else
            {
                l->next = delete_node( l->next, limit );
            }
        }
    
        return l;
    }
    
    void display( struct list *l )
    {
        if ( l == NULL )
        {
            puts( "null" );
        }
        else
        {
            printf( "%d -> ", l->age );
            display( l->next );
        }
    }
    
    int push_front( struct list **l, int age )
    {
        struct list *current = malloc( sizeof( struct list ) );
        int success = current != NULL;
    
        if ( success )
        {
            current->age = age;
            current->next = *l;
            *l = current;
        }
    
        return success;
    }
    
    int main(void) 
    {
        enum { Lower = 7, Upper = 20 };
    
        struct list *head = NULL;
    
        srand( ( unsigned int )time( NULL ) );
    
        for ( int i = Lower; i < Upper; ++i )
        {
            int age = rand() % ( Upper - Lower + 1 ) + Lower;
            push_front( &head, age );
        }
    
        display( head );
    
        head = delete_node( head, ( Upper + Lower ) / 2 );
    
        display( head );
    
        head = delete_node( head, Upper + 1 );
    
        display( head );
    
        return 0;
    }
    

    程序输出可能看起来像

    14 -> 11 -> 8 -> 15 -> 8 -> 13 -> 16 -> 18 -> 11 -> 8 -> 18 -> 13 -> 12 -> null
    14 -> 15 -> 13 -> 16 -> 18 -> 18 -> 13 -> null
    null
    

    【讨论】:

    • @chqrlieforyellowblockquotes 我正在准备一个演示程序以确保函数定义正确。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多