【问题标题】:Deleting in a linked list在链表中删除
【发布时间】:2010-12-08 12:38:15
【问题描述】:

仅给定一个指向要删除节点的指针,我们如何删除链表中的节点...?

【问题讨论】:

  • 单链表?双向链表?
  • 如果是单链表则重复:stackoverflow.com/questions/1960562/… 如果是双链表...不值得在面试中问:)
  • 此外,如果列表的对象很大(即非平凡的或只是昂贵的复制构造函数),则该副本的解决方案是一个丑陋的 hack。请参阅 codaddict 的帖子。不切实际的面试问题是不切实际的。 :)

标签: c++ c


【解决方案1】:

这个问题太模棱两可了,很可能是出于某种原因(例如,引发对话而不是测试您对数据结构的实际知识)。他们可能希望你问“这是一个双向链表还是一个单链表?”如果是双向链表,就很简单了:

curr->prev->next = curr->next;
curr->next->prev = curr->prev;
delete curr;

如果是单链表,必须要有头节点,这样才能在链表中找到前一个节点。因此,他们可能希望您询问您是否有指向头节点的指针。伪代码将是:

loop from head to end until test->next == curr
test->next = curr->next;
delete curr;

或者,如果您可以修改列表(不带头节点):

temp = curr->next;
curr->data = temp->data;
curr->next = temp->next;
delete temp;

【讨论】:

    【解决方案2】:

    好吧,这只是个把戏。

    假设curr是给定的地址,下面是伪代码:

    to_delete = curr->next
    curr->data = to_delete->data
    curr->next = to_delete->next
    delete to_delete
    

    本质上这只是将列表中下一个节点的数据和下一个指针复制到当前节点并删除下一个节点。

    【讨论】:

    • 听起来 OP 想要删除 curr,而不是 curr->next。否则,问题太容易了。 ;)
    • 同样的技巧可以用来在当前节点之前插入,在它之后插入一个节点然后交换数据;但是,如果其他人持有指向该节点的指针、该节点已被删除或其数据已更改,则此方法会出现问题!
    • 我自己也遇到过这个问题,我相信他实际上打算删除值而不是节点本身:)(至少这是我的期望)。
    【解决方案3】:

    如果您没有指向列表头的指针,我认为在单链表中几乎是不可能的。你应该总是有一个链表头指针。

    【讨论】:

    • 好的,在 codaddict 在对该问题的评论中给出的线程中,如果您将其作为参数给出,则可以删除节点。
    • 虽然你应该有头指针,但如果没有它,从单链表中删除一个项目并非不可能(尽管从技术上讲,你会将下一个项目复制到当前项目并删除下一个项目)。对于双向链表,删除没有头或尾指针是微不足道的。
    • 这就是为什么我写了几乎不可能的评论。正如您所注意到的,这种方法并不是真正删除节点。如果您在其他地方有指向您“删除”的节点旁边的节点的指针,那么当您尝试对其进行操作时,您将遇到分段错误。我不能接受。
    【解决方案4】:

    在标准链表实现中,您必须修改指向被删除节点的节点。要修改它,你必须先找到它。如果你有一个指向列表头的指针,或者在被删除之前的任何元素,你可以通过遍历列表找到它。如果没有,这个问题没有通用的解决方案。

    您可以通过修改链表的定义以某种方式标记已删除的节点(例如,使用布尔属性deleted)来摆脱这种情况,然后修改列表遍历以跳过此类节点。

    【讨论】:

      【解决方案5】:
      You have a pointer to that node (say, node N). Meaning, you have access on that node.
      If that node has pointer to it's front node and it's back node, then simply point the back node to the front node. And the front node to the back of your node N.
      
      To illustrate: 
      step 1:
      ---> [ node ] ---> [ node ] ---> [ node ] ---> 
      <--- [  M   ] <--- [  N   ] <--- [  O   ] <--- etc...
      
      step 2:
      ---> [ node ] -----------------> [ node ] ---> 
      <--- [  M   ] <--- [node N] <--- [  O   ] <--- etc...
      
      step 3:
      ---> [ node ] -----------------> [ node ] ---> 
      <--- [  M   ] <----------------- [  O   ] <--- etc...
      
                                          [ node ] ---> (still points to node O)
            (still points to node M) <--- [  N   ]
      
      step 4:
      just point Node N to NULL
                                          [ node ] ---> NULL
                                NULL <--- [  N   ]
      
      result:
      ---> [ node ] -----------------> [ node ] ---> 
      <--- [  M   ] <----------------- [  O   ] <--- etc...
      

      【讨论】:

        【解决方案6】:

        如果这不是尾巴,我有一个解决方案。

        如果它是一个单链表,您只需与您旁边的节点“交换”并删除该节点即可。

        假设我有

        struct Node
        {
          T value;
           Node * next;
        };
        

        解决方案类似于:

        void freeNode( Node * node )
        {
           Node * next = node->next;
           if( next )
           {
              node->value = next->value;
              node->next = next->next;
              free( next ); 
           }
           // else I'm stuck!
        }
        

        上述 C 和 C++ 的伪混合。

        如果我们拥有的节点是尾部,假设尾部由node->next == NULL表示,我无法将前一个节点变成尾部,所以我无法求解。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-06
          • 2013-11-22
          • 1970-01-01
          • 1970-01-01
          • 2021-06-07
          相关资源
          最近更新 更多