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

发布于 2024-07-27 15:46:18 字数 133 浏览 5 评论 0原文

我有几种不同类型的树节点,每个节点可能有 0 到 5 个子节点。 我正在尝试找出一种算法来生成所有可能的深度 <= N 的树。这里有什么帮助吗? 鉴于我对节点所做的每次更改都可能会暴露新的子树(或删除旧的子树),我无法弄清楚如何递归地遍历树。

I have several different types of tree nodes, each of which may have anywhere from 0 to 5 children. I'm trying to figure out an algorithm to generate all possible trees of depth <= N. Any help here? I'm having trouble figuring out how to recursively walk the tree given that each change I make to a node may expose new subtrees (or remove old ones).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

这样的小城市 2024-08-03 15:46:18

这是我编写的一个 Python 程序,我认为它可以满足您的要求。 它将返回给定起始节点的所有可能的树。 本质上,它可以归结为位操作的技巧:如果一个节点有 5 个子节点,则有 25 = 32 个不同的可能子树,因为每个子节点可以独立地存在或不存在于子树中。

代码:

#!/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]]

如果您愿意,我可以将其翻译成其他语言。 你没有指定,所以我使用Python; 使用 Java 或 C++ 或其他语言编写的代码会更加冗长,因为我大量利用了 Python 的列表推导式。

Here's a Python program I wrote up that I think does what you're asking. It'll return all of the possible trees given a starting node. Essentially, it boils down to a trick with bit manipulation: if a node has 5 children, then there are 25 = 32 different possible subtrees as each child can independently be present or not present in a subtree.

Code:

#!/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

Here's a graphical representation of the test tree:

  1
 / \
2   3
   /|\
  4 5 6

And here's the output from running the program:

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]]

If you'd like I could translate this into a different language. You didn't specify so I used Python; the code would be a bit more verbose in Java or C++ or whatever since I took advantage of Python's list comprehensions in a big way.

非要怀念 2024-08-03 15:46:18

您可以创建一个包含 for 循环的函数,该循环将元素添加到多维数组并再次调用该函数,直到树完成。 我无法提供示例,因为我不知道您喜欢哪种语言。

You could create a function containing a for loop which adds the elements to a multidimensional array and calls that function again, until the tree is complete. I cannot provide examples since I don't know which language you prefer.

贩梦商人 2024-08-03 15:46:18

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

这有点拗口……

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

If the only difference between node types is the number of children, then generating every possible tree with only the node type with the greatest number of children will also generate every possible tree for any combination of nodes having equal or fewer children.

That's sort of a mouthful...

Put another way, if 5 children is the maximum, then some of the possible trees made of only 5-children nodes will have nodes that have, for example, two actual children, and three null pointers. This is practically the same as having a node with only two children.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文