什么python代码为二元运算符生成所有可能的分组(树)

时间:2013-06-21 18:35:12

标签: python algorithm binary-tree

正如在几个SO问题中所解释的那样,并且更加抽象地在mathworld处解释,加泰罗尼亚数字的序列恰好对应于可以为任何给定数量的运算符生成的括号分组的数量。但我还没有找到生成所有这些分组的算法。

这种二进制包围算法对应于Tamari Lattice,可以用许多不同的方式来描述。该算法最明显的实际用途是通过围绕二元运算符和它们运算的数字的每个可能的包围来生成所有可能的表达式。这可以用于彻底测试二叉树上的各种类型的操作。

网络搜索确实显示one implementation in C#,但我认为我需要一段时间来理解,因为我不知道C#语法。

那么,什么python代码生成围绕运算符的所有可能的括号分组(因此可以与实际表达式一起使用以生成所有可能性)?对于2,3和4,输出看起来如下:

AllBinaryTrees(2)

  1. (X(XX))
  2. ((XX)x)的
  3. AllBinaryTrees(3)

    1. (((XX)x)的x)的
    2. ((X(XX))×)
    3. ((XX)(XX))
    4. (×((XX)X))
    5. (X(X(XX)))
    6. AllBinaryTrees(4)

      1. (X(X(X(XX))))
      2. (X(X((XX)X)))
      3. (×((XX)(XX)))
      4. (×((X(XX))×))
      5. (×(((XX)x)的X))
      6. ((XX)(X(XX)))
      7. ((XX)((XX)X))
      8. ((X(XX))(XX))
      9. (((XX)x)的(XX))
      10. ((X(X(XX)))×)
      11. ((×((XX)X))×)
      12. (((XX)(XX))×)
      13. (((X(XX))×)x)的
      14. ((((XX)x)的x)的x)的
      15. 更好的是代码可以执行以下操作:

        AllBinaryTrees( “2 + 3/4”)

        输出:

        1. 2+(3/4)
        2. (2 + 3)/ 4

2 个答案:

答案 0 :(得分:5)

怎么样

def allbinarytrees(s):
    if len(s) == 1:
        yield s
    else:
        for i in range(1, len(s), 2):
            for l in allbinarytrees(s[:i]):
                for r in allbinarytrees(s[i+1:]):
                    yield '({}{}{})'.format(l, s[i], r)

样本用法:

for t in allbinarytrees('1+2-3*4/5'):
    print(t)

输出:

(1+(2-(3*(4/5))))
(1+(2-((3*4)/5)))
(1+((2-3)*(4/5)))
(1+((2-(3*4))/5))
(1+(((2-3)*4)/5))
((1+2)-(3*(4/5)))
((1+2)-((3*4)/5))
((1+(2-3))*(4/5))
(((1+2)-3)*(4/5))
((1+(2-(3*4)))/5)
((1+((2-3)*4))/5)
(((1+2)-(3*4))/5)
(((1+(2-3))*4)/5)
((((1+2)-3)*4)/5)

答案 1 :(得分:3)

接受的答案仅适用于单位数字,我会将其作为已接受的答案,因为它以易于阅读的方式说明了这一概念。这个经过修改的,看起来很简洁的版本适用于所有数字,而不仅仅是单个数字:

def allbinarytrees(s):
    if s.isdigit():
        yield s
    else:
        i = 0
        while i < len(s)-1:
            while i < len(s) and s[i].isdigit():
                i += 1
            if i < len(s) - 1:
                for left in allbinarytrees(s[:i]):
                    for right in allbinarytrees(s[i+1:]):
                        yield '({}{}{})'.format(left, s[i], right)
            i += 1

样本用法:

j=0
for t in allbinarytrees('11+22*3/4456'):
    j += 1
    print j, (t[1:-1])

输出:

1 11+(22*(3/4456))
2 11+((22*3)/4456)
3 (11+22)*(3/4456)
4 (11+(22*3))/4456
5 ((11+22)*3)/4456