C 递归删除单个链接列表中元素的所有出现

C 递归删除单个链接列表中元素的所有出现,c,recursion,linked-list,singly-linked-list,function-definition,C,Recursion,Linked List,Singly Linked List,Function Definition,我正在学习使用C语言的数据结构和算法,但我不知道如何递归地解决这个问题 它有简单的迭代解决方案,但我需要一些递归版本的帮助 这是我的递归版本: void delAllOcc(node** headRef,int key) { node * prev; if (*headRef != NULL && (*headRef)->data == key) { prev = *headRef; *headRef = (*headRef)

我正在学习使用C语言的数据结构和算法,但我不知道如何递归地解决这个问题

它有简单的迭代解决方案,但我需要一些递归版本的帮助

这是我的递归版本:

void delAllOcc(node** headRef,int key) {
    node * prev;
    if (*headRef != NULL && (*headRef)->data == key) {
        prev = *headRef;
        *headRef = (*headRef)->next;
        free(prev);
    }
    else {
        if (*headRef != NULL) {
            delAllOcc(&(*headRef)->next,key);
        }
    }
}

删除节点时,函数不会调用自身

看看这个代码片段

if (*headRef != NULL && (*headRef)->data == key) {
    prev = *headRef;
    *headRef = (*headRef)->next;
    free(prev);
}
函数本身没有递归调用

该函数可以按以下方式显示

void delAllOcc( node **headRef, int key ) 
{
    if ( *headRef != NULL )
    {
        if ( ( *headRef )->data == key )
        {
            node *tmp = *headRef;
            *headRef = ( *headRef )->next;
            free( tmp );
        }
        else
        {
            headRef = &( *headRef )->next;
        }

        delAllOcc( headRef, key );
    }
}
要获得迭代解决方案,只需将if语句替换为while语句,并删除递归调用

void delAllOcc( node **headRef, int key ) 
{
    while( *headRef != NULL )
    {
        if ( ( *headRef )->data == key )
        {
            node *tmp = *headRef;
            *headRef = ( *headRef )->next;
            free( tmp );
        }
        else
        {
            headRef = &( *headRef )->next;
        }
    }
}
遗憾的是,最干净的递归解决方案不使用尾部递归:




注意:我用普通指针替换了指针到指针的参数,并将返回类型更改为指针。否则,递归就没有什么意义。

请注意,对于这个问题,递归是一个非常糟糕的主意,因为它效率较低,而且很长的列表可能会出现堆栈溢出。代码是递归的,而不是迭代的-您声明它是您的迭代版本。碰巧你诚实地尝试递归解决方案对任何回答的人都更有用,你的工作迭代解决方案就没有什么意义了。递归是计算机科学课程所钟爱的一个“巧妙的技巧”——在现实世界中,最好避免递归,因为真实的计算机有有限的堆栈。在这种情况下,列表长度很容易超过最大调用堆栈深度。学习它,通过你的课程,然后知道谨慎使用,当然不是在像这样没有约束的情况下。是的,我应该提到这是我的递归尝试,我写错了,我的错。谢谢你的解释真的很感谢。谢谢你的解决方案。以上是我的递归版本,而不是迭代版本。对不起,我写错了。谢谢,你的解决方案真的很有帮助。我应该提到它是递归的,而不是迭代的。@wildplasser对于初学者来说,这句话“我用普通指针替换了指针到指针的参数,并将返回类型更改为指针。否则,递归就没有什么意义了。”没有意义。其次,您的代码有一个bug。@RoyLy:它是递归的。这里没有循环。你的是递归的,我的也是,但是在我的代码上面我说这是一个迭代版本,这是错误的@wildplasser
#include <stdlib.h>

struct node {
        struct node *next;
        int key;
        };

struct node *del_recursive (struct node *ptr, int key)
{
if (!ptr) return ptr;

ptr->next = del_recursive(ptr->next, key);
if (ptr->key == key) {
        struct node *del = ptr;
        ptr=ptr->next;
        free(del);
        }
return ptr;
}
struct node *del_recursive_tail (struct node *ptr, int key)
{
if (!ptr) return ptr;

if (ptr->key == key) {
        struct node *del = ptr;
        ptr=ptr->next;
        free(del);
        }
if (!ptr) return ptr;
ptr->next = del_recursive_tail(ptr->next, key);
return ptr;
}