调试链表指针代码:segmentation fault
Debugging linked list pointers code: segmentation fault
所以下面的代码:
/*
* For your reference:
*
* SinglyLinkedListNode {
* int data;
* SinglyLinkedListNode* next;
* };
*
*/
SinglyLinkedListNode* insertNodeAtTail(SinglyLinkedListNode* head, int data) {
SinglyLinkedListNode* temp = head;
while (temp != NULL) {
temp = temp->next;
}
SinglyLinkedListNode* temp1;
temp1->data = data;
temp1->next = NULL;
temp->next = temp1;
return temp;
}
所以,基本上我想在链表 "head" 和更新列表的末尾添加 "data" 和 return 。那么错在哪里呢?
编辑:好的,我犯了第一个错误。但即使我在循环条件中用 temp->next!=NULL 替换 temp!=NULL 仍然存在此错误
这里也崩溃了:
SinglyLinkedListNode* temp1;
temp1->data=data;
当您到达循环的末尾 while(temp!=NULL){
时,这里的 temp
是 NULL
。
下面你正在使用这样的语句 temp->next=temp1;
这会导致崩溃
您必须为节点分配内存。记得清理分配的内存。对于 new
的每次调用,您都需要调用 delete
。所以我更喜欢智能指针。
在你的循环 temp
包含 NULL
之后。您不能取消引用空指针。
SinglyLinkedListNode* insertNodeAtTail(SinglyLinkedListNode* head, int data) {
SinglyLinkedListNode* temp1 = new SinglyLinkedListNode;
temp1->data = data;
temp1->next = nullptr;
if (!head) {
head = temp1;
return head;
}
SinglyLinkedListNode* temp = head;
while(temp->next){
temp = temp->next;
}
temp->next = temp1;
return temp;
}
这个函数
SinglyLinkedListNode* insertNodeAtTail(SinglyLinkedListNode* head, int data) {
SinglyLinkedListNode* temp=head;
while(temp!=NULL){
temp=temp->next;
}
SinglyLinkedListNode* temp1;
temp1->data=data;
temp1->next=NULL;
temp->next=temp1;
return temp;
}
没有意义。在这个循环之后
while(temp!=NULL){
temp=temp->next;
}
指针temp
等于NULL。所以这个声明
temp->next=temp1;
调用未定义的行为。
指针 temp1
未初始化。所以这些陈述再次
temp1->data=data;
temp1->next=NULL;
调用未定义的行为。
函数的使用者并不知道返回的指针是链表的头指针还是尾指针。所以不清楚是把返回的指针赋值给头指针还是直接忽略返回值
函数可以如下所示。
void insertNodeAtTail( SinglyLinkedListNode * &head, int data )
{
SinglyLinkedListNode **current = &head;
while ( *current != nullptr ) current = &( *current )->next;
*current = new SinglyLinkedListNode { data, nullptr };
}
如果在 main 中定义了指向头节点的指针,例如
SinglyLinkedListNode *head = nullptr;
那么函数调用会像这样
insertNodeAtTail( head, some_data );
函数的另一种定义方式如下
SinglyLinkedListNode* insertNodeAtTail( SinglyLinkedListNode *head, int data )
{
SinglyLinkedListNode *new_node = new SinglyLinkedListNode { data, nullptr };
if ( head == nullptr )
{
head = new_node;
}
else
{
SinglyLinkedListNode *current = head;
while ( current->next != nullptr ) current = current->next;
current->next = new_node;
}
return head;
}
在这种情况下,如果您在 main 中定义了指向头节点的指针,例如
SinglyLinkedListNode *head = nullptr;
那么函数调用看起来像
head = insertNodeAtTail( head, some_data );
在这两个函数定义之间,第一个函数定义更可取,因为不需要记住将返回的指针分配给头节点。
请记住,如果您有一个单向链表并希望将新节点附加到链表十的尾部,最好定义双向单向链表。在这种情况下,列表定义看起来像
class SinglyLinkedList
{
private:
struct Node
{
int data,
Node *next;
} *head = nullptr, *tail = nullptr;
public:
SinglyLinkedList() = default;
void insertNodeAtHead( int data );
void insertNodeAtTail( int data );
// other member functions;
};
所以下面的代码:
/*
* For your reference:
*
* SinglyLinkedListNode {
* int data;
* SinglyLinkedListNode* next;
* };
*
*/
SinglyLinkedListNode* insertNodeAtTail(SinglyLinkedListNode* head, int data) {
SinglyLinkedListNode* temp = head;
while (temp != NULL) {
temp = temp->next;
}
SinglyLinkedListNode* temp1;
temp1->data = data;
temp1->next = NULL;
temp->next = temp1;
return temp;
}
所以,基本上我想在链表 "head" 和更新列表的末尾添加 "data" 和 return 。那么错在哪里呢?
编辑:好的,我犯了第一个错误。但即使我在循环条件中用 temp->next!=NULL 替换 temp!=NULL 仍然存在此错误
这里也崩溃了:
SinglyLinkedListNode* temp1;
temp1->data=data;
当您到达循环的末尾 while(temp!=NULL){
时,这里的 temp
是 NULL
。
下面你正在使用这样的语句 temp->next=temp1;
这会导致崩溃
您必须为节点分配内存。记得清理分配的内存。对于 new
的每次调用,您都需要调用 delete
。所以我更喜欢智能指针。
在你的循环 temp
包含 NULL
之后。您不能取消引用空指针。
SinglyLinkedListNode* insertNodeAtTail(SinglyLinkedListNode* head, int data) {
SinglyLinkedListNode* temp1 = new SinglyLinkedListNode;
temp1->data = data;
temp1->next = nullptr;
if (!head) {
head = temp1;
return head;
}
SinglyLinkedListNode* temp = head;
while(temp->next){
temp = temp->next;
}
temp->next = temp1;
return temp;
}
这个函数
SinglyLinkedListNode* insertNodeAtTail(SinglyLinkedListNode* head, int data) {
SinglyLinkedListNode* temp=head;
while(temp!=NULL){
temp=temp->next;
}
SinglyLinkedListNode* temp1;
temp1->data=data;
temp1->next=NULL;
temp->next=temp1;
return temp;
}
没有意义。在这个循环之后
while(temp!=NULL){
temp=temp->next;
}
指针temp
等于NULL。所以这个声明
temp->next=temp1;
调用未定义的行为。
指针 temp1
未初始化。所以这些陈述再次
temp1->data=data;
temp1->next=NULL;
调用未定义的行为。
函数的使用者并不知道返回的指针是链表的头指针还是尾指针。所以不清楚是把返回的指针赋值给头指针还是直接忽略返回值
函数可以如下所示。
void insertNodeAtTail( SinglyLinkedListNode * &head, int data )
{
SinglyLinkedListNode **current = &head;
while ( *current != nullptr ) current = &( *current )->next;
*current = new SinglyLinkedListNode { data, nullptr };
}
如果在 main 中定义了指向头节点的指针,例如
SinglyLinkedListNode *head = nullptr;
那么函数调用会像这样
insertNodeAtTail( head, some_data );
函数的另一种定义方式如下
SinglyLinkedListNode* insertNodeAtTail( SinglyLinkedListNode *head, int data )
{
SinglyLinkedListNode *new_node = new SinglyLinkedListNode { data, nullptr };
if ( head == nullptr )
{
head = new_node;
}
else
{
SinglyLinkedListNode *current = head;
while ( current->next != nullptr ) current = current->next;
current->next = new_node;
}
return head;
}
在这种情况下,如果您在 main 中定义了指向头节点的指针,例如
SinglyLinkedListNode *head = nullptr;
那么函数调用看起来像
head = insertNodeAtTail( head, some_data );
在这两个函数定义之间,第一个函数定义更可取,因为不需要记住将返回的指针分配给头节点。
请记住,如果您有一个单向链表并希望将新节点附加到链表十的尾部,最好定义双向单向链表。在这种情况下,列表定义看起来像
class SinglyLinkedList
{
private:
struct Node
{
int data,
Node *next;
} *head = nullptr, *tail = nullptr;
public:
SinglyLinkedList() = default;
void insertNodeAtHead( int data );
void insertNodeAtTail( int data );
// other member functions;
};