我是C ++编码员。最近开始使用Python。我正在看一下Python中的简单链接列表实现。我在这里有点困惑。不仅在这里,而且在树实现等等同样的问题。
class Element包含指向下一个节点的数据和指针。完美没问题。但是在LinkedList类中,我可以看到self.tail.next = e,现在next是Element类的变量,即使它是公共的,而且Element类的对象也必须访问它。在这里我们如何编写类似self.tail.next = e的东西,因为tail只是LinkedList类的变量而不是Element类的对象。我很困惑。
class Element:
def __init__(self,x):
self.data=x
self.next=None
class LinkedList:
def __init__(self):
self.head=None
self.tail=None
def append(self,x):
# create a new Element
e = Element(x)
# special case: list is empty
if self.head==None:
self.head=e
self.tail=e
else:
# keep head the same
self.tail.next=e
self.tail=e
答案 0 :(得分:4)
Python使用引用。一切都始终通过引用传递,值始终通过引用共享(除非明确复制)。
分配对象意味着分配对该对象的引用。这种方式self.tail.next = e
意味着:self.tail期望引用Element类的对象。该对象具有.next属性。 self.tail.next = e
表示非空列表的最后一个元素将指向刚刚附加的新元素。然后self.tail = e
表示对最后一个元素的引用被移动到刚刚追加的最后一个元素。
Python中的任何变量都只是具有给定名称的引用变量。它会自动解除引用。因此,熟悉经典编译语言(如C ++)的人可能看起来很奇怪。
我不确定您是否可以在不创建帐户的情况下在Expert Exchange上显示文章。如果是,请查看http://www.experts-exchange.com/Programming/Languages/Scripting/Python/A_6589-Python-basics-illustrated-part-2.html,然后查看解释问题的图片的http://www.experts-exchange.com/Programming/Languages/Scripting/Python/A_7109-Python-basics-illustrated-part-3.html。
答案 1 :(得分:1)
初始化self.tail的唯一地方是附加,并在那里将其设置为等于e。稍高于e = Element(x)
,因此e 是Element类型的对象。请注意,在您调用self.tail.next=e
时,您知道head不是none,因此tail也不是None,而是Element的实例。
希望这有帮助。
答案 2 :(得分:1)
您写道:
现在接下来是Element类的变量,即使它是公共的,而且Element类的对象也必须访问它。
那里有一个误解。公共成员(即除了以两个下划线开头的成员之外的所有成员)都可以从任何地方访问,而不仅仅是从同一类的方法中访问。
答案 3 :(得分:0)
next
和tail
元素,这就是原因。对于任何语言的链表,包括C或C ++,都是如此。 链接列表是使用指针/引用链接在一起的元素列表。
遍历列表时,这些链接用于从节点(元素)到节点。如果他们提到其他链接列表就没有意义了,不是吗?列表中的第一个元素是head
,最后一个元素是tail
,节点中指向的next
元素是列表中的元素{{1 } node是它之前的元素。
答案 4 :(得分:0)
在python中,一切都是参考。
请:将列表实现与您的(应用程序)数据分开。
与在C ++中一样,封装访问方法是一种很好的方式 - 但是因为实例字段没有访问限制,所以可以从任何地方访问它们。
一个通用双链表的想法(这只是一个应该加强的骨架 - 但我希望它能传达这个想法)。
class DoubleLinkedList(object):
class ListNode(object):
def __init__(self):
self.__next = None
self.__prev = None
def next(self):
return self.__next
def prev(self):
return self.__prev
def set_next(self, next_node):
self.__next = next_node
def set_prev(self, prev_node):
self.__prev = prev_node
def is_last(self):
return self.next()==None
def __init__(self):
'''Sets up an empty linked list.'''
self.__head = DoubleLinkedList.ListNode()
self.__tail = DoubleLinkedList.ListNode()
self.__head.set_next(self.__tail)
self.__tail.set_prev(self.__head)
def first(self):
return self.__head.next()
def last(self):
return self.__tail.prev()
def append(self, list_node):
list_node.set_next(self.__tail)
list_node.set_prev(self.__tail.prev())
self.__tail.set_prev(list_node)
list_node.prev().set_next(list_node)
########################################
class MyData(DoubleLinkedList.ListNode):
def __init__(self, d):
DoubleLinkedList.ListNode.__init__(self)
self.__data = d
def get_data(self):
return self.__data
ll = DoubleLinkedList()
md1 = MyData(1)
md2 = MyData(2)
md3 = MyData(3)
ll.append(md1)
ll.append(md2)
ll.append(md3)
node = ll.first()
while not node.is_last():
print("Data [%s]" % node.get_data())
node = node.next()