【问题标题】:Given A pointer to a node, Delete that particular node给定一个指向节点的指针,删除该特定节点
【发布时间】:2011-10-31 09:54:57
【问题描述】:

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

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

【问题讨论】:

    标签: c++ linked-list


    【解决方案1】:

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

    【讨论】:

    • 假设列表为 1--->2--->3--->4---->5。我想删除包含数据“3”的节点。我的逻辑将复制数据“4”代替数据“3”并删除给定指针的下一个节点。
    • @aj983:您可能应该改写函数名称,因为您实际上并没有删除“给定”节点。但是如果给定的节点在列表的末尾,你遇到的问题是它失败了,你应该考虑一下pointerNode->next是NULL,当你访问NULL-pointers时会发生什么。
    • 这就是我的想法。如果我将逻辑修改为 if(pointerNode->next!= NULL) { node *temp=pointerNode->next;指针节点->id=temp->id;指针节点->下一个=临时->下一个;免费(临时); } 然后在我的 else 条件下,我应该处理我的最后一个节点删除条件。如何处理。
    • 根据您的设计,您必须找到倒数第二个节点,并在该节点上调用deleteNodWhosePointerIsGivene。
    • 这个设计本质上是有缺陷的:因为它释放了next 节点,它不可能删除最后一个节点。最后一个节点没有next 节点。这是一个单链表,所以你不能退后一步。
    【解决方案2】:

    想想你想要做什么。

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

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

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

    通常我会做一些类似的事情。

    DeleteObject(*obj)
     Get Next Object
     Get Prev Object
     Set Prev->next = Next 
     Set Next->prev = Prev
     Delete obj;
    

    如果我理解你上面的 cmets 你想要复制,那么你的代码应该是这样的。

     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"
    

    如果要删除列表中的最后一个对象,则无法将指针设置在列表中倒数第二个对象中。做到这一点的唯一方法是使用双链表,或者遍历列表以查找要删除的指针并跟踪列表中的最后一个对象。

    【讨论】:

    • 如果我们只有一个指向要删除的节点的指针,那么我们可以得到前一个节点的引用。
    • 我正在尝试在单链接列表中实现。我认为您的逻辑适用于双向链表。
    • 很公平。但是然后考虑每个阶段的对象和指针值,并弄清楚它什么时候会为空。在一张纸上绘制操作以帮助可视化这些步骤。这是我辅导大学生时让学生做的事情。
    • 抱歉无法理解..我再次认为代码中存在一些问题。
    • 想一想,您不能删除当前对象,如果您尝试删除最后一个对象,则必须执行 deleteNextObject 引发异常。或者使用双链表。
    【解决方案3】:

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

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

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

    你传入一个“3”的指针节点。然后您的代码执行以下操作:

    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 指针时访问冲突。

    双向链表将是一个更好的解决方案,因为删除指针节点需要更改前一个节点的 Next 指针。否则你必须先扫描列表才能找到pointerNode之前的节点。

    【讨论】:

      【解决方案4】:

      这是适用于单向链表的代码。请记住,对于大型列表,这将非常慢,我会支持 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);
      }
      

      【讨论】:

        【解决方案5】:

        如果您确实需要删除与您拥有指针的节点关联的项目,那么当涉及到最后一个节点时,您有两种选择:

        • 从列表的开头迭代找到它的前任(倒数第二个节点),删除最后一个节点并将其前任的next设置为NULL。

        • 采取惰性方法 - 不要实际删除节点,仅将其标记为死节点(例如,通过将其数据设置为不可能的值。)稍后从前一个节点到达它时将其删除(然后也是 NULL- ing 前任的next)。

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

        【讨论】:

          【解决方案6】:

          如果您能够引用前一个节点。

          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;
          }
          

          否则,您将需要引用列表的第一个节点,然后搜索前一个。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-03-10
            • 1970-01-01
            • 2021-02-19
            • 2018-04-07
            • 1970-01-01
            • 1970-01-01
            • 2013-06-15
            • 2019-04-19
            相关资源
            最近更新 更多