从单链表的中间删除一个节点?
Removing a node from the middle of a singly-linked list?
我知道这个问题已经被问过很多次了,但我似乎仍然无法弄清楚我遇到的错误。这是我的代码:
int remove(ListNode * &head, int length)
{
if(head != NULL)
{
string str = head->word;
if(str.size() > length)
{
if(head->next->next != NULL)
{
head->word = head->next->word;
ListNode* tempNode = head->next->next;
delete head->next; //segfault
head->next = tempNode;
return 1 + remove(head->next, length);
}
else if(head->next != NULL)
{
head->word = head->next->word;
delete head->next;
head->next = NULL;
return 1 + remove(head->next, length);
}
else
{
delete head;
head = NULL;
return 1 + remove(head->next, length);
}
}
else
{
return remove(head->next, length);
}
}
return count;
}
目标是删除任何大小大于参数中给定长度的单词。当我尝试删除 head->next 时发生错误,即使它显然存在并且我也能够打印出这个词。我得到的错误是
* Error in `./a.out': double free or corruption (out): 0x00007ffde3d4d7c0 * Aborted (core dumped)
我尝试在其上 运行 Valgrind,但无法解释输出,因为它没有指定任何行号。
感谢您对这个简单问题的任何帮助。
Note: The first part of this answer was before OP edited the code (see new answer below)
这部分:
head == NULL;
return remove(head->next, length, count + 1);
^^^^
不好。
首先,你不应该设置:
head == NULL;
^^
应该是:
HEAD = NULL;
此外,之后您不应该再次调用该函数:
return remove(head->next, length, count + 1);
完成后(您刚刚删除了 head
元素,因此 head
为 NULL)。只需 return 0;
(或您想要 return 的任何值)。
Answer to edited question
你的新代码的一个问题是这个结构:
if(head->next->next != NULL) // Here you know that head isn't NULL
{ // but head->next can still be NULL so
.... // don't do head->next->next !
}
else if(head->next != NULL) // This check should also be part
{ // of your first if-statement. Like:
.... // if ((head->next != NULL) && (head->next->next != NULL))
}
else
{
....
}
总的来说,我不认为使用递归函数调用对这个问题有好处。非递归方法是:
int remove(ListNode * &head, int length)
{
if(head == NULL)
{
// empty
return 0;
}
ListNode *tmp;
int removed = 0;
// Remove elements from start of list
while(true)
{
string str = head->word;
if(str.size() > length)
{
// Remove head element
tmp = head;
head = head->next;
delete tmp;
++removed;
if (head == NULL)
{
return removed;
}
}
else
{
// No more head elements to remove
break;
}
}
// Remove elements from middel to end
tmp = head;
while(tmp->next)
{
string str = tmp->next->word;
if(str.size() > length)
{
// Remove element tmp->next
ListNode *tmp2 = tmp->next;
tmp->next = tmp->next->next;
delete tmp2;
++removed;
}
else
{
// Keep current tmp->next and move to next element
tmp = tmp->next;
}
}
return removed;
}
我知道这个问题已经被问过很多次了,但我似乎仍然无法弄清楚我遇到的错误。这是我的代码:
int remove(ListNode * &head, int length)
{
if(head != NULL)
{
string str = head->word;
if(str.size() > length)
{
if(head->next->next != NULL)
{
head->word = head->next->word;
ListNode* tempNode = head->next->next;
delete head->next; //segfault
head->next = tempNode;
return 1 + remove(head->next, length);
}
else if(head->next != NULL)
{
head->word = head->next->word;
delete head->next;
head->next = NULL;
return 1 + remove(head->next, length);
}
else
{
delete head;
head = NULL;
return 1 + remove(head->next, length);
}
}
else
{
return remove(head->next, length);
}
}
return count;
}
目标是删除任何大小大于参数中给定长度的单词。当我尝试删除 head->next 时发生错误,即使它显然存在并且我也能够打印出这个词。我得到的错误是
* Error in `./a.out': double free or corruption (out): 0x00007ffde3d4d7c0 * Aborted (core dumped)
我尝试在其上 运行 Valgrind,但无法解释输出,因为它没有指定任何行号。 感谢您对这个简单问题的任何帮助。
Note: The first part of this answer was before OP edited the code (see new answer below)
这部分:
head == NULL;
return remove(head->next, length, count + 1);
^^^^
不好。
首先,你不应该设置:
head == NULL;
^^
应该是:
HEAD = NULL;
此外,之后您不应该再次调用该函数:
return remove(head->next, length, count + 1);
完成后(您刚刚删除了 head
元素,因此 head
为 NULL)。只需 return 0;
(或您想要 return 的任何值)。
Answer to edited question
你的新代码的一个问题是这个结构:
if(head->next->next != NULL) // Here you know that head isn't NULL
{ // but head->next can still be NULL so
.... // don't do head->next->next !
}
else if(head->next != NULL) // This check should also be part
{ // of your first if-statement. Like:
.... // if ((head->next != NULL) && (head->next->next != NULL))
}
else
{
....
}
总的来说,我不认为使用递归函数调用对这个问题有好处。非递归方法是:
int remove(ListNode * &head, int length)
{
if(head == NULL)
{
// empty
return 0;
}
ListNode *tmp;
int removed = 0;
// Remove elements from start of list
while(true)
{
string str = head->word;
if(str.size() > length)
{
// Remove head element
tmp = head;
head = head->next;
delete tmp;
++removed;
if (head == NULL)
{
return removed;
}
}
else
{
// No more head elements to remove
break;
}
}
// Remove elements from middel to end
tmp = head;
while(tmp->next)
{
string str = tmp->next->word;
if(str.size() > length)
{
// Remove element tmp->next
ListNode *tmp2 = tmp->next;
tmp->next = tmp->next->next;
delete tmp2;
++removed;
}
else
{
// Keep current tmp->next and move to next element
tmp = tmp->next;
}
}
return removed;
}