代码之家  ›  专栏  ›  技术社区  ›  Joe

生成深度为N的所有可能的树?

  •  3
  • Joe  · 技术社区  · 15 年前

    我有几种不同类型的树节点,每个节点可能有0到5个子节点。我想找出一个算法来生成所有可能的深度树,有什么帮助吗?我可能要递归地删除每一个旧的子树(我可能要通过递归的方式来删除每一个新的节点)。

    4 回复  |  直到 15 年前
        1
  •  4
  •   John Kugelman Michael Hodel    15 年前

    我写了一个Python程序,我想它能满足你的要求。它将返回给定起始节点的所有可能的树。本质上,它归结为一个位操作的技巧:如果一个节点有5个子节点,那么有2个子节点 5

    代码:

    #!/usr/bin/env python
    
    def all_combos(choices):
        """
        Given a list of items (a,b,c,...), generates all possible combinations of
        items where one item is taken from a, one from b, one from c, and so on.
    
        For example, all_combos([[1, 2], ["a", "b", "c"]]) yields:
    
            [1, "a"]
            [1, "b"]
            [1, "c"]
            [2, "a"]
            [2, "b"]
            [2, "c"]
        """
        if not choices:
            yield []
            return
    
        for left_choice in choices[0]:
            for right_choices in all_combos(choices[1:]):
                yield [left_choice] + right_choices
    
    class Node:
        def __init__(self, value, children=[]):
            self.value    = value
            self.children = children
    
        def all_subtrees(self, max_depth):
            yield Node(self.value)
    
            if max_depth > 0:
                # For each child, get all of its possible sub-trees.
                child_subtrees = [list(self.children[i].all_subtrees(max_depth - 1)) for i in range(len(self.children))]
    
                # Now for the n children iterate through the 2^n possibilities where
                # each child's subtree is independently present or not present. The
                # i-th child is present if the i-th bit in "bits" is a 1.
                for bits in xrange(1, 2 ** len(self.children)):
                    for combos in all_combos([child_subtrees[i] for i in range(len(self.children)) if bits & (1 << i) != 0]):
                        yield Node(self.value, combos)
    
        def __str__(self):
            """
            Display the node's value, and then its children in brackets if it has any.
            """
            if self.children:
                return "%s %s" % (self.value, self.children)
            else:
                return str(self.value)
    
        def __repr__(self):
            return str(self)
    
    tree = Node(1,
    [
        Node(2),
        Node(3,
        [
            Node(4),
            Node(5),
            Node(6)
        ])
    ])
    
    for subtree in tree.all_subtrees(2):
        print subtree
    

    以下是测试树的图形表示:

      1
     / \
    2   3
       /|\
      4 5 6
    

    下面是运行程序的输出:

    1
    1 [2]
    1 [3]
    1 [3 [4]]
    1 [3 [5]]
    1 [3 [4, 5]]
    1 [3 [6]]
    1 [3 [4, 6]]
    1 [3 [5, 6]]
    1 [3 [4, 5, 6]]
    1 [2, 3]
    1 [2, 3 [4]]
    1 [2, 3 [5]]
    1 [2, 3 [4, 5]]
    1 [2, 3 [6]]
    1 [2, 3 [4, 6]]
    1 [2, 3 [5, 6]]
    1 [2, 3 [4, 5, 6]]
    

        2
  •  1
  •   user142019 user142019    15 年前

        4
  •  0
  •   Ryan Fox    15 年前

    如果节点类型之间的唯一区别是子节点的数量,那么仅使用子节点数量最多的节点类型生成每个可能的树,也将为具有相等或更少子节点的任何组合生成每个可能的树。

    有点像是一口。。。

    换句话说,如果5个子节点是最大值,那么仅由5个子节点组成的一些可能树的节点将具有,例如,两个实际子节点和三个空指针。这实际上与只有两个子节点的节点相同。