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

Python递归DFS返回指定节点问题及可变对象传参疑问

Python可变对象默认参数陷阱与二叉树节点查找优化

你遇到的核心问题是Python默认参数的创建时机——函数的默认参数是在函数定义的时候就初始化了,而不是每次调用函数时重新创建。列表是可变对象,所以当你第一次调用get_node时,修改了这个默认的列表n,它的状态会被保留下来;第二次调用时,函数会复用这个已经被修改过的列表,新找到的节点会直接追加进去,导致返回的列表包含两次调用的结果。这就是为什么你第二次调用get_node时,列表里还留着第一次的n1节点,需要取索引1来获取n2。

至于用字符串或None无法生效,是因为它们属于不可变对象。在递归过程中,如果你试图给它们赋值(比如n = root),其实只是创建了一个新的局部变量,不会影响上层递归调用中的n;而列表是可变的,append操作直接修改了原对象的内容,所以能在整个递归链路中收集到所有匹配的节点。

能不能用默认值为None的普通对象替代?

当然可以!这还是Python中规避默认可变参数陷阱的标准做法。你可以把默认参数设为None,然后在函数内部判断,如果n是None,就初始化一个新的列表(或你需要的普通对象)。这样每次调用函数时,都会创建一个全新的空列表,不会复用之前的状态。

改进后的代码示例:

def get_node(self, d, root, n=None):
    # 每次调用时初始化新列表,彻底避免复用默认参数的对象
    if n is None:
        n = []
    if root is None:
        return
    if root.data == d:
        n.append(root)
    # 递归时传递当前的n列表
    self.get_node(d, root.left, n)
    self.get_node(d, root.right, n)
    return n

def tree_traversal(self, n1_val, n2_val):
    # 现在每次调用get_node都会返回独立的列表,直接取索引0即可
    n1 = self.get_node(n1_val, self.root)[0]
    n2 = self.get_node(n2_val, self.root)[0]
    print(n1.data)
    print(n2.data)
    return self.helper(n1, n2)

额外优化建议

如果你的需求是找到第一个匹配的节点就返回,而不是收集所有匹配节点,还可以简化递归逻辑,找到后直接返回,不需要遍历整个树:

def get_node(self, d, root):
    if root is None:
        return None
    if root.data == d:
        return root
    # 先遍历左子树,找到结果直接返回
    left_result = self.get_node(d, root.left)
    if left_result is not None:
        return left_result
    # 左子树没找到,再遍历右子树
    return self.get_node(d, root.right)

这样调用时直接n1 = self.get_node(n1_val, self.root)即可,不需要处理列表,效率也更高。

内容的提问来源于stack exchange,提问作者danep

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:06:30