【问题标题】:What is the easiest way to turn a LinkedList class into a Circular Linked List class?将 LinkedList 类转换为 Circular Linked List 类的最简单方法是什么?
【发布时间】:2018-10-03 19:42:24
【问题描述】:

我有一个包含近 200 行代码的 LinkedList 类。我想通过始终确保任何myLL.tail.next is myLL.head 来创建一个新的class LLCircular(LinkedList)。我相信我需要相应地更新append()push()remove() 等。有没有办法让原始的 LinkedList 类保持完整?也许是一个装饰器或一些笨拙的方法?

为简洁起见,如果阅读代码,我的push() 方法与append() 正好相反。我还有一个 pop()remove() 方法,如果我只是重写这些方法,就需要更新它们。由于我试图避免这种方法,因此我没有发布那部分代码。

class LinkedListNode:
   def __init__(self, value, nextNode=None, prevNode=None):
      self.value  = value
      self.next   = nextNode
      self.prev   = prevNode
   def __str__(self):
      return str(self.value)

class LinkedList:
   def __init__(self, values=None):
      self.head   = None
      self.tail   = None
      if values is not None:
         self.append(values)
   def __str__(self):
      values = [str(x) for x in self]
      return ' -> '.join(values)
   def append(self, value=None):
      if value is None:
         raise ValueError('ERROR: LinkedList.py: append() `value` PARAMETER MISSING')
      if isinstance(value, list):
         for v in value:
            self.append(v)
         return
      elif self.head is None:
         self.head   = LinkedListNode(value)
         self.tail   = self.head
      else:
         ''' We have existing nodes  '''
         ''' Head.next is same '''
         ''' Tail is new node '''
         self.tail.next = LinkedListNode(value, None, self.tail)
         self.tail      = self.tail.next
         if self.head.next is None:
            self.head.next = self.tail.prev
      return self.tail

'''class LLCircular(LinkedList):'''
    ''' ??? '''

测试代码:

foo = LinkedList([1,2,3])
foo.tail.next = foo.head #My LL is now circular
cur = foo.head
i = 0
while cur:
   print(cur)
   cur = cur.next
   i +=1
   if i>9:
      break

【问题讨论】:

    标签: python python-3.x linked-list


    【解决方案1】:

    您想要的是使用super 关键字调用您的LinkedList 基类函数,然后对LLCircular 类函数进行轻微修改,即:

    class LLCircular(LinkedList):
        def append(self, value=None):
            super(LLCircular, self).append(value)
            # In addition to having called the LinkedList append, now you want
            # to make sure the tail is pointing at the head
            self.tail.next = self.head
            self.head.prev = self.tail
    

    【讨论】:

    • 我做Android/Java开发已经有4个月了,我很震惊我之前没有想到这个::joy::谢谢!
    • __init__ 不需要被覆盖,如果它所做的只是调用链更高的__init__
    • 不应该把self.head.prev的山雀也设置在新的尾巴上吗?
    • @T.Woody 是的,这取决于您的列表是否应该是“双重链接”,如果您只在一个方向上遍历,则不需要它。
    • 请注意,您可能需要更新self.tail.nextself.head.prev 的唯一原因是将节点添加到空列表中; LinkedList.append 不会破坏现有的循环链表。在实现中使用适当的“虚拟”节点,以便即使是“空”列表也包含某些内容,甚至可以摆脱这种特殊情况。
    【解决方案2】:

    如果它是“圆形”的,它就不需要尾巴或头,对吗? “追加”也没有意义——insert_after 和 insert_before 方法就足够了——此外,任何节点都是对完整循环列表的引用,不需要不同的对象:

    class Circular:
        def __init__(self, value=None):
            self.value = value
            self.next = self
            self.previous = self
        def insert_after(self, value):
            node = Circular(value)
            node.next = self.next
            node.previous = self
            self.next.previous = node
            self.next = node
        def insert_before(self, value):
            node = Circular(value)
            node.next = self
            node.previous = self.previous
            self.previous.next = node
            self.previous = node
        def del_next(self):
            self.next = self.next.next
            self.next.previous = self
        def __iter__(self):
            cursor = self.next
            yield self
            while cursor != self:
                 yield cursor
                 cursor = cursor.next
        def __len__(self):
            return sum(1 for _ in self)
    

    【讨论】:

    • 感谢您的回答;谢谢你。我应该更具体地想用现有的 LinkedList 类使它成为一个循环列表,以避免编写一个完整的新类。
    • 如果你喜欢它,你可能会支持它,并保持另一个被接受。
    猜你喜欢
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    • 2014-05-09
    • 1970-01-01
    • 2012-02-05
    • 2012-01-07
    • 2020-01-16
    相关资源
    最近更新 更多