3

我有一本字典,我想用它来创建一棵树。这个想法是获取指定索引的,将其附加到列表中。将此值用作字典下一项中的索引,然后重复该过程,直到我们得到 None

我的字典

dict = {
         'A' : 'AF',
         'BF': 'B',
         'AF': 'Z',
         'Z' : None,
         'B' : 'B'
       }

我可以循环遍历字典并获得第一个值,但我无法更好地递归循环遍历字典。

注意 x 是我要指定的索引参数。即 A、BF、AF、Z 或 B

def tree(x,dict):
   result = []
   for value in dict:
      result.append(value)
    #stuck somewhere here. 
    #I would like to use this value as an index again and pick next value. 
    #Do this until I have no further relation

   #print final results in a list
   print result

当调用 tree(x,dict) 时,取 x = 'A' 预期的结果应该是:

['A','AF','Z']

感谢您的帮助和贡献。

4

3 回答 3

3

非递归版本要快得多,但有一个看起来不错

>>> def tree(D, x):
        if x is None: 
            return []
        else: 
            return [x] + tree(D, D[x])


>>> tree(D, 'A')
['A', 'AF', 'Z']

或作为单行:

def tree(D, x):
    return [] if x is None else [x] + tree(D, D[x])

这将具有二次运行时间,因为它每次都会添加两个列表,尽管如果您想要性能,您只需使用.append,然后无论如何只使用循环会更实用。

于 2013-03-23T12:54:49.533 回答
0
def tree(x,dict):
    old_value = x
    while True:
        value = dict.get(old_value)
        if not value:
            break
        result.append(value)
    print result
于 2013-03-23T12:50:59.577 回答
0

您还可以尝试递归生成器:

# This will loop "forever"
data = {                                                                        
  'A' : 'AF',                                                          
  'BF': 'B',                                                           
  'AF': 'Z',                                                           
  'Z' : None,                                                          
  'B' : 'B'                                                            
}                                                                      
                                                                                                                                                   
def tree(key):                                                                  
  value = data.get(key)                                                         
  yield key                                                                     
  if value is not None:                                                         
    for value in tree(value):                                                   
      yield value                                                               
                                                                            
for value in tree("A"):                                                         
  # Do something with the value     

编辑:上面建议的方法无法检测循环并将循环直到达到最大递归深度。

下面的递归方法跟踪访问的节点以检测循环并在存在时退出。关于如何找到循环的最易理解的描述来自这个答案

data = {
  'A' : 'AF',
  'BF': 'B',
  'AF': 'Z',
  'Z' : None,
  'B' : 'B'
}

def visit_graph(graph, node, visited_nodes):
    print "\tcurrent node: ", node, "\tvisited nodes: ", visited_nodes
    # None means we have reached a node that doesn't have any children
    if node is None:
        return visited_nodes
    # The current node has already been seen, the graph has a cycle we must exit
    if node in visited_nodes:
        raise Exception("graph contains a cycle")
    # Add the current node to the list of visited node to avoid cycles
    visited_nodes.append(node)
    # Recursively call the method with the child node of the current node
    return visit_graph(graph, graph.get(node), visited_nodes)


# "A" does not generate any cycle
print visit_graph(data, "A", [])

# Starting at "B" or "BF" will generate cycles
try:
    print visit_graph(data, "B", [])
except Exception, e:
    print e

try:
    print visit_graph(data, "BF", [])
except Exception, e:
    print e
于 2013-03-23T13:40:59.470 回答