在通用(非二进制)列表列表树

时间:2016-06-27 06:40:05

标签: python tree

我有一个以这种方式编码的树:

[A, [B, [G, [H], [I]]], 
    [D, [C], [E], [F]]]

这代表以下结构:

        A
       / \
      B   D
     /   /|\
    G   C E F
   / \
  H   I

此外,叶子都包含' end'而不是一个真实的字母,所以H,I,C,E,F,实际上都是'结束'

查看可能更直观的列表的另一种方法。在这种情况下,缩进代表树级

[A, 
    [B, 
        [G, 
            [H], 
            [I]
        ]
    ], 
    [D, 
        [C], 
        [E], 
        [F]
    ]
]

我想遍历树并列出所有叶子路径

[A, B, G, H]
[A, B, G, I]
[A, D, C]
[A, D, E]
[A, D, F]

我编写了这个可以遍历树并正确识别树叶的函数,但是我不确定如何像上面那样构建路径:

def leave_paths(lst, level=0):
    #level is used to keep track how far in the tree we are to
    #perform various functions - removed here for simplicity
    if lst[0] == 'end':
        #This is a leaf!
    for i, l in enumerate(lst[1:]): 
        if type(l) is list:
            leave_paths(l, level + 1)

据我所知,这种方法是正确的,但我不确定如何跟踪路径,以便按照我描述的方式对其进行格式化。

2 个答案:

答案 0 :(得分:1)

通过递归,您应该确定基本情况,然后使用简单的单个步骤来构建基本情况,以便制作更复杂的案例。

基本情况: 叶子是每条路径的独特之处,这似乎是一条线索,您可以在构建路径时从叶子开始。将包含叶子的列表作为返回值传递,这是您的基本情况。在只有一个节点的情况下,您只能在一个列表中只有一个值(只有一个路径)。

递归案例:您需要获取递归的结果(根据您的示例最多2个分支),然后将当前节点添加到每个子节点中结果列表(除非当前节点下没有分支,否则可能超过2)。在前期后返回结果。

修改:由于您对某些代码的要求非常好,所以基本上可以做到这一点:

def leave_paths(current):
    # Identify leaves by their length
    if len(current) == 1:
        return current
    # Take all branches, get the paths for the branch, and prepend current
    return [[current[0]] + path for branch in current[1:] for path in leave_paths(branch)]

这应该会为您提供一个"路径"名单。请注意我们如何在每个递归步骤中重新展平,方法是迭代branch es,然后迭代每个path的结果branch,然后放置前面的 - 结果将结果list理解为我们的返回值。

答案 1 :(得分:0)

以下是针对两个用例的更多应用复制粘贴答案,基于(并且主要是副本)机器向往的答案:

创建一个长字符串的路径,例如[' ABCDE']

def leave_paths(current):
    # Identify leaves by their length
    if len(current) == 1:
        return current

    # Take all branches, get the paths for the branch, and prepend 
    return [current[0] + path for branch in current[1:] for path in leave_paths(branch)]

如果您希望将路径作为列表,例如[' A'' B',' C'' d'' E&#39]

def leave_paths(current):
    # Identify leaves by their length
    if len(current) == 1:
        return [current]

    # Take all branches, get the paths for the branch, and prepend 
    return [[current[0]] + path for branch in current[1:] for path in leave_paths(branch)]