【问题标题】:How to implement linked list using OOP?如何使用 OOP 实现链表?
【发布时间】:2018-12-24 18:35:12
【问题描述】:

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

当我在add() 中打印self.__headself.__tail 时,代码永远不会进入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()

【问题讨论】:

  • 撇开不必要的双下划线名称修改,以及非常不符合 Python 标准的 getter 和 setter 使用,我想说这段代码中发生了很多奇怪的事情。 self.__head=Node(data).get_data()有什么意义???为什么不只是更直接和等效的self.__head = data?但这可能根本不是你想要的......
  • python 中没有私有属性(您的属性也是私有的)。删除 getter 和 setter,只使用 self.dataself.next
  • 因为数据是节点类的私有变量。
  • 而__用于创建私有变量
  • 正如 Daniel 所说,Python 中没有私有的东西。即使您使用__尝试将事情设为私有,我也可以选择核选项并修复它,如果我真的想要访问。

标签: python oop linked-list


【解决方案1】:

这看起来很可疑:

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

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

我确定还有其他问题,但您可以用谷歌搜索或实际做自己的项目/家庭作业。

【讨论】:

    【解决方案2】:

    所以,我已经为我的问题找到了答案。谢谢大家的帮助。这个我还不是很清楚:

    我知道与 Java 等语言相比,默认情况下 python 不带有私有变量,但我相信 python 是关于尊重约定的,'__' 是告诉另一个开发人员这个特定实体是私有的约定。

    但是,在我的情况下,我无法直接访问来自 LinkedList 类的节点类的数据和下一个属性,反之亦然,因为在使用私有变量时名称被解析为 _Classnmae__attribute_name .因此,更好的解决方案是使用 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. 否则,

      一个。使尾节点的链接指向新节点

      b.将新节点称为尾节点

    【讨论】:

    • “但我相信 python 是关于尊重约定的,'__' 是告诉另一个开发人员这个特定实体是私有的约定。”不,约定适用于“私有”变量(API 的非公共部分)的单下划线。双下划线用于名称修改,以防止 子类 中的冲突。而且你不应该在 Python 中使用 getter 和 setter,尤其是如果它们所做的只是获取和设置一个值。相反,只需使用普通属性,如果您想控制访问,请使用property。阅读this
    【解决方案3】:

    这是一种通过使用我知道的几个单链表实现“技巧”来更简洁的方法。

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

    1. 知道tail 在哪里可以快速轻松地添加一些内容。
    2. 列表永远不会为空,因此不需要检查特殊情况。这样做的一个很好的副作用是,遍历列表的元素只需要跟随 self._next 直到它成为哨兵节点 - 单个条件表达式。

    另一个“技巧”是在当前标记节点之前添加一个新的最后一个元素——这在单链表中听起来很慢,因为它似乎需要修改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()
    

    输出:

    adding: Sugar
    adding: Milk
    adding: Tea
    adding: Biscuits
    
    Linked list contents:
      Sugar
      Milk
      Tea
      Biscuits
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多