【问题标题】:Recursive tree search stops too early递归树搜索过早停止
【发布时间】:2020-09-16 19:14:44
【问题描述】:

我对 Python 和递归都很陌生,所以我可能找不到一些相关的问题,但我还没有看到这个确切的问题。我的任务是找出以下列表中每个名字的儿童人数

parents = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'V', 'W', 'X', 'Y', 'Z']

我有以下图形结构,上面有父母,下面有孩子(以字典和图表形式)。每个字母都算作它自己的孩子,所以最小的孩子数是一个。

data = {'G': ['F'], 'A': [], 'B': ['A'], 'C': ['A'], 'D': ['B', 'C'], 'E': ['D'], 'F': ['D'], 'X': [], 'Y': ['X', 'A'], 'Z': ['X'], 'V': ['Z', 'Y'], 'W': ['V']}

     A   X
    /|\ / \
   B C Y   Z
    \|  \ /
     D   V
    / \   \
   E   F   W
        \
         G

我碰巧知道这个问题的正确答案

Node   Correct   My_answers
A       10          10
B       5           1          Incorrect
C       5           5
D       4           4
E       1           1
F       2           2
G       1           1
V       2           2
W       1           1
X       5           2          Incorrect
Y       3           3
Z       3           1          Incorrect

我尝试将解决方案拆分为两个不同的函数,然后使用简单的循环打印出答案。 is_parent() 检查par 是否是父级,如果cld 并且如果我没记错的话,这意味着cldpar 的子级。由于输入格式,我已经这样做了。然后我有child_count(),它只是通过遍历所有名称并检查给定的潜在子级(pot_child)是否将par 作为其父级来吐出计数器。我的怀疑是我在is_parent() 中有一个问题,它会吐出False 在它广泛检查所有树枝之前,因此导致孩子人数低于真实人数。

这是我写的完整代码,上面定义了数据和父母。

def is_parent(cld, par, data):
    if cld == par:
        return True
    else:
        for par_2 in data[cld]:
            x = is_parent(par_2,par,data)
        if len(data[cld]) == 0:
            x = False
    return x
def child_count(par, data):
    cnt = 0
    for pot_child in data:  # for each potential child
        cnt += 1 if is_parent(pot_child, par, data) else 0
    return cnt


for parent in parents:
    print(parent,":",child_count(parent, data))

抱歉,这个问题的介绍太长了,但我想问的本质是两方面的。首先,我解决问题的一般方法是否合适(两个函数,然后是一个循环),是否有更快、更易读的替代方案?其次,如何防止我的递归搜索算法过早停止搜索(我尝试了可视化工具,但它在 1000 步后停止,这对我的算法来说还不够)?如何确保(通常)递归算法不会过早停止。

我也非常感谢一些免费资源来熟悉如何在 Python 中正确编写递归

先谢谢了!

【问题讨论】:

    标签: python recursion tree


    【解决方案1】:

    错误在这里:

    def is_parent(cld, par, data):
        if cld == par:
            return True
        else:
            for par_2 in data[cld]:
                x = is_parent(par_2,par,data) # <=== if x is True, return True!
                if x: break # <== quick fix
            if len(data[cld]) == 0:
                x = False
        return x
    

    后面的登录很简单。如果图形“分支”之一通向父级,则结果为True,而与其他分支无关

    经过一番清理:

    def is_parent(cld, par, data):
        return cld == par or any(is_parent(par_2,par,data) for par_2 in data[cld])
    

    有向图不能包含循环。标题提到了“树”,即使示例数据严格来说不是树,但它是无循环的。如果允许循环,则需要一组已访问节点来停止无限递归。

    (很抱歉没有回答一般如何编写递归函数以及推荐哪些资源的问题)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-26
      • 2014-01-02
      • 2017-03-02
      • 2021-07-03
      • 2019-04-17
      相关资源
      最近更新 更多