2015-02-09 45 views
1

我有一个链接列表,我想实现为一个队列。我已经发现它的工作原理,但是我对这个特定部分的工作原理有疑问。下面是代码:Python与单尾链接列表

class LinkedQueue: 
    class _Node: 
     def __init__(self, element, next): 
      self._element = element 
      self._next = next 

    def __init__(self): 
     self._head = None 
     self._tail = None 
     self._size = 0 

    def enqueue(self, e): 
     newest = self._Node(e, None) 
     if self.is_empty(): 
      self._head = newest 
     else: 
      self._tail._next = newest 
     self._tail = newest 
     self._size += 1 

如果队列是空的,我入队,第一个条件在排队的真实,被触发,最新被分配到self._head。但是,当我添加另一个元素时,else块被触发,并且self._tail._next被分配最新。这显然会改变_head的_next变量。但是,分配第三个元素时,_head的_next变量不会更改。这是为什么?另外,不应该_tail被最新改变,并且因此_next变量被新分配的None覆盖。

该代码完全工作,我理解链表的逻辑,但我不明白为什么这个特定的代码工作。

回答

1

你问:

self._tail._next分配newest。这显然改变了_head的变量 _next

是的,因为当时_tail_head是同一个对象的两个名字。

所以当然分配给_tail._next具有完全按照分配给_head._next也有同样的效果 - 这怎么可能不是,因为_tail_head指的是相同的对象?

让我们来看看它们是如何引用同一个对象的!当if分支执行时,您执行self._head = newest;然后无条件地if/else你做self._tail = newest。在Python中,赋值始终是引用 - 赋值(对于名称[*])本身从不隐式地创建副本。

(作业到一个列表中的一个片段是一个非常不同的操作,因此这个迂回的括号 - 但现在让我们忘记它,因为你不处理片的任务:-)。

然而,分配的第三元件的情况下,对于_head_next变量不被改变。这是为什么?

因为在那个时候它没有任何更多的事实,_tail_head是同一对象两个名字:他们是那么的不同对象的名称。

那是因为你周围的第二次指派了不同的东西(newest)到self._tail - 但指派了什么新的self._head,因此这仍然是指以前的对象......这_tail不涉及任何更长的时间。

此外,不应该由_tailnewest被改变,并且这样的_next 变量由新分配的无覆盖?

self._tail确实重新绑定(“改变”是一个非常模糊的术语 - !)来指代相同的对象为newest,所以如果你在当时印刷self._tail._next(在enqueue方法的尽头)你确实将它看作None。但紧前分配self._tail._next影响当时什么简称self._tail_next属性self._tail=newest!) - 与新分配到self._tail立即成为倒数第一位在列表中的节点。

+0

啊,我明白了。我一直在使用C++,而我只注意到Python有不同的赋值规则(所有对象都是通过引用传递的)。我想这对于某些事情来说非常方便,但是对于其他人来说却很混乱。无论如何,非常感谢您的全力帮助! 对于其他人摆动,这里是一个链接,以帮助避免我的错误作为上述伟大反应的补充:http://robertheaton.com/2014/02/09/pythons-pass-by-object-reference-as -explained逐菲利普-K-迪克/ – cnxwelcomes 2015-02-09 01:37:28