python从递归方法返回列表

python从递归方法返回列表,python,recursion,binary-tree,preorder,Python,Recursion,Binary Tree,Preorder,我正在使用这本书中描述的二叉树 已经有一个按如下定义的前序遍历方法 def preorder(tree): if tree: print(tree.self.key) preorder(tree.getLeftChild()) preorder(tree.getRightChild()) 我只想添加已访问节点列表的返回值。所以我可以做一些像 for i in preorder(tree): etc... def preorde

我正在使用这本书中描述的二叉树

已经有一个按如下定义的前序遍历方法

def preorder(tree):
    if tree:
        print(tree.self.key)
        preorder(tree.getLeftChild())
        preorder(tree.getRightChild())
我只想添加已访问节点列表的返回值。所以我可以做一些像

for i in preorder(tree):
    etc...
def preorder(tree, visnodes):
    if tree:
        visnodes.append(tree.self.key)
        print(tree.self.key)
        preorder(tree.getLeftChild(), visnodes)
        preorder(tree.getRightChild(), visnodes)

...
vn = []
preorder(tree, vn)
我从递归方法返回列表时遇到问题。递归一碰到我使用的“return”就停止了

return [tree.self.key] + preorder()

有什么想法吗?

您必须实际从递归函数返回一个值(目前,它只是打印值)。您应该边做边创建列表,也许可以稍微清理一下代码-类似这样:

def preorder(tree):
    if not tree:
        return []
    # optionally, you can print the key in this line: print(self.key)
    return [tree.key] + preorder(tree.leftChild) + preorder(tree.rightChild)

您可以将第二个参数添加到
preorder
函数中,如

for i in preorder(tree):
    etc...
def preorder(tree, visnodes):
    if tree:
        visnodes.append(tree.self.key)
        print(tree.self.key)
        preorder(tree.getLeftChild(), visnodes)
        preorder(tree.getRightChild(), visnodes)

...
vn = []
preorder(tree, vn)

是否确实要打印时使用
tree.self.key
,而不仅仅是
tree.key

否则,使用(Python 3.3+)的解决方案:

或使用简单的
产量

def preorder(tree):
    if tree:
        yield tree
        for e in preorder(tree.getLeftChild()):
            yield e
        for e in preorder(tree.getRightChild()):
            yield e
请注意,使用
yield
yield from
将函数转换为一个函数;特别是,如果您想要一个实际的列表(例如用于索引、切片或显示),您需要显式地创建它:
list(preorder(tree))

如果您有不同数量的孩子,很容易适应:

def preorder(tree):
    if tree:
        yield tree
        for child in tree.children:
            yield from preorder(child)

您只需为每个递归调用返回一个连接列表,该列表组合了当前键、左子树和右子树:

def preorder(tree):
        if tree:
            return ([tree.key] + preorder(tree.getLeftChild()) +
                    preorder(tree.getRightChild()))
        return []
对于n元树:

def preorder(tree):
    if tree:
        lst = [tree.key]
        for child in tree.children:
            lst.extend(preorder(child))
        return lst
    return []

你犯了什么错误?这是关于连接None和list的问题吗。似乎
preorder()
是一个辅助函数,实际上不是
BinaryTree
类的方法,因此将其称为方法有点混乱。2). 如果
tree
BinaryTree
的实例,则
tree.self.key
是错误的。3). 在Python中,很少需要getter(或setter)方法,只需直接访问属性。例如,
preorder(tree.leftChild)
。由于您直接访问
tree.key
,您最好使用
preorder(tree.leftChild)
preorder(tree.getRightChild)
。此外,您应该提到,要以这种方式获取节点列表,您需要执行类似于
节点=列表(预排序(树))
节点=[node for node In preorder(树)]
的操作。感谢您对列表的建议。至于你的另一点,我正在访问
tree.key
,因为我不想猜测是否有
getKey()
方法,但我相信OP的
tree.self.key
可能有问题。已经有人评论说Python中不需要getter和setter,但这里的评论实际上是多余的,因为问题的标题,我提到了如何创建列表。还要注意的是,它应该是
print tree.key
,而不是
yield tree.key
-OP需要一个节点列表,而不是一个节点和键混合的列表。没有节点,只有键(归纳为:
preorder
only yield
tree.key
或者什么
preorder
yield)。但实际上OP似乎想要一个节点列表,所以我已经编辑了
收益树
。非常感谢您的回复。我使用的是PythonV3.4,我没有让收益率表达式工作,我仍然在迭代器和生成器之间迷失了方向。。。无论如何,这个“if not tree return empty list”修复了我在“can not+NoneType”中遇到的问题,谢谢你的回复。如果它不是一个二叉树,我怎么能循环遍历所有的子树,例如def preorder(tree):if tree:return[tree.key]+[preorder(child,msg)for child in tree.children]@DamianSavage是的,但是在这里使用列表理解会得到一个列表,因为每个
preorder
调用都返回一个列表。您可以使用循环来实现这一点。我将用它更新我的答案。您可以使用:
返回和((tree.children的preorder(child),[tree.key])
,而不是显式循环。
def preorder(tree):
    if tree:
        lst = [tree.key]
        for child in tree.children:
            lst.extend(preorder(child))
        return lst
    return []