这个函数应该从链表中删除元素。然而,目前它已经完成了这项工作,经过进一步的测试,我发现在使用该函数约2-3次后,我出现了分割错误。例如,假设listA
包含1 2 3 4 4 5
,当我执行remove listA 4
,然后打印listA
的元素时,输出应该是1 2 3 5
,事实确实如此。但是,当我在列表上再使用1-2次remove函数时,它就停止了工作,并且不断出现分段错误。我不知道为什么。。任何帮助都将不胜感激!
void mylist::remove(int z)
{
Node *currP, *prevP;
prevP = NULL;
for (currP = head;
currP != NULL;
prevP = currP, currP = currP->next) {
if (currP->key == z) {
if (prevP == NULL) {
head = currP->next;
} else{
prevP->next = currP->next;
}
delete currP;
currP=prevP;
numberofnodes--;
}
}
return;
}
当第一个节点表单列表被删除时,您不会处理这种情况,因为prevP
将为null。删除currP
之后,您正在分配currP=prevP;
。在下一次迭代中,当执行prevP = currP, currP = currP->next
进行下一次循环迭代时,将导致分割故障。
你可以使用while循环,比如:
void mylist::remove(int z)
{
Node *currP, *prevP, *temp;
prevP = NULL;
currP = head;
while(currP != NULL){
if (currP->key == z) {
if (prevP == NULL) {
head = currP->next;
} else{
prevP->next = currP->next;
}
temp = currP;
currP = currP->next;
delete temp;
numberofnodes--;
}
else
{
prevP = currP;
currP = currP->next;
}
}
return;
}
考虑当您删除列表中的第一个条目时会发生什么:您设置了head = currP->next
,但将prevP
保留为NULL
。当代码到达currP=prevP
时,currP
变为NULL
,然后在迭代中尝试访问currP->next
时会遇到错误。你需要重新组织你的循环来避免这种情况。
在for循环上移动到下一次迭代时的指针管理是不正确的。当currP
在删除第一项时设置为NULL时,您将在for循环的迭代增量步骤中取消引用NULL。
老实说,for循环一开始并不是这个算法最热门的想法,但如果你真的想用最少的精力做到这一点,指针对指针的解决方案可以很快完成这项任务:
void mylist::remove(int z)
{
Node **pp = &head;
while (*pp)
{
if ((*pp)->key != z)
{
pp = &(*pp)->next;
}
else
{
Node *victim = *pp;
*pp = victim->next;
delete victim;
--numberofnodes;
}
}
}
它的工作原理
指向指针pp
的指针包含我们感兴趣检查匹配的指针的地址。它最初保存head
指针的地址。
Node **pp = &head;
对于每个不匹配,我们移动到当前节点的next
指针的地址:
if ((*pp)->key != z)
{
pp = &(*pp)->next;
}
但是,当我们发现匹配时,pp
中保存地址的指针值将保存到临时的:
Node *victim = *pp;
则该指针(如果这是列表中的第一项,则可以是head
指针)被更新为其指向节点的next
指针值。
*pp = victim->next;
最后,现在未链接的节点被丢弃。
delete victim;
注意:
当我们放弃匹配时,next
有NO移动。在删除之前,我们已经通过加载*pp
并将指针值保存在它自己的next
指针中来移动到那里。此外,如果列表为空,则head
指针为NULL,并且最后一个节点next
指针为终止列表的NULL
,这是(希望很明显)关键。我知道标准链接列表的东西,但它很重要,因此被提及。
祝你好运。
考虑删除列表中的1。prevP=空;然后删除currP并为其分配prevP,切换为NULL。循环结束。然后它转到的部分:prevP=currP,currP=currP->next;后一种情况是问题,因为currP为NULL。您正在访问NULL->next。
删除currP;currP=prevP;
这导致了分段错误,在第一次迭代时,prevP为null,因此如果在迭代prevP不为null的情况下执行。