使用递归函数删除链表

delete linked list using recursive function?

本文关键字:链表 删除 递归函数      更新时间:2023-10-16
struct Node {
    int value;
    Node* next;
    ~Node() {
        delete next;
    }
};
Node* deleteList(Node* p) {
    if(p == nullptr) return nullptr;
    Node* pNext = p->next;
    delete p;
    return deleteList(pNext);
}

编译器说了一些关于访问错误的事情。我尝试设置断点来调试它。如果链表是 [3, 2, 1],它首先删除 3,然后删除 2 和 1,然后跳回到 2,然后遇到异常。有人可以告诉我问题出在哪里吗?

节点结构的析构函数已经在"next"上调用了 delete。因此,它转到"next"并调用其析构函数,依此类推。然后,链表中跟随p的所有节点都将通过调用delete p;删除(其中 p 是节点*(。

我建议你去掉节点的析构函数,以防止这种链破坏发生。

struct Node {
    int value;
    Node* next;
};

作为旁注,虽然我不知道你的代码的其余部分,但我看不出为什么 deleteList(Node* p( 应该返回一个 Node*(因为它将始终是 nullptr,没有返回有趣的结果(。

void deleteList(Node* p)
{
    if(p == nullptr) return;
    Node* pNext = p->next;
    delete p;
    deleteList(pNext);
}

如果链表是: [3, 2, 1] ,当您调用 deleteList 时,会发生以下情况:

  1. p = 3 pNext = 23delete p; 删除 然后调用析构函数,因此delete next将删除2并以递归方式1

  2. 然后在deleteList函数中delete p后,再次调用deleteList(pNext),所以这次:p = 2pNext = 1,由于2在上一步中已经被删除,因此当您再次调用delete p时它会损坏。

因此,请删除~Node()中的delete next;

实际上,我不明白为什么要使用deleteList,因为它总是会返回nullptr并删除所有节点。那么为什么不删除deleteList功能,并将delete next;保持在~Node()中。您可以直接删除已创建的Node对象。

当然,完成此任务的最佳方法是: std::list .

我敢打赌,您正在delete已被删除的实例上多次调用。当你调用delete p; 时,p 的析构函数将被调用,并且它正在删除列表中的下一个节点。然后递归调用deleteList,将刚刚被p的析构函数删除的节点传递给它,使你持有的指针无效。

您需要做的是确定Node是否拥有列表中它后面的Node(即,它是否负责清理它(,或者是否会由一些外部代码来处理这个问题。你不能两者兼而有之。


编辑:

顺便说一句,你真正想要的不是递归删除函数,而是deleteList函数中的一个循环。像...

struct Node {
  int value;
  Node* next;
};
// Loop in the function; recursion not required, and no return value.
void delete_list(Node* n)
{
  Node* tmp;
  while (nullptr != n) {
    tmp = n->next;
    delete n;
    n = tmp;
  }
}

在这种情况下,Node实例不拥有其同级Node(Node.next(,也不负责解除分配它;这取决于delete_list函数。

Node 的析构函数中删除行delete next;

我认为您可能有两种选择。首先,正如 R Sahu 所说,删除析构函数中的delete next

struct Node {
    int value;
    Node* next;
};
Node* deleteList(Node* p) {
    if(p == nullptr) return nullptr;
    Node* pNext = p->next;
    delete p;
    return deleteList(pNext);
}

其次,只需删除 deleteList 中链接的头节点,但不递归删除节点。

struct Node {
    int value;
    Node* next;
    Node() : value(0), next(nullptr)
    {}
    ~Node() {
        if (next != nullptr)
        {
            delete next;
        }
    }
};
Node* deleteList(Node* p) {
    if (p != nullptr)
    {
        delete p;
    }
    return nullptr;  // in fact your code always return nullptr. so it just return nullptr here.
}