功能不能多次工作?

时间:2014-10-28 06:34:13

标签: c++ data-structures linked-list

此函数应该从链表中删除元素。目前它正在完成这项工作,但通过进一步的测试,我发现在使用该功能约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;
         }

5 个答案:

答案 0 :(得分:2)

删除第一个节点表单列表时,您没有处理这种情况,因为prevP将为空。删除currP后,您将分配currP=prevP;。在下一次迭代中,当prevP = currP, currP = currP->next执行下一次for循环迭代时,将导致分段错误。

您可以使用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;
     }

答案 1 :(得分:1)

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

答案 2 :(得分:1)

在for-loop上移动到下一次迭代时,指针管理是不正确的。在删除第一个项目时将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指针中保存指针值来移动到那里。此外,(希望很明显) critical 如果列表为空,则head指针为NULL,并且最后一个节点next指针为NULL以终止列表。我知道标准链表的东西,但它很重要,因此提到了。

祝你好运。

答案 3 :(得分:1)

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

答案 4 :(得分:0)

删除currP; currP = prevP;

这导致分段错误,在第一次迭代时,prevP为null,因此如果在迭代情况下执行prevP不是Null。