You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

链表反转时不同赋值方式导致结果差异的原因解析

链表反转中不同赋值方式的差异问题

我在尝试反转链表时发现,不同的赋值方式会导致结果不同,具体情况如下:

from typing import Optional

class ListNode:
    def __init__(self, val=0, next: Optional["ListNode"] = None):
        self.val = val
        self.next = next


# 使用解包赋值,结果符合预期
nodes = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5)))))
rev = None
while nodes is not None:
    rev, rev.next, nodes = nodes, rev, nodes.next
# rev = [5, 4, 3, 2, 1]

# 但逐个赋值时,结果不符合预期
cnt = 0
nodes = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5)))))
rev = None
while nodes is not None:
    if cnt > 10:
        break
    rev = nodes
    rev.next = rev
    nodes = nodes.next
    cnt += 1
# rev = [1, 1, 1, 1, 1...] 出现循环引用导致无限循环!

我的运行环境为Python 3.10.7,请问为何会出现这样的差异?


原因解析

核心差异在于Python中解包赋值与逐个赋值的执行逻辑完全不同:

1. 解包赋值的执行逻辑

rev, rev.next, nodes = nodes, rev, nodes.next 这行代码遵循「先计算所有右侧值,再批量赋值」的规则:

  • 第一步:一次性获取当前nodes的引用(记为A)、当前rev的引用(记为B)、当前nodes.next的引用(记为C),这三个值会被临时缓存,不受后续赋值操作影响
  • 第二步:依次将A赋值给rev,B赋值给A.next(也就是新的rev.next),C赋值给nodes

整个过程中,修改rev.next时操作的是原nodes节点的next属性,而此时nodes还未被更新,不会破坏原链表的后续节点引用,因此能正确完成反转。

2. 逐个赋值的执行逻辑

而逐个赋值的代码执行顺序是「赋值一个,生效一个」:

rev = nodes
rev.next = rev
nodes = nodes.next
  • 第一步:rev = nodes 让rev指向当前nodes节点(比如第一次循环是节点1)
  • 第二步:rev.next = rev 直接将这个节点的next指向自身,制造了循环引用
  • 第三步:nodes = nodes.next 此时nodes.next已经变成了节点1自己,所以nodes仍然指向节点1,下一次循环重复同样操作,最终整个链表变成循环链表。

如果要修正逐个赋值的写法,需要先缓存原nodes.next的引用,避免修改next属性后丢失后续节点:

cnt = 0
nodes = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5)))))
rev = None
while nodes is not None:
    if cnt > 10:
        break
    next_node = nodes.next  # 先保存下一个节点的引用
    nodes.next = rev       # 修改当前节点的next指向rev
    rev = nodes            # 更新rev为当前节点
    nodes = next_node      # 让nodes指向之前保存的下一个节点
    cnt += 1
# rev = [5,4,3,2,1] 结果正确

内容的提问来源于stack exchange,提问作者kama-meshi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 06:05:26