为什么我的删除节点功能不起作用?

时间:2013-05-24 07:28:52

标签: c++ recursion linked-list

我已经检查过电路板,但却找不到任何帮助。我发现给定基本和一般情况下的递归函数很容易,但这不像我这样做。我应该迭代一个列表,直到我到达链表的尾部。如果下一个节点为NULL,那么我必须将值存储在最后一个节点,删除该节点,然后返回该值。所以它类似于一个dequeue方法,除了它是递归执行的。我究竟做错了什么?

int LinkedList::removeTailRec(Node *n)
{
    // check for the base case(s)
    if(n->next == NULL)
    {
        Node *tmp = new Node();
        tmp = n;
        int val = n->value;
        tmp = NULL;
        return val;
    }
    else
        return removeTailRec(n->next);

    // else call the recursive method
}

4 个答案:

答案 0 :(得分:5)

首先,我建议您使用nullptr而不是NULL。

然后,在您的代码上。你实际上并没有从列表中删除任何内容。

if(n->next == NULL)
{
    Node *tmp = new Node();
                ^^^^^^^^^^
    //Useless, and dangerous. This memory is never free'd

    tmp = n;
    int val = n->value;
    tmp = NULL;
    ^^^^^^^^^^
    //You just set a local variable to NULL, you're not deleting anything

    return val;
}

如果要删除节点,则必须保留对前一节点的引用(例如,具有双向链表,即具有指向下一个元素的指针 a指向每个节点中前一个元素的指针,或直接在前一个节点上工作。

将此前一个节点的next设置为nullptr,存储节点的值,然后删除Node指针。

执行此操作的一种方法是使用指向下一个节点的指针:

int LinkedList::removeTailRec(Node *n)
{
    //EDIT: Adding a check for n validity
    if(!n){
        //Here, you should have a way of detecting 
        //a call to your method with a null pointer
        return 0;
    }

    Node* nextNode = n->next;
    // check for the base case(s)
    if(nextNode->next == nullptr)
    {
        //Get the next node value
        int val = nextNode->value;

        //Set the current node next member to nullptr
        n->next = nullptr;

        //Free the last node
        delete nextNode;

        return val;
    }
    else{
        return removeTailRec(n->next);
    }

    // else call the recursive method
}

答案 1 :(得分:1)

您正在存储结果,但不会从链接列表中删除它。您可以在另一个变量(指针:结果)中返回结果。

Node* getTail(Node *n,int *result){
    //u can even free the memory
    if(!n->next)
    {
       result=n->value;
       return NULL;
    }
    n->next=getTail(n->next,result);
}

或者你可以采取其他方式

int getTail(Node *n)
{
    if(!n) return 0;
    if(n->next)
    {
        if(!n->next->next)
        {
            Node *frnode=n->next;
            int result=n->next->value;
            n->next=NULL;
            delete frnode;
            return result;
        }
     getTail(n->next);
}

答案 2 :(得分:1)

您没有删除代码中的最后一个节点,而是泄漏了另一个(临时)节点。 要删除最后一个节点,必须将上一节点中的链接归零。 您的代码应该是

...
if (n == NULL || n->next == NULL)
    throw std::out_of_range("node");
if(n->next->next == NULL)
{
    int val = n->next->value;
    delete n->next;
    n->next = NULL;
    return val;
}
else ...

请注意c ++不是函数式语言并且没有尾递归的优化这一事实,所以在实际应用中,随着列表变得越来越大,你最终会出现堆栈溢出失败=)使用Haskell或Erlang来实现这一点编程风格,在c ++中使用forwhile

答案 3 :(得分:0)

当n是尾节点时,您应该将Node n的上一个Node的下一个字段设置为NULL。