【问题标题】:Why does my reverse linked list function mutate the global variable linkedlist?为什么我的反向链表函数会改变全局变量linkedlist?
【发布时间】:2022-01-19 01:44:31
【问题描述】:

以下是我的代码:

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

    def __str__(self):
        return str(self.val) + " -> " + str(self.next)

def reverse_list(head: ListNode) -> ListNode:
    prev, curr  = None, head
    while curr:
        nxt = curr.next
        curr.next = prev
        prev = curr
        curr = nxt
    return prev

linked_list = ListNode(1, ListNode(2, ListNode(3)))

打印出来时,linked_list 显示为“1 -> 2 -> 3 -> None”。但是,在调用了reverse_list函数一次,然后再次打印linked_list之后,它似乎发生了变异,变成了1 -> None。谁能解释这背后的原因?示例如下:

print(linked_list)
# 1 -> 2 -> 3 -> None
print(reverse_list(linked_list))
# 3 -> 2 -> 1 -> None
print(linked_list)
# 1 -> None

【问题讨论】:

  • 因为您正在修改列表节点。所以最初的节点现在是最后一个。
  • linked_list 仍然包含对最初第一个但现在是最后一个节点的引用。
  • @Barmar 你能解释一下我的函数是如何改变全局变量的吗?有没有办法在不改变全局变量的情况下反转列表?谢谢
  • 它没有改变全局变量。
  • 它改变了全局变量引用的对象。

标签: python oop linked-list mutation


【解决方案1】:

发生这种情况是因为返回的节点实例不是传递给reverse的节点实例。

这可能有助于形象化。此时reverse被调用,即将开始反转,我们有这个状态:

         curr
         head                                              prev 
          ↓                                                 ↓ 
        ┌───────────┐    ┌───────────┐    ┌───────────┐
        │ value: 1  │    │ value: 2  │    │ value: 3  │
        │ next: ───────> │ next: ───────> │ next: ───────> None
        └───────────┘    └───────────┘    └───────────┘ 
          ↑
         linked_list (global)

然后当reverse 完成它的循环时,我们有这个:

curr     head                              prev
 ↓        ↓                                 ↓
        ┌───────────┐    ┌───────────┐    ┌───────────┐
        │ value: 1  │    │ value: 2  │    │ value: 3  │
None <────── :next  │ <────── :next  │ <─────── :next │
        └───────────┘    └───────────┘    └───────────┘ 
          ↑
         linked_list (global)

reverse 然后返回 prev 引用。很明显,这个引用的节点和linked_list引用的节点不是同一个。

所以当print(reverse_list(linked_list))被调用时,__repr__方法将获取值为3的节点作为参数,从而能够打印出next链之后的所有节点。

然而,当print(linked_list)被调用时,__repr__方法会获取值为1的节点作为参数,当循环查找next属性时,它会找到None——这会停止印刷。当您查看上面的可视化时,您可以看到如果以 linked_list 作为参考开始,则值为 2 和 3 的节点是无法访问的。 linked_list 引用了反向列表的 tail

“解决方案”很简单:你必须捕获reverse返回的值,你可以将它重新赋值给linked_list变量:

linked_list = reverse_list(linked_list)

一旦执行,您将获得以下可视化效果:

        ┌───────────┐    ┌───────────┐    ┌───────────┐
        │ value: 1  │    │ value: 2  │    │ value: 3  │
None <────── :next  │ <────── :next  │ <─────── :next │
        └───────────┘    └───────────┘    └───────────┘ 
                                            ↑
                                           linked_list (global)

所以把你的主脚本改成:

print(linked_list)
# 1 -> 2 -> 3 -> None
linked_list = reverse_list(linked_list)
print(linked_list)
# 3 -> 2 -> 1 -> None

【讨论】:

  • 谢谢!这很有帮助
猜你喜欢
  • 1970-01-01
  • 2019-08-06
  • 2023-03-09
  • 2013-10-29
  • 1970-01-01
  • 1970-01-01
  • 2021-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多