生成所有可能的深度N的树? [英] Generating all possible trees of depth N?
问题描述
我有几种不同类型的树节点,每个树节点可能有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).
推荐答案
这是我写的一个Python程序,我认为它可以满足您的要求。给定一个起始节点,它将返回所有可能的树。从本质上讲,它可以归结为通过位操作的技巧:如果一个节点有5个子树,则有2 5 = 32个可能的子树,因为每个子树可以独立地存在或不存在于子树中。
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.
代码:
#!/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
这是运行程序的输出:
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]]
如果d就像我可以将其翻译成另一种语言一样。您没有指定,所以我使用了Python;因为我在很大程度上利用了Python的列表理解功能,所以代码在Java或C ++或其他语言上会更加冗长。
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.
这篇关于生成所有可能的深度N的树?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!