无法通过递归枚举所有算术表达式

时间:2016-01-14 13:25:58

标签: python recursion binary-tree generator

我想从给定的有序数字集生成所有可能的表达式,包括+, - ,*和/:

class Node:
    def __init__(self, data):
        self.left = None
        self.right = None
        self.data = data

    def is_leaf(self):
        if self.left is None:
            assert self.right is None
            return True
        return False

    def __repr__(self):
        if self.is_leaf():
            return repr(self.data)
        return '(%s%s%s)' % (self.left, self.data, self.right)


def enumerate_trees(numbers):
    n = len(numbers)
    if n == 1:
        yield Node(numbers[0])
    else:
        for i in range(1, n):
            left_subtrees = enumerate_trees(numbers[:i])
            right_subtrees = enumerate_trees(numbers[i:])
            for left in left_subtrees:
                for right in right_subtrees:
                    for op in ['+', '-', '*', '/']:
                        root = Node(op)
                        root.left = left
                        root.right = right
                        yield root


if __name__ == '__main__':
    for tree in enumerate_trees([5, 7, 10, 1]):
        print(repr(tree)[1:-1])

输出结果为:

5+(7+(10+1))
5-(7+(10+1))
5*(7+(10+1))
5/(7+(10+1))
5+(7-(10+1))
5-(7-(10+1))
5*(7-(10+1))
5/(7-(10+1))
5+(7*(10+1))
5-(7*(10+1))
5*(7*(10+1))
5/(7*(10+1))
5+(7/(10+1))
5-(7/(10+1))
5*(7/(10+1))
5/(7/(10+1))
5+(7+(10-1))
5-(7+(10-1))
5*(7+(10-1))
5/(7+(10-1))
5+(7-(10-1))
5-(7-(10-1))
5*(7-(10-1))
5/(7-(10-1))
5+(7*(10-1))
5-(7*(10-1))
5*(7*(10-1))
5/(7*(10-1))
5+(7/(10-1))
5-(7/(10-1))
5*(7/(10-1))
5/(7/(10-1))
5+(7+(10*1))
5-(7+(10*1))
5*(7+(10*1))
5/(7+(10*1))
5+(7-(10*1))
5-(7-(10*1))
5*(7-(10*1))
5/(7-(10*1))
5+(7*(10*1))
5-(7*(10*1))
5*(7*(10*1))
5/(7*(10*1))
5+(7/(10*1))
5-(7/(10*1))
5*(7/(10*1))
5/(7/(10*1))
5+(7+(10/1))
5-(7+(10/1))
5*(7+(10/1))
5/(7+(10/1))
5+(7-(10/1))
5-(7-(10/1))
5*(7-(10/1))
5/(7-(10/1))
5+(7*(10/1))
5-(7*(10/1))
5*(7*(10/1))
5/(7*(10/1))
5+(7/(10/1))
5-(7/(10/1))
5*(7/(10/1))
5/(7/(10/1))
5+((7+10)+1)
5-((7+10)+1)
5*((7+10)+1)
5/((7+10)+1)
5+((7+10)-1)
5-((7+10)-1)
5*((7+10)-1)
5/((7+10)-1)
5+((7+10)*1)
5-((7+10)*1)
5*((7+10)*1)
5/((7+10)*1)
5+((7+10)/1)
5-((7+10)/1)
5*((7+10)/1)
5/((7+10)/1)
(5+7)+(10+1)
(5+7)-(10+1)
(5+7)*(10+1)
(5+7)/(10+1)
(5+7)+(10-1)
(5+7)-(10-1)
(5+7)*(10-1)
(5+7)/(10-1)
(5+7)+(10*1)
(5+7)-(10*1)
(5+7)*(10*1)
(5+7)/(10*1)
(5+7)+(10/1)
(5+7)-(10/1)
(5+7)*(10/1)
(5+7)/(10/1)
(5+(7+10))+1
(5+(7+10))-1
(5+(7+10))*1
(5+(7+10))/1

我可以从输出中看到至少两个问题:

  1. 未到达某些树,例如(((5 7) 10) 1)
  2. 对于某个树,可能并非涵盖所有表达式。例如,对于树((5 (7 10)) 1),仅

    (5+(7+10))+1
    (5+(7+10))-1
    (5+(7+10))*1
    (5+(7+10))/1
    

    已到达。

  3. 是什么原因?感谢。

1 个答案:

答案 0 :(得分:2)

您的递归调用如下所示:

left_subtrees = enumerate_trees(numbers[:i])
right_subtrees = enumerate_trees(numbers[i:])
for left in left_subtrees:
    for right in right_subtrees:
        #...

enumerate_trees返回一个生成器对象,该对象只能迭代一次。因此for上的right_subtrees循环仅在第一次有效,并且在外for循环的下一次迭代中不会产生任何结果。

要解决此问题,您可以将递归调用直接放在for语句中,以便每次执行它们,也可以使用list(enumerate_trees(...))将结果复制到列表中。