我有一个指向节点的指针,我想从链表中删除这个特定的节点。下面的逻辑工作得很好,但是如果要删除的节点是最后一个节点,它就会失败。如何删除最后一个节点?
void deleteNodWhosePointerIsGivene(node *pointerNode)
{
node *temp=pointerNode->next;
pointerNode->id=temp->id;
pointerNode->next=temp->next;
free(temp);
}
首先,您不是从列表中删除pointerNode
,而是删除列表中的下一个节点。其次,您没有检查是否有下一个节点。
想想你在做什么。
您正在尝试删除列表中的下一个对象。
您位于列表的末尾,因此temp指针将为空。
你试图从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
传入一个值为"3"的pointerNode。然后,您的代码执行以下操作:
1)将pointerNode->赋值到temp的旁边,即"4"
2) pointerNode->Next将被分配temp->Next即。"5"
3) temp被释放,即"4"
那么在这之后的列表就是1->2->3->5。
当你到达节点"5"时就会出现访问冲突
1) pointerNode->next被赋值给temp,即NULL
2) pointerNode->Next将被赋值为temp->Next,即当您引用NULL指针时访问冲突。
一个双重链表将是一个更好的解决方案,因为删除pointerNode你需要改变前一个节点的Next指针。否则,您必须首先扫描列表,以便在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;
}
否则,您需要有对List的First Node的引用,并搜索前面的