【问题标题】:'NoneType' object has no attribute 'next' while merging two sorted Linked Lists in Python'NoneType' 对象在 Python 中合并两个排序的链表时没有属性'next'
【发布时间】:2020-10-21 19:24:20
【问题描述】:

我写了一个函数来在 Python 中合并两个排序的链表。这是代码:-

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


class LinkedList:
    def __init__(self):
        self.head = None

    def append(self, data):
        new_node = Node(data)
        if self.head is None:
            self.head = new_node
            return
        last_node = self.head
        while last_node.next is not None:
            last_node = last_node.next
        last_node.next = new_node
    
    def print(self):
        cur_node = self.head
        while cur_node.next is not None:
            print(cur_node.data, "-> ", end='')
            cur_node = cur_node.next
        print(cur_node.data)

def merge(l1, l2):
    cur_node1 = l1.head
    cur_node2 = l2.head
    l3 = LinkedList()
    while cur_node1.next is not None or cur_node2.next is not None:
        if cur_node1.data > cur_node2.data:
            l3.append(cur_node2.data)
            cur_node2 = cur_node2.next
        else:
            l3.append(cur_node1.data)
            cur_node1 = cur_node1.next
    if cur_node1.next is None:
        l3.append(cur_node1.data)
        while cur_node2.next is not None:
            l3.append(cur_node2.data)
            cur_node2 = cur_node2.next
        l3.append(cur_node2.data)
    elif cur_node2.next is None:
        l3.append(cur_node2.data)
        while cur_node1.next is not None:
            l3.append(cur_node1.data)
            cur_node1 = cur_node1.next
        l3.append(cur_node1.data)
    return l3


ll1 = LinkedList()
ll2 = LinkedList()
ll1.append(12)
ll1.append(45)
ll1.append(69)
ll1.append(70)
ll2.append(1)
ll2.append(2)
ll2.append(99)
ll2.append(100)
ll3 = merge(ll1, ll2)
ll3.print()

但是在运行代码后我得到了这个错误 File "C:/Users/_/PycharmProjects/DAA/SinglyLinkedList.py", line 179, in <module> ll3 = merge(ll1, ll2) File "C:/Users/_/PycharmProjects/DAA/SinglyLinkedList.py", line 143, in merge while (cur_node1.next is not None or cur_node1 is not None) or (cur_node2.next is not None or cur_node2 is not None): AttributeError: 'NoneType' object has no attribute 'next'

这里发生了什么?我不明白。我尝试在合并函数的 while 循环中运行没有 or 语句的代码。它工作得很好。所以显然问题出在while语句中。有人可以帮忙吗?

【问题讨论】:

  • 我认为您希望该检查为cur_node1 and cur_node2,因为您在循环中执行的第一件事是访问cur_node1.datacur_node2.data。不确定这是否足以使合并正常工作;这可能表明您没有考虑极端情况。
  • 考虑cur_node1 is None的情况。您希望cur_node1.next is not None or cur_node1 is not None 评估成功吗?为什么?怎么样?
  • 是的,这绝对不够——您的初始 while 循环将离开一个列表或另一个列表的末尾,因此之后的代码需要能够处理其中至少一个这两个节点是None
  • 我将 cur_node1 设为第一个链表的指针,将 cur_node2 设为第二个链表的指针。现在我比较了我在两个链表中遍历的特定节点中的数据。如果某些特定数据较小,我将其附加到新创建的列表 l3 中。现在,如果我们在比较时到达一个链表的末尾,我们应该退出 while 循环。 cur_node1 永远不会是 None,因为当 cur_node1 是指向 list1 中最后一个节点的指针时,cur_node1.next 会变为 None,因此它将在下一次迭代中跳出 while 循环。 or 运算符导致问题。
  • Lmao,没关系。我只是将while 循环更改为while True: 并将条件放入循环中。如果满足条件(cur_node1.next is not None or cur_node2.next is not None),我就跳出循环。现在效果很好。

标签: python oop data-structures linked-list


【解决方案1】:

问题出现在您的第一个循环中:

while cur_node1.next is not None or cur_node2.next is not None:

这意味着两个节点之一可能具有next 属性,即None。如果那个节点的数据也小于另一个节点中的数据,那么这个节点变量将被设置为None。然后再次评估while 条件,并产生错误,因为这个None 值没有next 属性...

您实际上是通过检查 cur_nodeX.next 属性是 None 而不是 cur_nodeX 本身使算法过于复杂。因此,您仍然需要在第一个循环完成后 从两个列表中添加节点。此外,您的代码假定两个列表都不为空。

因此,根据当前节点而不是它们的 next 属性来设置您的 while 条件:

def merge(l1, l2):
    cur_node1 = l1.head
    cur_node2 = l2.head
    l3 = LinkedList()
    while cur_node1 is not None or cur_node2 is not None:
        if cur_node1 is None or cur_node2 is not None and cur_node1.data > cur_node2.data:
            l3.append(cur_node2.data)
            cur_node2 = cur_node2.next
        else:
            l3.append(cur_node1.data)
            cur_node1 = cur_node1.next
    return l3

【讨论】:

  • 您的代码只有在我们假设迭代 l1 首先完成时才有效。如果 cur_node2 首先变为 None - if cur_node1 is None or cur_node1.data > cur_node2.data: AttributeError: 'NoneType' object has no attribute 'data',我会收到此错误
  • 确实如此。现已修复。
  • 不错。相当干净的代码。我需要学习如何写这样大声笑。
【解决方案2】:

这个打印 '1 -> 2 -> 12 -> 45 -> 69 -> 70 -> 99 -> 100'

def merge(l1, l2):
    cur_node1 = l1.head
    cur_node2 = l2.head
    l3 = LinkedList()
    while cur_node1 and (cur_node1.next is not None or cur_node2.next is not None):
        if cur_node1.data > cur_node2.data:
            l3.append(cur_node2.data)
            cur_node2 = cur_node2.next
        else:
            l3.append(cur_node1.data)
            cur_node1 = cur_node1.next
        if cur_node1.next is None:
           l3.append(cur_node1.data)
           while cur_node2.next is not None:
               l3.append(cur_node2.data)
               cur_node2 = cur_node2.next
           l3.append(cur_node2.data)
        elif cur_node2.next is not None:
            l3.append(cur_node2.data)
            while cur_node1.next is not None:
                l3.append(cur_node1.data)
                cur_node1 = cur_node1.next
            l3.append(cur_node1.data)
    return l3

【讨论】:

  • 预期结果是“1 -> 2 -> 12 -> 45 -> 69 -> 70 -> 99 -> 100”
  • 现在好了,出现了缩进问题
【解决方案3】:

对于任何想知道的人来说,这是可行的。

def merge(l1, l2):
cur_node1 = l1.head
cur_node2 = l2.head
l3 = LinkedList()
while True:
    if cur_node1 is None:
        while cur_node2.next is not None:
            l3.append(cur_node2.data)
            cur_node2 = cur_node2.next
        l3.append(cur_node2.data)
        break
    elif cur_node2 is None:
        while cur_node1.next is not None:
            l3.append(cur_node1.data)
            cur_node1 = cur_node1.next
        l3.append(cur_node1.data)
        break
    if cur_node1.data > cur_node2.data:
        l3.append(cur_node2.data)
        cur_node2 = cur_node2.next
    elif cur_node1.data < cur_node2.data:
        l3.append(cur_node1.data)
        cur_node1 = cur_node1.next
return l3

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-26
    • 2022-01-04
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2019-02-26
    • 2013-04-19
    相关资源
    最近更新 更多