2014-10-28 61 views
0

这个函数应该从链表中移除元素。然而,目前它完成了这项工作,通过进一步的测试,我发现在使用该功能约2-3次后出现分段错误。例如,可以说listA包含1 2 3 4 4 5,当我做remove listA 4然后打印listA的元素时,输出应该是1 2 3 5,它是。但是,当我在列表中多次使用1-2次删除功能时,它会停止工作,并且不断收到分段错误。我不知道为什么..任何帮助将不胜感激!函数不能多次工作?

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; 
     } 
+0

你已经接近精确了,但是:*“当我在列表中多次使用1-2次删除功能时,它会停止工作”*放下了球。看看[“最小,完整,可验证示例”](http://stackoverflow.com/help/mcve)。显示您的确切输入,以及编译任何人都可以复制的程序 - 粘贴到编译器(“完成”)并且可以重复(“可验证地”)给出错误的输出。测试基本案例,例如从包含1的列表中删除“1”。您可能在过程中发现自己的问题... – HostileFork 2014-10-28 06:39:24

+0

只需修改for循环中的update语句,仅当它不是NULL时才从currP访问下一个元素。 – 2014-10-28 07:20:41

回答

2

由于prevP将为空,因此您不处理第一个节点表单列表被删除的情况。删除currP后,您正在分配currP=prevP;。在下一次迭代中,当prevP = currP, currP = currP->next将被执行用于下一个循环迭代时,它将导致分段错误。在转移到下一个迭代的for循环是不正确

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; 
    } 
0

delete currP; currP = prevP;

这是导致分段错误,在第一次迭代prevP为空,所以如果在迭代prevP不是空的情况下执行。

+0

好吧,有道理。我将如何改变我的代码来做到这一点?不确定。 – sam696969 2014-10-28 06:44:34

+0

prevPcurrentP; 删除currP; – 2014-10-28 06:57:24

1

请考虑当您删除列表中的第一个条目时会发生的情况:您设置了head = currP->next但您将prevP保留为NULL。当代码变为currP=prevP时,currP变为NULL,然后在迭代中尝试访问currP->next时会出现错误。你需要重新组织你的循环来避免这种情况。

1

您的指针管理:

您可以使用while循环来代替,等等。当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; 

注:

NO运动next当我们放弃比赛。我们已经通过加载*pp,并在删除之前将其指针值保存在其自己的next指针中移动到那里。此外,它是(很显然)关键head指针为空,如果列表为空,最后一个节点next指针是NULL终止列表。标准链表的东西,我知道,但它很重要,因此提到。

祝你好运。

1

考虑在列表中删除1。 prevP = NULL; 然后你删除currP并用prevP分配它,巫婆是NULL。 此循环结束。 然后它转到以下部分:prevP = currP,currP = currP-> next; 后一种情况下的问题,因为currP是NULL。您正在访问NULL-> next。