递归生成图形-Python

递归生成图形-Python,python,recursion,hash,graph,nodes,Python,Recursion,Hash,Graph,Nodes,这是我现在的代码: hasht= {"A":["B", "D", "E"], "B":["C"], "C":["D", "E"], "D":["C", "E"], "E":["B"]} paths=[] def recusive(start, finish, val): if start==finish and val!=1: return start else: for i in hasht[start]:

这是我现在的代码:

   hasht= {"A":["B", "D", "E"], "B":["C"], "C":["D", "E"], "D":["C", "E"], "E":["B"]}
   paths=[]
   def recusive(start, finish, val):
      if start==finish and val!=1:
        return start
    else:
        for i in hasht[start]:
            path= start+ recusive(i,finish,2)
            paths.append(path)
print (recusive("C","C",1))
print paths

#[CDC, CDEBC, CEBC]
我试图生成一个类似于底部的表,但遇到了字符串和数组无法连接的问题。然而,当我刚刚返回时,它返回CDC并工作,然而,退出函数是返回的目的。我想知道如何改进我的代码,1)使其工作,2)为什么我的逻辑是错误的。例如,我知道它一般是说[DC],但我不知道如何绕过它。可能会为返回的值编制索引?

有几件事:

  • 格式化:把一个图形放在一行上是很糟糕的
  • 函数失败的原因是递归函数返回字符串或None,但字符串和None之间的连接未定义。始终确保递归函数始终返回给定的数据类型或始终不返回任何内容
  • 除非可以干净地调用递归函数,否则使用helper函数隐藏不必要的变量初始化
  • val变量是不必要的;没有一个节点循环到它们自己(无论如何,这并不能正确地防止这种情况发生)
  • 为什么要打印函数调用?您正在调用函数来发现路径,但它不会返回路径
  • 为什么要写入全局变量?多次运行该函数将累积不相关的路径
  • 为什么函数不向原始调用返回任何内容
我将函数改为传递path变量而不是start变量,因为递归函数在不返回数据而是写入变量(路径列表)时更容易理解(这是嵌套辅助函数的另一个好处)

我还嵌套了helper函数,以提供一个干净的调用接口,但也为局部变量提供了平坦的返回结构,而不使用堆栈

这种结构也更容易看到路径是如何扩展的;也就是说,path始终是一个字符串列表,而i始终是一个字符串,因此将列表封装的字符串连接到列表将始终有效

hasht = \
{
    "A" : ["B", "D", "E"],
    "B" : ["C"],
    "C" : ["D", "E"], 
    "D" : ["C", "E"], 
    "E" : ["B"]
}

def recursive(start, finish):
    paths=[]
    def recursive_helper(path, finish):
        for i in hasht[path[-1]]:
            if i == finish:
                paths.append(path + [i])
                continue
            else:
                recursive_helper(path + [i], finish)
    recursive_helper([start], finish)
    return paths

print recursive("C", "C")

这里的主要问题是,当到达内部for循环的末尾时,没有返回任何内容。因此,从导致错误的上一个递归返回一个非类型:

TypeError: cannot concatenate 'str' and 'NoneType' objects
让我们浏览一下您的代码,看看会发生什么: 我们将通过在for循环的列表中替换来实现这一点,这样我们就可以完全看到发生了什么(这不是有效的python代码,只是为了演示:D)

好的,到目前为止还不错,我们有路径(Path_j)'DC',所以我们把它附加到路径上,现在看看最里面的循环,其中j现在被设置为'E'

rec('C','C',1)

for i in ['D','C']
  path_i = 'C'+rec('D','C',2)
  for j in ['E']
    path_j = 'D'+rec('E','C',2)
    for k in ['B']
      path_k = 'B'+rec('B','C',2)
      for l in ['C']
          'C'=='C' and 2!=1
           return 'C'
好的,我们有另一条路。这一次是path_k='BC',所以让我们将其附加到path。 但是现在k的元素已经用完了,我们需要返回一些东西

rec('C','C',1)
for i in ['D','C']
  path_i = 'C'+rec('D','C',2)
  for j in ['E']
    path_j = 'D'+rec('E','C',2)
    for k in []
        return ???
目前您没有返回任何内容,因此python会为您返回一个“NoneType”对象

rec('C','C',1)
for i in ['D','C']
  path_i = 'C'+rec('D','C',2)
  for j in ['E']
    path_j = 'D'+NoneType
不幸的是,您现在试图将此非类型与字符串连接,因此出现错误:

TypeError: cannot concatenate 'str' and 'NoneType' objects
要进行更正,只需返回路径字符串: (这是现在实际有效的python代码)

这将返回以下路径:

['DC', 'BC', 'EBC', 'DEBC', 'CDEBC', 'BC', 'EBC', 'CEBC']

为什么不直接使用networkx呢?这就是它的目的

hasht = \
{
    "A" : ["B", "D", "E"],
    "B" : ["C"],
    "C" : ["D", "E"], 
    "D" : ["C", "E"], 
    "E" : ["B"]
}

import networkx as nx
G = nx.DiGraph(hasht)

list(nx.all_simple_paths(G, 'C', 'C'))
[['C', 'E', 'B', 'C'], ['C', 'D', 'C'], ['C', 'D', 'E', 'B', 'C']]

如果这是家庭作业。。。很明显,你不能这样做,但是用imho…

哦,是的,回答你原来的问题要容易得多:你不能做
'a'+['b','c']
,但你可以做
['a']+['b','c']
。只需将元素用括号括起来,列出它,然后就可以附加它了。
hasht = \
{
    "A" : ["B", "D", "E"],
    "B" : ["C"],
    "C" : ["D", "E"], 
    "D" : ["C", "E"], 
    "E" : ["B"]
}

import networkx as nx
G = nx.DiGraph(hasht)

list(nx.all_simple_paths(G, 'C', 'C'))
[['C', 'E', 'B', 'C'], ['C', 'D', 'C'], ['C', 'D', 'E', 'B', 'C']]