C++链表不删除头节点

Posted

技术标签:

【中文标题】C++链表不删除头节点【英文标题】:C++ linked list does not delete the head node 【发布时间】:2014-02-17 01:31:35 【问题描述】:

我有一个非常简单的节点类来实现链表(它只有数据和下一个指针)。下面的函数应该删除具有“数据”=值的第一个节点。 该功能工作正常。但是当我尝试删除第一个元素(列表的头部)时,它没有。那么,问题出在哪里? 这是代码

class Node
    public:
        int data;
        Node *next;
....some other functions...

;
void deleteNode(Node *n, int value)
    cout<<"after deleting node with data = "<<value<<" : ";
    if(n->data == value)
        n = n->next;        //I guess the problem is somewhere here!
        return;
    
    while(n)
        if(n->next->data == value)
            n->next = n->next->next;
            return;
        
        n = n->next;
    


void printTheLinkedList(Node *n)
    while(n)
        cout<<n->data<<" --> ";
        n = n->next;
    
    cout<<"NULL"<<endl;



int main()
    Node N(0);
    for(int i = 1; i < 10; i++)
        N.appendNode(i);

    printTheLinkedList(&N);
    deleteNode(&N, 3);
    printTheLinkedList(&N);
    deleteNode(&N, 0);
    printTheLinkedList(&N);


    return 0;

这里是代码的输出(注意:3被删除,0不是)

0 --> 1 --> 2 --> 3 --> 4 --> 5 --> 6 --> 7 --> 8 --> 9 --> NULL
0 --> 1 --> 2 --> 4 --> 5 --> 6 --> 7 --> 8 --> 9 --> NULL
0 --> 1 --> 2 --> 4 --> 5 --> 6 --> 7 --> 8 --> 9 --> NULL

【问题讨论】:

相关:使链表中的所有节点成为动态的。无需保留哨兵非动态头节点。 nullptr 是一个非常好的标记值,用于推断“列表为空”状态。 【参考方案1】:

首先,您在代码注释中的猜测是正确的。这条线与问题有关。

存在三个问题:

    无法删除根节点,因为它是作为main 函数的局部变量在堆栈上分配的。

    链接节点需要封装在类似linked_list 容器数据结构中。它会在内部(至少)存储一个指向链表的head(例如开头)的指针。如果 head 节点被删除,您只需将下一个指针设置为 head

    您的删除代码当前没有释放动态分配的节点,因此您的应用正在泄漏内存。

由于您使用 C++ 进行编码,因此您可以使用智能指针来处理自动释放。

【讨论】:

+1 我同意智能指针的心态,并且全心全意支持它的使用。使用它们实现链接节点系统时应小心,尤其是在删除它们时。如何释放这样一个节点系统(例如 100,000 个项目的链表) 不会引起对节点析构函数的递归,从而快速消耗调用激活堆栈以被遗忘,这不一定是直观的。使用它们好的和正确的,别搞错了。但这样做需要一些额外的专业知识。 @WhozCraig 感谢您分享您的意见!我完全没有想到这种情况,但完全有道理。在 C++ 中有很多小陷阱可以发现:-D 完全没问题。例如,See it live【参考方案2】:

您将局部变量 n 更改为 n-&gt;nextmain 中的 head 值实际上并没有改变。试试这个,它会返回新的头部。

Node* deleteNode(Node *n, int value)
    cout<<"after deleting node with data = "<<value<<" : ";
    if(n->data == value)
        n = n->next;        //I guess the problem is somewhere here!
        return n;
    
    Node* root = n;
    while(n)
        if(n->next->data == value)
            n->next = n->next->next;
            return;
        
        n = n->next;
    
    return root;

然后像这样调用:

printTheLinkedList(&N);
Node* head = deleteNode(&N, 3);
printTheLinkedList(head);
head = deleteNode(head, 0);
printTheLinkedList(head);

【讨论】:

我个人认为 NobuGames 的回答更好,一定要听从他的建议!【参考方案3】:

您将 head 定义为

Node N(0);

因此你不能删除这个节点(头)。您应该将 head 声明为指向 Node 的指针

Node *N( nullptr );

在这种情况下,函数可以如下所示

void deleteNode( Node * &n, int value )

    cout << "after deleting node with data = " << value << " : ";

    Node *current = n;
    Node *previous = nullptr;;

    while ( current && current->data != value )
    
        previous = current;
        current = current->next;
    

    if ( current )
    
        if ( previous ) previous->next = current->next;
        else n = nullptr;

        delete current;
    

【讨论】:

以上是关于C++链表不删除头节点的主要内容,如果未能解决你的问题,请参考以下文章

剑指offer(C++)-JZ18:删除链表的节点(数据结构-链表)

剑指offer(C++)-JZ18:删除链表的节点(数据结构-链表)

剑指offer(C++)-JZ18:删除链表的节点(数据结构-链表)

leetcode No203 移除链表元素 java

数据结构-链表

链表(删除节点)