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);
}
如果确实需要删除与指针所在节点关联的项,那么在最后一个节点上有两个选项:
- 从列表开始迭代以查找其前置节点(从下到最后的节点),删除最后一个节点并将其前置节点的
设置为NULLnext
- 采用延迟方法-不要实际删除节点,只将其标记为死节点(例如,通过将其数据设置为不可能的值)。稍后从前置节点访问时将其删除(然后也将前置节点的
设置为空)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,如果您尝试删除最后一个对象,则会引发异常。或者使用双链接列表。