问题描述
给定以下循环字典:
{'E': ['F'],'F': ['C','G'],'C': ['E'],'G': ['H'],'H': ['I'],'I': ['J','D'],'J': ['D'],'D': ['E']}
其中键代表父节点,值是它指向的所有子节点(这表示有向图)。
可以看出有3个周期:
- E -> F -> C
- E -> F -> G -> H -> I -> J -> D
- 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
,您将得到(E
和 print(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)