如何“完全”删除链表中的所有节点?

Posted

技术标签:

【中文标题】如何“完全”删除链表中的所有节点?【英文标题】:How to "completely" delete all nodes in a linked list? 【发布时间】:2016-03-19 01:22:34 【问题描述】:

我很好奇指针和删除指针在 C++ 中是如何工作的,所以我做了一个实验。我制作了一个非常简单的单链表和以下递归函数,用于删除列表中的所有节点:

void deleteList(Node *node) 
    if (!node)
        return;
    deleteList(node->next);
    cout << "deleting node " << node->data << endl;
    delete node;
    node = nullptr;

我想这会成功删除列表中的所有节点。但是,在main中调用了这个函数后,我检查了头节点是否仍然存在:

List list;
// appending a bunch of numbers to the list...
list.deleteList(list.head);
if (list.head) 
    cout << true;

这将在控制台打印 1,这意味着头部确实仍然存在。我希望头部和它之后的所有其他节点都为空,因此 if 条件失败,因为将指针设置为空是我在递归函数中做的最后一件事。那么为什么程序会报告头部仍然存在呢?

编辑:更改列表列表();列出列表;

【问题讨论】:

List list(); 不是你想的那样。 Most Vexing Parse 是的,我的实验中实际上有两个构造函数。上面示例中的一个调用另一个构造函数,该构造函数初始化诸如 0 的大小值和一个新的空头节点。 该语句根本不调用构造函数。它是一个函数list 的声明,它的返回类型是List。对于对象初始化,()需要被移除。 哦,你说得对。一时间不知道我在想什么 【参考方案1】:

您释放了内存,但分配给nullptr 只影响传递给函数的指针的副本,而不影响调用者中的原始指针。

如果你将函数声明为通过引用接收指针:

void deleteList(Node *&node) 

那么node = nullptr; 的分配也会影响调用者。

请注意,由于您标记了此 C++11,因此将链表定义为正向的一系列 std::unique_ptr&lt;Node&gt;s 通常要简单得多(如果它是双向的,则反向的原始指针避免引用循环),因此您可以避免需要特殊的删除函数,只需将头指针设置为nullptr,让C++完成级联删除的工作。

编辑:让std::unique_ptr 完成工作是有缺陷的;正如在 cmets 中所指出的,这意味着列表大小实际上受到堆栈的限制,并且当您删除它们时,太大的列表会导致堆栈溢出。因此,明确地一一清除(最简单的方法是正确实现弹出,并且清除只是弹出直到 head 通过 popleft 方法转换为 nullptr )会更安全。我将最初的建议留给后人,所以这个解释是有道理的。

【讨论】:

完美,感谢您的澄清。我认为指针总是通过引用传递。这是我第一次听说唯一指针(如果这就是它们的名称?)。我需要更多地了解这些 @MannyKim:是的,unique pointers。指针很有趣,因为指针本身是按值传递的;两个指针最初都引用相同的内存,但是更改被调用者中的指针不会影响调用者,它只会更改指向的数据(包括在该位置释放内存的效果;不要取消引用你知道的指针由另一个函数释放)可见。 为了清楚起见,“释放指针”是指“删除节点”,“取消引用指针”是指“节点 = nullptr”,对吗?并感谢您提供的额外细节,它确实使指针更容易理解 @MannyKim:“释放”和“删除”是等价的;在 C 中,您使用 free 函数,在 C++ 中,您使用 delete 关键字(尽管理想情况下,您使用像 unique_ptrshared_ptr 这样的智能指针以避免需要显式使用 delete)。取消引用指针意味着实际使用它来查找数据,使用*-&gt;。删除实际上也有效地取消了指针的引用(删除它两次是一个严重的错误)。分配nullptr 既不删除/释放也不引用哑指针,但对于唯一指针,它相当于一次删除和清除指针。 让C++做递归数据结构的级联删除工作会导致栈溢出。

以上是关于如何“完全”删除链表中的所有节点?的主要内容,如果未能解决你的问题,请参考以下文章

删除链表中的节点后,打印节点列表显示已删除节点

如何删除链表中的节点?

Leetcode练习(python):链表类:第82题:删除排序链表中的重复元素 II:给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。

删除链表中的节点

如何删除链表中的头节点? C

删除链表中的重复节点