C++ 给定指向节点的指针,删除该特定节点

C++ 给定指向节点的指针,删除该特定节点,c++,linked-list,C++,Linked List,我有一个指向某个节点的指针,我想从链表中删除那个特定的节点。 下面的逻辑工作正常,但如果要删除的节点是最后一个节点,则会失败。 如何删除最后一个节点 void deleteNodWhosePointerIsGivene(node *pointerNode) { node *temp=pointerNode->next; pointerNode->id=temp->id; pointerNode->next=temp->next; free(temp)

我有一个指向某个节点的指针,我想从链表中删除那个特定的节点。 下面的逻辑工作正常,但如果要删除的节点是最后一个节点,则会失败。 如何删除最后一个节点

void deleteNodWhosePointerIsGivene(node *pointerNode)
{
  node *temp=pointerNode->next;
  pointerNode->id=temp->id;
  pointerNode->next=temp->next;
  free(temp);
}

首先,不是从列表中删除
pointerNode
,而是删除列表中的下一个节点。其次,您没有检查是否有下一个节点。

想想您想做什么

您正在尝试删除列表中的下一个对象

您位于列表的末尾,因此临时指针将为空

然后,您将尝试从null获取下一个,并尝试释放null

通常情况下,我会做一些类似的事情

DeleteObject(*obj)
 Get Next Object
 Get Prev Object
 Set Prev->next = Next 
 Set Next->prev = Prev
 Delete obj;
如果我理解你上面的评论,你想做一个副本,那么你的代码应该是这样的

 DeleteObject
 Get Next Object
 if (Next Object is not null)
    This.Id == Next.Id
    Free Next
 else 
    Throw exception "Cannot delete last object in list"

如果要删除列表中的最后一个对象,则无法在列表中倒数第二个对象中设置指针。执行此操作的唯一方法是使用双链接列表,或在列表中迭代查找要删除的指针,并跟踪列表中的最后一个对象。

您不是在代码中删除pointerNode,而是在删除pointerNode->next

看看您的单链表示例。假设我们有:

1->2->3->4->5

您传入一个pointerNode“3”。然后,您的代码执行以下操作:

1) 将pointerNode->分配到temp旁边,即“4”

2) pointerNode->Next将被指定为temp->Next,即“5”

3) 释放温度,即“4”

因此,在此之后的列表将是1->2->3->5

当您到达节点“5”时,您将获得访问冲突

1) pointerNode->next被分配给临时值,即NULL

2) pointerNode->Next将被指定为temp->Next,即引用空指针时的访问冲突


对于删除pointerNode,双链接列表是一个更好的解决方案,您需要更改上一个节点的下一个指针。否则,您必须首先扫描列表,以找到pointerNode之前的节点。

以下是适用于单链表的代码。请记住,对于大型列表,这将非常缓慢,我支持Andrew Norman关于使用双链接列表的建议

无论如何。。来吧。为了使其正常工作,您需要传递列表的根节点,并注意如果您尝试删除它,该节点的地址可能会发生更改,因此我将其作为指向指针的指针传递

void DeleteNode (Node **rootNode,Node *pointerNode)
{
    Node *prevNode;

    if (pointerNode == *rootNode) {

       // Head node is being removed

       *rootNode = pointerNode->Next;

    } else {

       // Find the previous node

       for (prevNode = *rootNode; prevNode->Next != pointerNode;
            prevNode = prevNode->Next) ;

       prevNode->Next = pointerNode->Next;
    }

    // Free the node

    free (pointerNode);
}

如果确实需要删除与指针所在节点关联的项,那么在最后一个节点上有两个选项:

  • 从列表开始迭代以查找其前置节点(从下到最后的节点),删除最后一个节点并将其前置节点的
    next
    设置为NULL

  • 采用延迟方法-不要实际删除节点,只将其标记为死节点(例如,通过将其数据设置为不可能的值)。稍后从前置节点访问时将其删除(然后也将前置节点的
    next
    设置为空)


这两种方法都有明显的缺点。这就是为什么从链表中删除节点时最好始终使用前置节点。

如果您能够引用上一个节点

void deleteNodWhosePointerIsGivene(structNode* pCurrentNode, structNode* pPreviousNode)
{
    // Not the Last Node ?
    if(pCurrentNode->pNext) 
        pPreviousNode->pNext = pCurrentNode->pNext);                    
    else
        pPreviousNode->pNext = NULL;

    delete pCurrentNode;
    pCurrentNode = NULL;
}

否则,您将需要对列表的第一个节点进行引用,并搜索前一个节点。

假设列表为1-->2-->3-->4-->5。我想删除包含数据“3”的节点。我的逻辑将复制数据“4”而不是数据“3”,并删除给定指针的下一个节点。@aj983:您可能应该重新表述函数名,因为您实际上没有删除“给定”节点。但是如果给定的节点位于列表的末尾,那么您应该考虑
pointerNode->next
NULL
,以及当您访问
NULL
指针时会发生什么。这就是我的想法。如果我将逻辑修改为(pointerNode->next!=NULL){node*temp=pointerNode->next;pointerNode->id=temp->id;pointerNode->next=temp->next;free(temp);}然后在else条件下,我应该处理最后一个节点删除条件。如何处理。根据您的设计,您必须找到倒数第二个节点,并在该节点上调用
deleteNodeWhosepointerisgive
。该设计本质上存在缺陷:因为它释放了
next
节点,所以不可能删除最后一个节点。最后一个节点没有
next
节点。这是一个单链表,所以你不能后退。如果我们只有一个指向要删除的节点的指针,那么我们可以得到上一个节点引用。我正在尝试在单链表中实现。我认为你的逻辑是双重链表,这很公平。然后考虑每个阶段的对象和指针值,并确定它何时为空。在一张纸上绘制操作,以帮助可视化步骤。这是我在辅导大学生时让学生们做的。很抱歉,无法理解。我再次思考代码中存在的一些问题。考虑到这一点,您无法删除当前对象,您必须执行deleteNextObject,如果您尝试删除最后一个对象,则会引发异常。或者使用双链接列表。