将输入列表映射到最低级别的嵌套列表

时间:2015-06-28 23:13:57

标签: python-2.7 nested

我有一个Python类,它本身存储更多类,作为锯齿状树结构。最高层和中间层不存储任何数据,但最低层不存储。我有一个列表,例如[8, 2, 5, 3],我想将每个值分配给树的最低级别的相应插槽:tree每个节点可以向下具有不同数量的连接,并且可以是任意数量的层。我的问题是,我无法使用类似问题中提供的traverse函数,因为我正在分配多个值,而且我无法轻松获得底部每个值的索引。这是节点类:

    class Node(object):
        def __init__(self, branches):
            self.branches = branches # This is a list of Node objects
            self.value = 0

分支列表包含更多节点,其中包含节点本身列表。该值默认为0,但如前所述,稍后会有一个列表映射到它们。这是一个如何创建树的示例,以及我想要做的事情:

tree = Node([
        Node([
            Node([
                None # This node's value is 1
            ]),
            Node([
                None # This node's value is 2
            ])
        ]),

        Node([
            Node([
                None # This node's value is 3
            ]),
            Node([
                None # This node's value is 4
            ])
        ])
    ])

    tree.set_inputs([1, 2, 3, 4]) # See above comments, this is what I want

我怎样才能做到这一点?我唯一的想法是一个递归函数,它将输入的索引转换为二进制(这可能会根据分支数量而改变)数字,例如0100110,它通过索引其分支来确定每个递归的方向:< / p>

# In the example above: b0 -> b1 -> b0 -> b0 -> b1 -> b1 -> b0.

如果这是解决这个问题的方法,我需要一些帮助来实现它。否则,对我的问题的任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:0)

深度优先搜索可以按照从左到右或从右到左的顺序产生树的叶节点的方式完成,具体取决于它的实现方式。首先,我要向您的name添加__repr__属性和Node,以便更轻松地查看正在发生的事情:

class Node(object):
    def __init__(self, name, branches):
        self.branches = branches # This is a list of Node objects
        self.value = 0
        self.name = name

    def __repr__(self):
        return '<Node {}>'.format(self.name)

现在我们将定义两个函数。第一个产生深度优先搜索中的节点:

from collections import deque

def dfs(root):
    stack = deque([root])
    while stack:
        node = stack.pop()
        yield node
        if node.branches is not None:
            for child in reversed(node.branches):
                stack.append(child)

请注意有关此代码的一些内容。首先,我们迭代节点的reversed个子节点。这导致叶子从左到右产生。如果我们删除reversed,则会从右到左迭代叶子。另外,请注意,对于没有子节点的叶节点,可能更清晰的表示是将空迭代(例如空元组)分配给node.branches。然后可以完全删除node.branches is not None检查。

上述代码当然会生成所有节点。我们只想要叶子:

def leaves(root):
    for node in dfs(root):
        if node.branches is None:
            yield node

让我们测试一下。这是一棵简单的树:

#      g
#     / \   
#    /   \
#   e     f
#  /\    /\
# a  b  c  d

a, b, c, d = [Node(name, None) for name in 'abcd']
e = Node('e', (a,b))
f = Node('f', (c,d))
g = Node('g', (e,f))

让我们列出树叶:

>>> list(leaves(g))
[<Node a>, <Node b>, <Node c>, <Node d>]

请注意,它们按从左到右的顺序排列。现在分配值很简单:

values = [1, 2, 3, 4]
for leaf, value in zip(leaves(g), values):
    leaf.value = value

那样:

for node in (a, b, c, d):
    print(node.name, node.value)

给出:

a 1
b 2
c 3
d 4