给定一个指向节点的指针,删除该特定节点

Given A pointer to a node, Delete that particular node

本文关键字:节点 指针 删除 一个      更新时间:2023-10-16

我有一个指向节点的指针,我想从链表中删除这个特定的节点。下面的逻辑工作得很好,但是如果要删除的节点是最后一个节点,它就会失败。如何删除最后一个节点?

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的引用,并搜索前面的