使用对象递归打印族树

2024-05-17 02:36:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要有关家谱递归表示的帮助。以下是数据:

children_and_parents = {
    "Mary": ["Patricia", "Lisa"], 
    "Patricia": ["Barbara", "Helen", "Maria"], 
    "Maria": ["Keren", "Carol"], 
    "Barbara": ["Betty"]
}

我需要提到的是,这些值是对象,所以我需要调用它们children_and_parents["Maria"].child来获取['Patricia', 'Lisa']

我目前拥有的递归程序:

def draw_family_tree(person, level=0):
    if person in children_and_parents:
        for i in range (len(children_and_parents[person].child)):
            print (" "*level, person)
            return draw_family_tree(children_and_parents[person].child[i], level+3) 

它目前正在做的是:

Mary
   Patricia
      Barbara

但结果应该是:

Mary
   Patricia
       Barbara
           Betty
       Helen
       Maria
           Keren
           Carol
   Lisa

我被困在节目的开头。如果有人愿意帮忙,我会非常感激

粗略代码:https://repl.it/repls/BlondCavernousExponents


Tags: andchildlevelpersonhelenchildrenmarylisa
1条回答
网友
1楼 · 发布于 2024-05-17 02:36:46

查找树的根对于单独的操作来说是一个很好的选择。在您的示例中,我们知道它是"Mary",因此我们可以相应地进行迭代。如果未知,可以编写函数返回第一个父节点,该父节点不是任何其他节点的子节点:

def find_root(tree):
    all_children = {x for y in tree.values() for x in y}
    
    for node in tree:
        if node not in all_children:
            return node

至于实际的打印过程,请在迭代子节点之前尝试打印父节点。我还建议将树作为参数传递给函数,以维护封装并保持其可重用性(即不依赖于调用范围中存在的名为children_and_parents的变量)

def draw_family_tree(tree, root, gap=3, level=0):
    if root:
        print(" " * level + root)

        if root in tree:
            for child in tree[root]:
                draw_family_tree(tree, child, gap, level + gap)

我们还可以避免draw_family_tree中的副作用,让它返回一个生成器,让调用者决定如何处理结果:

def find_root(tree):
    all_children = {x for y in tree.values() for x in y}
    
    for node in tree:
        if node not in all_children:
            return node

def draw_family_tree(tree, root, gap=3, level=0):
    if root:
        yield " " * level + root

        if root in tree:
            for child in tree[root]:
                yield from draw_family_tree(tree, child, gap, level + gap)

if __name__ == "__main__":
    children_and_parents = {
        "Mary": ["Patricia", "Lisa"], 
        "Patricia": ["Barbara", "Helen", "Maria"], 
        "Maria": ["Keren", "Carol"], 
        "Barbara": ["Betty"]
    }
    root = find_root(children_and_parents)

    for node in draw_family_tree(children_and_parents, root):
        print(node)

输出:

Mary
   Patricia
      Barbara
         Betty
      Helen
      Maria
         Keren
         Carol
   Lisa

正如前面讨论中提到的,我不建议对简单的<string, list>对使用类;它在没有功能的情况下增加了很多冗长的内容,实际上有点误导,因为parent表明此人有一个家长(它实际上指的是对象所代表的人的名字)。如果您选择这样做,则需要将.child附加到所有括号访问中,并为类(或print(root.parent))编写一个__repr__(self)函数

相关问题 更多 >