在包含 1 个以上循环的字典中查找所有循环

问题描述

给定以下循环字典:

{'E': ['F'],'F': ['C','G'],'C': ['E'],'G': ['H'],'H': ['I'],'I': ['J','D'],'J': ['D'],'D': ['E']}

其中键代表父节点,值是它指向的所有子节点(这表示有向图)。

可以看出有3个周期:

  1. E -> F -> C
  2. E -> F -> G -> H -> I -> J -> D
  3. E -> F -> G -> H -> I -> D

我试图找出一种能够提取所有循环的方法或函数,以便我可以输出或返回三个循环:

EFC

EFGHIJD

EFGHID

我正在寻找 Python 解决方案!谢谢:)

解决方法

您可以使用递归生成器函数:

d = {'E': ['F'],'F': ['C','G'],'C': ['E'],'G': ['H'],'H': ['I'],'I': ['J','D'],'J': ['D'],'D': ['E']}
def get_cycles(n,o = None,c = []):
   if n == o: #check if current node being examined is the same as the start
      yield c #if the condition is met,then a cycle is found and the path is yielded back
   else:
      #get the children of the current node from d and iterate over only those that have not been encountered before (except if the node is the same as the start)
      for i in filter(lambda x:x not in c or x == o,d.get(n,[])):
         #recursively find the children of this new node `i`,saving the running path (c + [n])
         yield from get_cycles(i,o = n if o is None else o,c = c + [n])

print(list(get_cycles('E')))
print(list(get_cycles('D')))

输出:

[['E','F','C'],['E','G','H','I','J','D']]
[['D','E','J'],['D','I']]
,

获取一个起始节点的所有周期的一种方法是:

System check identified no issues (0 silenced).
June 15,2021 - 01:54:10
Django version 3.2.4,using settings 'codersavvy.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
Internal Server Error: /api/blogs/post/
Traceback (most recent call last):
  File "D:\work environment\Django_Api\codersavvy\lib\site-packages\django\core\handlers\exception.py",line 47,in inner
    response = get_response(request)
  File "D:\work environment\Django_Api\codersavvy\lib\site-packages\django\core\handlers\base.py",line 181,in _get_response
    response = wrapped_callback(request,*callback_args,**callback_kwargs)
  File "D:\work environment\Django_Api\codersavvy\lib\site-packages\django\views\decorators\csrf.py",line 54,in wrapped_view
    return view_func(*args,**kwargs)
  File "D:\work environment\Django_Api\codersavvy\lib\site-packages\django\views\generic\base.py",line 70,in view
    return self.dispatch(request,*args,**kwargs)
  File "D:\work environment\Django_Api\codersavvy\lib\site-packages\rest_framework\views.py",line 509,in dispatch
    response = self.handle_exception(exc)
  File "D:\work environment\Django_Api\codersavvy\lib\site-packages\rest_framework\views.py",line 469,in handle_exception
    self.raise_uncaught_exception(exc)
  File "D:\work environment\Django_Api\codersavvy\lib\site-packages\rest_framework\views.py",line 480,in raise_uncaught_exception
    raise exc
  File "D:\work environment\Django_Api\codersavvy\lib\site-packages\rest_framework\views.py",line 506,in dispatch
    response = handler(request,**kwargs)
  File "D:\work environment\Django_Api\codersavvy\lib\site-packages\rest_framework\decorators.py",line 50,in handler
    return func(*args,**kwargs)
  File "D:\work environment\Django_Api\codersavvy\blog\views.py",line 75,in post_blog
    image=data['image'],KeyError: 'image'
[15/Jun/2021 01:54:15] "POST /api/blogs/post/ HTTP/1.1" 500 96879

使用您的图表和起始节点 def cycles(graph,start): results = [] paths = [(start,)] while paths: path = paths.pop() childs = set(graph.get(path[-1],[])) if start in childs: results.append(path) paths.extend( (path + (child,)) for child in childs.difference(path) ) return results ,您将得到(Eprint(cycles(g,'E')) 您的字典):

g

如果您想要图形中的所有循环,则必须做更多工作:一个起始节点通常不会导致图形的所有循环。实现这一目标的一种方法是遍历所有节点,应用 [('E','D'),('E','C')] ,然后收集所有结果:

cycles
result = [cycle for node in g for cycle in cycles(g,node)]

但是这种方式会导致一些冗余:[('E','C'),('F','D','E'),'C',('C','F'),('G',('H','G'),('I','H'),('J','I'),('D','J')] ('E','C')('C','F')本质上是相同的(等等)。如果你想摆脱它,你可以这样做:

( 'F','E')

results = [] d = {node: set(g.get(node,[])) for node in g} nodes = list(d) while nodes: node = nodes.pop() results.extend(cycles(d,node)) del d[node] for other_node in d: d[other_node].discard(node)

print(results)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...