【问题标题】:Circular linked list code is getting into infinite loop循环链表代码进入无限循环
【发布时间】:2018-04-01 05:39:13
【问题描述】:

我是这样定义循环链表的。

class Link(object):
    def __init__ (self, data, next = None):
        self.data = data
        self.next = next


class CircularList(object):

    def __init__ ( self ):
        self.first = Link(None, None)
        self.first.next = self.first

    def insert_first ( self, item ):
        new_link = Link(item)
        new_link.next = self.first
        self.first = new_link

    def __iter__(self):
        current = self.first
        first = current
        while current.next != first:
            yield current
            current = current.next

    def __str__(self):
        return str([Link.data for Link in self])

    def __repr__(self):
        return self.__str__()

然后我将项目插入到我的列表中

a = CircularList()
a.insert_first(4)
a.insert_first(5)

我想要一个我的循环列表的字符串表示,但看起来__iter__() 正在无限循环。我可以正确定义我的迭代器,并获得正确的字符串表示吗?

【问题讨论】:

  • __iter__中的first = current替换为first = self.first是否有效?
  • @ndmeiri 不,它不起作用
  • 您的insert_first 方法不正确——您没有正确更新指针。我建议采取一些样本案例,在纸上追踪它们并验证它确实不起作用。
  • @juanpa.arrivillaga 对不起,我对面向对象编程真的很陌生,无法理解你在说什么......

标签: python oop linked-list iterator circular-list


【解决方案1】:

我会分解步骤。

首先,我将Link 重命名为Node

class Node(object):
    def __init__(self, data, next=None):
        self.data = data
        self.next = next

链接与节点不同 - 节点用于保存您的数据,链接将两个节点连接在一起。

接下来,CircularList 类需要进行一些更改。

__init__ 需要初始化一个 empty 列表。这意味着根本没有节点。为方便起见,我将self.last 定义为非常 简化代码(注意,非常,否则您将遇到困难)。

class CircularList(object):
    def __init__(self):
        self.first = self.last = None

对于insert_first,您需要注意列表为空时的极端情况和一般情况。相应地更新self.firstself.last

def insert_first(self, item):
    if self.first is None:
        self.first = self.last = Node(item)
        self.first.next = self.first
    else:
        self.first = Node(item, self.first)
        self.last.next = self.first

您的__iter__ 方法也应该以实物形式回应。内嵌评论。

def __iter__(self):
    # corner case - yield empty list
    if not self.first:
        yield []
    else:
        # start by yielding the head node
        yield self.first
        cur = self.first.next
        # iterate as long as you do not see the head node again 
        while cur is not self.first:
            yield cur
            cur = cur.next

其他方法保持不变。测试代码:

a = CircularList()
for i in [5, 4, 3, 2, 1]:
    a.insert_first(i)

print(a)
[1, 2, 3, 4, 5]

完整代码清单

class Node(object):
    def __init__(self, data, next=None):
        self.data = data
        self.next = next

class CircularList(object):
    def __init__(self):
        self.first = self.last = None

    def insert_first(self, item):
        if self.first is None:
            self.first = self.last = Node(item)
            self.first.next = self.first    
        else:
            self.first = Node(item, self.first)
            self.last.next = self.first

    def __iter__(self):
        if not self.first:
            yield []
        else:
            yield self.first
            cur = self.first.next
            while cur is not self.first:
                yield cur
                cur = cur.next

    def __str__(self):
        return str([Link.data for Link in self])

    def __repr__(self):
        return self.__str__()

【讨论】:

  • 你是最棒的
  • @EricKim 我希望这个答案能教会你一些东西。祝你好运!
  • 嘿,你的代码工作得很好,但是对于 insert_first(),如果我把 self.first = Link(item), self.last = Link(item),由于某种原因它不起作用. (它似乎无限迭代)。你在一行上做了 self.first = self.last = Link(item) ,但我试着用两行做,然后它不起作用。你知道为什么吗?
  • @EricKim 诀窍在于 self.first 和 self.last 需要指向完全相同的对象,否则 cur is not self.first 上的代码会失败,因为 is 会检查身份对象(AKA,id,它们与您的更改不同)。
  • 哦,这是有道理的。谢谢!!
猜你喜欢
  • 2013-12-30
  • 2014-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-19
  • 1970-01-01
  • 2013-03-19
相关资源
最近更新 更多