【问题标题】:Removing the lastNode in a singly Linked List删除单链表中的 lastNode
【发布时间】:2016-07-30 14:00:21
【问题描述】:

我可以检查一下吗 我们如何从单个链表中删除最后一个节点?

和我们移除第一个节点的方式一样吗?

删除第一个节点

def deleteAtHead(self):
    temp = self.head
    self.head = self.head.next
    delete temp

删除最后一个节点

def deleteAtTail(self):
    prev = None
    temp = self.tail
    self.tail= self.tail.prev 
    delete temp

【问题讨论】:

    标签: python singly-linked-list


    【解决方案1】:

    因为这是一个单链表,您必须遍历该列表才能到达尾部之前的节点。我认为你的功能只需要是

    def deleteAtTail(self):
         temp = self.head
         while(temp.next != None):
             if temp.next == tail: #finds the node just before tail
                 break
             temp = temp.next
         temp.next = None
         self.tail = temp
    

    我们设置self.tail = temp,因为 temp 等于列表末尾之前的节点。所以我们删除 temp(通过删除它的最后一个引用),然后将 tail 设置为我们之前确定为列表中倒数第二个节点的节点,因为它实际上是列表的新结尾。

    编辑:

    为了解决一些 cmets 对此答案的担忧。在处理单链表或双链表时,最好维护headtailcurrent 指针。知道 tail 的位置对于在列表中插入计算上合理的东西非常有价值。

    这意味着你的插入方法可以从这里开始:

    def insert(value):
        temp = self.head
        while(temp.next != None):
            temp = temp.next
        temp.next = Node()
        temp.next.value = value
    

    它的时间复杂度为 O(n):

    def insert(value):
        self.tail.next = Node()
        self.tail.next.value = value
        self.tail = self.tail.next
    

    它的时间复杂度明显更有利,为 O(1)。

    【讨论】:

    • 单链表中的节点只知道下一个,不知道上一个,
    • 天哪。我什至没有注意到它没有双重链接,因为 OP 在他的代码中使用了prev。我将编辑我的回复。
    • @ReblochonMasque 和 OP,我的示例已更新。
    • 它坏了,它也不知道它的尾巴……你必须找到它的尾巴!
    • 我可以理解这不是选定的答案,但任何人都可以提供一些指导,说明为什么我的答案被否决了吗?我所说的没有什么是错的,它只是 完全 OP 正在寻找什么。试图建立我的代表,这样的事情只会让我感到困惑。
    【解决方案2】:

    您不能在 O(n) = c 复杂度的单链表中执行删除操作,因为您没有前一个列表节点的参考。您将不得不遍历到列表的末尾,记住当前和以前的节点,然后您必须将前一个节点从引用中修剪到它的下一个节点,这是您尝试删除的最后一个节点。对于单链表,这将始终具有 O(n) = n 复杂度。

    【讨论】:

      【解决方案3】:

      你必须从头部开始爬回tail。 尾部是没有下一个的第一个节点:next is None。 跟踪倒数第二个 (prev),将其 next 设置为 None

      def deleteAtTail(self):   # remove_last would likely be a better name
          """ removes the last element of the singly linked list
          """
          temp = self.head
          while(temp.next is not None):
              prev  = temp
              temp = temp.next
          prev.next = None
      

      prev.next 设置为None 会删除尾节点(如果没有其他对它的引用,它将被垃圾收集)

      【讨论】:

      • 出于好奇,您为什么不只维护一个指向列表末尾的指针?如果列表很长并且额外指针的成本非常低,那么每次从头遍历到末尾是非常昂贵的。
      • 我同意你的看法,但这不是 OP 所要求的 - 它也不是简单的单链表 API 提供的。
      • 我的意思是....他在他的代码中使用了变量self.tail。我认为假设 OP 正在维护指向列表尾部的指针是合理的,因为这将是明智的做法。我想我也想知道谁对我的答案投了反对票,哈哈。你的意思是“裸骨单链表 ADT”吗?
      • 不,你不应该需要一个(双向链表维护以前的指针,而不是单独的)
      猜你喜欢
      • 2017-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多