段故障:链接列表节点插入功能[C ++]

时间:2019-06-26 19:27:56

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

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

我可以通过几个小调整就可以使用该函数,但是还有另一个问题,我失去了作为指针的头节点的属性,它现在包含一些垃圾数据,当我打印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;
}

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

任何帮助/深入了解都会有很大帮助。

谢谢。

1 个答案:

答案 0 :(得分:4)

问题1:

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

temp->next = addTo;

保证temp退出时NULL将是while(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.
}

社区添加How do I properly delete nodes of linked list in C++的第一个答案演示了如何使用相同的指针到指针技巧使删除节点变得容易。