【问题标题】:Deleting node in linked list - segmentation fault删除链表中的节点 - 分段错误
【发布时间】:2020-04-19 00:46:43
【问题描述】:

问题需要从链表中删除节点给定链表的头指针和要删除的链表中节点的位置。更多问题详情请见:https://practice.geeksforgeeks.org/problems/delete-a-node-in-single-linked-list/1

代码返回分段错误,但不确定我哪里出错了。我的代码如下:

Node* deleteNode(Node *head,int x)
{
    //Your code here
    struct Node* temp = head;

    if(x==0){
        //change head
        head = temp->next;
        free(temp);
    }
    //find previous node of node to be deleted
    for(int i=0; temp!=NULL && i<x-1; ++i){
        //traverse
        temp = temp->next;
    }
    //now temp should be pointing to previous node
    //store pointer to next of node to be deleted
    struct Node* next = temp->next->next;
    free(temp->next);
    temp->next= next;
}

【问题讨论】:

  • 抛开内部逻辑,别再对编译器撒谎了。你答应return一个Node*;兑现诺言。
  • 您真正使用的是哪种语言,C 还是 C++?你知道,它们是不同的语言。
  • @WhozCraig Snap,错过了哈哈。

标签: c++ c pointers linked-list segmentation-fault


【解决方案1】:

您应该在一开始以及在执行最后 3 行代码之前检查 head == nullptr 是否 temp == nullptr 因为您可以退出 for 循环,因为用户尝试删除的节点超出了大小。

您还应该考虑从您的函数中返回void

你可以这样做:

void deleteNode(Node *head,int x)
{
    // this way you avoid dereferencing nullptr with temp->next later on
    if(head == nullptr) return;
    //Your code here
    struct Node* temp = head;

    if(x==0){
        //change head
        head = temp->next;
        free(temp);
    }
    //find previous node of node to be deleted
    for(int i=0; temp!=NULL && i<x-1; ++i){
        //traverse
        temp = temp->next;
    }
    //now temp should be pointing to previous node
    //store pointer to next of node to be deleted

    // you need to check to see if temp is nullptr here or if the node
    // after temp is nullptr because either of those can cause you to 
    // get a segmentation fault because of dereferencing a nullptr
    if(temp == nullptr || temp->next == nullptr) return;
    struct Node* next = temp->next->next;
    free(temp->next);
    temp->next= next;
}

【讨论】:

    【解决方案2】:

    您的代码包含许多可以取消引用空指针的地方。例如这里:

    struct Node* temp = head;
    
    if(x==0){
        //change head
        head = temp->next;
        free(temp);
    }
    

    如果head 已经是一个空指针。此外,您似乎假设这会更改 caller 中的 head 变量,但事实并非如此。你必须通过一个双指针来实现这一点。最后,看起来您的函数应该在 free(temp); 之后返回。

    那么,看这部分:

    for(int i=0; temp!=NULL && i<x-1; ++i){
        //traverse
        temp = temp->next;
    }
    //now temp should be pointing to previous node
    //store pointer to next of node to be deleted
    

    不,它不一定指向一个节点,temp 也可以包含一个空指针,这是你的 for 循环的第二个中断条件。如果是这种情况,您必须检查并退出。

    【讨论】:

    • 感谢您的回复。为什么我必须传递一个双指针来更改调用者中的 head 变量? (是因为 head 本身是作为双指针传递的吗?)
    • @Prav 如果只更改传递的指针,则仅对函数中的局部参数进行赋值。如果将指针传递给指针,则可以取消引用它来分配它。 (即*head = temp-&gt;next)。另一种选择是保持原样,但返回新的head 并将其分配给调用函数中的头部(即调用者中的head = deleteNode(head, x);)。这要求您始终返回新的有效head,而您目前没有这样做。
    猜你喜欢
    • 2017-10-28
    • 2018-03-10
    • 2021-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-17
    相关资源
    最近更新 更多