首页 > 解决方案 > 段错误:链表节点插入函数 [C++]

问题描述

我创建了一个名为“插入”的函数,用于在链接列表中插入一个新节点。它采用值和头节点进行插入。当我自己手动添加节点时,程序按预期运行,但是当我使用该函数添加节点时出现分段错误。

我可以通过一些小调整来使该函数工作,但还有一个问题,我失去了头节点作为指针的属性,它现在包含一些垃圾数据,当我打印 LinkedList 时会打印这些数据。

我执行的调整是:

Change Line 26 to: A->next = NULL;
Change Line 17 to: while(temp->next != NULL)

“分段错误”发生在第 20 行(未完成调整时):

Line 20 ----->  temp->next = addTo;

我已经尝试通过引用传递参数,使用头节点的全局变量并检查函数的逻辑。该逻辑适用于手动添加节点。

我附上了下面的完整代码:

#include <bits/stdc++.h>
using namespace std;

struct ListNode {
int data;
ListNode *next;
};

void Insert(int x , ListNode* head)
{
    ListNode* addTo = new ListNode();
    addTo->data = x;
    addTo->next = NULL;

    ListNode* temp;
    temp = head;
    while(temp != NULL)
    temp = temp->next;

    temp->next = addTo;
}

int main()
{
    ListNode* A;
    A = NULL;

    //Inserting A Node Manually
    // ListNode* first = new ListNode();
    // first->data = 9;
    // first->next = NULL;
    // while(A != NULL)
    // A = A->next;
    //     A = first;

    //Inserting using Insert function.
   Insert(2,A);Insert(3,A);Insert(6,A);Insert(7,A);

    //Printing
    ListNode* temp = A;
    while(temp != NULL)
    {
        cout << temp->data << " ";
        temp = temp->next;
    }
    return 0;
}

我希望将节点添加到列表中,因为逻辑似乎是正确的,但是我遇到了分段错误。

对此的任何帮助/见解都会有很大帮助。

谢谢你。

标签: c++pointerslinked-listsegmentation-fault

解决方案


问题1:

while(temp != NULL)
temp = temp->next;

temp->next = addTo;

保证tempNULLwhile(temp != NULL)退出时进行。这意味着没有temp得到next从。

与其在这里解决这个问题,我将继续解决问题 2,用一块石头杀死两只鸟。

问题2:

void Insert(int x , ListNode* head)

head如果函数中发生更改,您将无法更新调用者Insert。您可以更改 指向的对象head,但head它本身只是地址的副本。如果您将此副本更改为指向另一个地址,则调用者不知道。

这意味着你每次打电话Insert(<number>, A);A都会一直在NULL

解决方案:

通过引用head传入Insert,以便可以对其进行更新。

void Insert(int x , ListNode*& head)
                             ^ reference to pointer

head的工作是指向列表中的第一项。这意味着它与任何next指针做同样的事情:它指向下一项。唯一的区别是名称。我们可以通过添加一个额外的间接,一个指向head.

ListNode ** temp = &head;

请注意,我们不能ListNode *& temp在此处使用引用 (),因为一旦初始化引用以引用一个对象,就不能将其更改为引用不同的对象。您可以更改的指针,允许我们遍历列表并始终指向temp下一个next

现在head或任何next是简单的temp。这使得head与所有其他变量完全相同,next并且不需要特殊情况。

void Insert(int x , ListNode*& head)   
{
    ListNode* addTo = new ListNode(); 
    addTo->data = x;
    addTo->next = NULL; // consider making a smarter ListNode constructor that makes 
                        // it impossible to forget to set next.

    ListNode ** temp = &head; // we can now manipulate the address in head through temp
                  
    while(*temp != NULL) // note the dereference to get the pointed at pointer
                         // temp won't be null, but it could be pointing at a pointer 
                         // that is null, and that is the end of the list
    { // I always use the optional braces. They prevent confusion.
        temp = &(*temp)->next; //get pointer to the next next pointer
                               // we can now manipulate it exactly the same as head. 
    }
    // we exit the loop with a pointer to the next pointer that we wish to point at 
    // the new list item regardless of whether it's head or the next of some later
    // link in the list
    *temp = addTo; // update the pointed at pointer with the new Node.
}

社区添加的第一个答案如何在 C++ 中正确删除链表的节点演示了如何使用相同的指针对指针技巧来轻松删除节点。


推荐阅读