如何使用OOP实现链表?

时间:2018-12-24 18:35:12

标签: python oop linked-list

我正在尝试使用OOP和私有变量来实现链表。但是,当我调用'str' object has no attribute 'get_data'类的display方法时,会得到 LinkedList 。另外,我觉得add方法也不正确。

当我在self.__head中打印self.__tailadd()时,代码从不输入else部分,而是输出:

Sugar Sugar
Milk Milk
Tea Tea
Biscuit Biscuit

下面是我的代码:

class LinkedList:
    def __init__(self):
        self.__head=None
        self.__tail=None

    def get_head(self):
        return self.__head

    def get_tail(self):
        return self.__tail

    def add(self,data): # Skeptical about it

        if self.__tail is None:
            self.__head=Node(data).get_data()
            self.__tail = self.__head
            print(self.__head,self.__tail)
        else:
            b=Node(data)
            self.__tail= b.get_data()
            self.__head = self.__tail
            b.set_next(self.__tail)
            self.__tail = b.get_next()

            print(self.__head,self.__tail)


    def display(self): # Gives the error

        temp = self.__head
        msg = []
        c = Node(temp)
        while (temp is not None):
            print(temp.get_data())

            msg.append(str(temp.get_data()))

            temp = temp.get_next()

        msg = ''.join(msg)
        print(msg)

class Node:
    def __init__(self,data):
        self.__data=data
        self.__next=None

    def get_data(self):
        return self.__data

    def set_data(self,data):
        self.__data=data

    def get_next(self):
        return self.__next

    def set_next(self,next_node):
        self.__next=next_node


list1=LinkedList()
list1.add("Sugar")

#print(list1.get_head())
#print("Element added successfully")

list1.add("Milk")
list1.add("Tea")
list1.add("Biscuits")
list1.display()

3 个答案:

答案 0 :(得分:1)

这似乎令人怀疑:

self.__head = Node(data).get_data()

考虑到您甚至不再引用该节点...然后尝试调用Node对象的方法。即使那样,您的实现仍然是错误的。

我确定还有其他问题,但是您可以在Google上进行搜索或实际执行自己的项目/作业。

答案 1 :(得分:0)

因此,我已经解决了我的问题。谢谢大家的帮助。我仍然不清楚:

与Java之类的语言相比,我知道python在默认情况下不带有私有变量,但是我相信python是关于遵守约定的,并且'__'是告诉其他开发人员该特定实体是私有的约定。

但是,在我的情况下,由于使用私有变量时名称解析为 _Classnmae__attribute_name ,因此我无法直接从LinkedList类访问Node类的数据和下一个属性,反之亦然。因此,更好的解决方案是使用getter和setter,因为这是它们的共同点。

def add(self,data):
    #Remove pass and write the logic to add an element
    new_node = Node(data)
    if self.__head is None:
        self.__head = self.__tail = new_node
    else:
        self.__tail.set_next(new_node)
        self.__tail = new_node

def display(self):
    #Remove pass and write the logic to display the elements
    temp = self.__head       
    msg = []
    c = Node(temp)
    while (temp is not None):
        msg.append(str(temp.get_data()))
        temp = temp.get_next()
    msg = ' '.join(msg)
    print(msg)
  

算法

     

添加(数据)

     
      
  1. 使用数据创建新节点

  2.   
  3. 如果链接列表为空(头节点未引用任何其他节点),   使头节点和尾节点引用新节点

  4.   
  5. 否则,

         

    a。使尾节点的链接引用新节点

         

    b。将新节点称为尾节点

  6.   

答案 2 :(得分:0)

这是一种通过使用一些我所知道的单链接列表实现“技巧”来更简洁地实现此目的的方法。

一个链表总是由至少一个 sentinel 节点组成,该节点自动创建并存储在实例属性self._tail中。拥有它有很多好处。

  1. 知道tail的位置可以快速简便地添加内容。
  2. 列表永远不会为空,因此不需要检查特殊情况。这样做有一个很好的副作用,那就是遍历列表的元素只需要跟随self._next直到它成为前哨节点(一个条件表达式)即可。

另一个“技巧”是在当前前哨节点之前 处添加新的最后一个元素时-在单链列表中听起来很慢,因为它似乎需要修改{{1 }}添加到其中一个。为了达到这样做的效果,但实际上却避免这样做,它要做的就是将现有前哨节点变成新的Node所包含的内容,并使其成为Node属性是它创建的新标记,以替换之前要重用的标记。

这如何帮助理解以下代码中发生的事情:

_next

输出:

class LinkedList:
    def __init__(self):
        self._tail = Node()
        self._head = self._tail

    def add(self, data):
        """ Add an item to the end of the linked list. """
        new_tail = Node()
        self._tail.set_data(data)  # Convert existing tail into a data node.
        self._tail.set_next(new_tail)
        self._tail = new_tail

        print('adding:', data)

    def display(self):
        """ Traverse linked list and print data associated with each Node. """
        print('\nLinked list contents:')
        curr = self._head
        while curr is not self._tail:
            print('  ' + curr.get_data())
            curr = curr.get_next()


class Node:
    def __init__(self, data=None):
        self._data = data
        self._next = None

    def get_data(self):
        return self._data

    def set_data(self, data):
        self._data = data

    def get_next(self):
        return self._next

    def set_next(self, next_node):
        self._next = next_node


if __name__ == '__main__':
    list1 = LinkedList()

    list1.add("Sugar")
    list1.add("Milk")
    list1.add("Tea")
    list1.add("Biscuits")

    list1.display()