python递归函数返回树中没有子节点的节点

时间:2018-05-21 20:01:08

标签: python recursion tree return

     0
   /   \
  1     2
 / \   /|\
3   4 5 6 7

我尝试使用递归函数从对象返回没有子节点的节点(3,4,5,6,7)。

它使用全局变量和此函数:

def find(self, nodes):
    if not hasattr(self, 'children'): 
        nodes.append(self)
    else:
        for i in self.children:
            i.find(nodes)


nodes = []
node.find(nodes) # can be any node (0,1,2,3,4, etc.)
print(nodes)

但我想在我的函数中使用return。我试过这样的事情:

   def find2(self):
    if not hasattr(self, 'children'): 
        return self
    else:
        for i in self.children:
            return i.find2()


nodes = root.find2()
print(nodes)

但我只得到一个节点。我也试过在这篇文章中传递一个数组:PYTHON Return a list from a recursive function。但是我没有得到我想要的结果,因为树结构(我猜)......

我被困了,你能帮助我吗?如何"将递归函数的每次迭代的结果返回给变量"?谢谢

3 个答案:

答案 0 :(得分:1)

请注意,在基本情况下,您将返回一个节点。然后该节点在递归中传播回来,并最终返回。即您返回的节点是第一个没有孩子的节点。有多种方法可以解决这个问题(例如通过返回和连接列表),但我认为这样做的一个自然方法是使您的函数成为生成器。为此,只需将return替换为yield即可。然后,函数的返回值充当迭代器,每次迭代都会产生下一个值,该值将在执行中“返回”,直到函数终止。

答案 1 :(得分:1)

你没有为我提供足够的代码来制作一个可运行且可测试的例子,但这是我猜你所寻求的:

def find(self):
    if not hasattr(self, 'children'):
        return [self]

    nodes = []

    for child in self.children:
        return nodes.extend(child.find())

    return nodes

# ...

nodes = root.find()
print(nodes)

答案 2 :(得分:1)

这是输入示例:

     0
   /   \
  1     2
 / \   /|\
3   4 5 6 7

考虑您希望为每个节点返回(递归)函数:

  • 在root(0)上调用时,应该返回完整的结果(3,4,5,6,7)
  • 在叶节点(例如5)上调用时,应该返回该节点(5)
  • 对于任何其他节点(例如1),它就像是较小树的根节点

因此,它有时会返回一个结果,有时会返回很多结果。 代码中的错误在这里,因为函数在第一次返回时结束,它不会返回很多:

    for i in self.children:
        return i.find2()

有两种解决方案:

  • 制作生成器功能,或
  • 创建一个返回列表的函数(使其始终返回一个列表,即使它只有一个元素!)

所以,选项1:

def find(self):
    if not hasattr(self, 'children'): 
        yield self
    else:
        for child in self.children:
            yield from child.find()

选项2:

def find(self):
    if not hasattr(self, 'children'): 
        return [self]
    else:
        rtn = []
        for child in self.children:
            for result in child.find():
                rtn.append(result)
        return rtn

我更喜欢发电机。此外,我并不特别喜欢您的某些节点具有children属性,而其他节点则没有。我会确保所有人都有children,这可能是空的或非空的。然后,代码变为:

def find_leaves(self):
    if self.children:
        for child in self.children:
            yield from child.find_leaves()
    else:
        yield self