Sie müssen die Pfadlängen sammeln, während Sie die Pfade erstellen. Es ist möglich, Ihren vorhandenen Code zu ändern, um dies zu tun, aber es wird unordentlich. Ein sauberer Weg, dies zu tun, besteht darin, Ihre Funktion in einen Generator umzuwandeln, so dass sie Pfade liefert, sobald sie sie finden, anstatt sie in einer Liste von Pfaden zu speichern.
Wir können die Generatorausgabe an die sorted
Funktion übergeben, um eine Liste der Pfade sortiert nach ihrer Länge zu erhalten.
import sys
graph1 = {
'e': {'a': 1, 'b': 5, 'c': 6, 'd': 6},
'a': {'e': 2, 'b': 4, 'c': 5, 'd': 5, 'k': 7},
'b': {'e': 5, 'a': 5, 'c': 3, 'd': 5, 'k': 6},
'c': {'e': 6, 'a': 5, 'b': 3, 'd': 4, 'k': 5},
'd': {'e': 6, 'a': 3, 'b': 5, 'c': 4, 'k': 2},
'k': {'a': 7, 'b': 6, 'c': 5, 'd': 2}
}
#start = input('start ')
#end = input('end ')
#required = input('via ').split(',')
#if required == ['']:
#required = []
# Hard-code some input data to make it easier to test the code
start, end = 'e', 'k'
required = []
def find_all_paths(graph, start, end, path=None, pathlen=0):
if path is None:
path = []
path = path + [start]
if start == end:
yield pathlen, path
if not start in graph:
yield [], 0
return
for node, val in graph[start].items():
if node not in path:
yield from find_all_paths(graph, node, end, path, pathlen + val)
def exists_in_graph(graph, nodes):
for node in nodes:
if not node in graph:
return False
return True
if not exists_in_graph(graph1, [start, end] + required):
print('Bad data!')
sys.exit()
all_paths = sorted(find_all_paths(graph1, start, end))
for pathlen, path in all_paths:
if exists_in_graph(path, required):
print(path, pathlen)
Ausgang
['e', 'a', 'd', 'k'] 8
['e', 'a', 'k'] 8
['e', 'd', 'k'] 8
['e', 'a', 'b', 'k'] 11
['e', 'a', 'c', 'k'] 11
['e', 'b', 'k'] 11
['e', 'c', 'k'] 11
['e', 'a', 'b', 'd', 'k'] 12
['e', 'a', 'c', 'd', 'k'] 12
['e', 'b', 'd', 'k'] 12
['e', 'c', 'd', 'k'] 12
['e', 'a', 'b', 'c', 'k'] 13
['e', 'b', 'c', 'k'] 13
['e', 'a', 'b', 'c', 'd', 'k'] 14
['e', 'b', 'c', 'd', 'k'] 14
['e', 'a', 'c', 'b', 'k'] 15
['e', 'a', 'd', 'c', 'k'] 15
['e', 'c', 'b', 'k'] 15
['e', 'd', 'c', 'k'] 15
['e', 'a', 'c', 'b', 'd', 'k'] 16
['e', 'c', 'b', 'd', 'k'] 16
['e', 'd', 'a', 'k'] 16
['e', 'a', 'd', 'b', 'k'] 17
['e', 'b', 'a', 'd', 'k'] 17
['e', 'b', 'a', 'k'] 17
['e', 'd', 'b', 'k'] 17
['e', 'c', 'a', 'd', 'k'] 18
['e', 'c', 'a', 'k'] 18
['e', 'a', 'b', 'd', 'c', 'k'] 19
['e', 'a', 'd', 'b', 'c', 'k'] 19
['e', 'a', 'd', 'c', 'b', 'k'] 19
['e', 'b', 'd', 'c', 'k'] 19
['e', 'd', 'a', 'b', 'k'] 19
['e', 'd', 'a', 'c', 'k'] 19
['e', 'd', 'b', 'c', 'k'] 19
['e', 'd', 'c', 'b', 'k'] 19
['e', 'b', 'a', 'c', 'k'] 20
['e', 'b', 'c', 'a', 'd', 'k'] 20
['e', 'b', 'c', 'a', 'k'] 20
['e', 'b', 'd', 'a', 'k'] 20
['e', 'c', 'd', 'a', 'k'] 20
['e', 'a', 'c', 'd', 'b', 'k'] 21
['e', 'b', 'a', 'c', 'd', 'k'] 21
['e', 'c', 'a', 'b', 'k'] 21
['e', 'c', 'b', 'a', 'd', 'k'] 21
['e', 'c', 'b', 'a', 'k'] 21
['e', 'c', 'd', 'b', 'k'] 21
['e', 'd', 'a', 'b', 'c', 'k'] 21
['e', 'b', 'c', 'd', 'a', 'k'] 22
['e', 'c', 'a', 'b', 'd', 'k'] 22
['e', 'd', 'c', 'a', 'k'] 22
['e', 'b', 'd', 'a', 'c', 'k'] 23
['e', 'c', 'd', 'a', 'b', 'k'] 23
['e', 'd', 'a', 'c', 'b', 'k'] 23
['e', 'd', 'b', 'a', 'k'] 23
['e', 'b', 'a', 'd', 'c', 'k'] 24
['e', 'c', 'b', 'd', 'a', 'k'] 24
['e', 'd', 'c', 'a', 'b', 'k'] 25
['e', 'd', 'c', 'b', 'a', 'k'] 25
['e', 'b', 'd', 'c', 'a', 'k'] 26
['e', 'd', 'b', 'a', 'c', 'k'] 26
['e', 'd', 'b', 'c', 'a', 'k'] 26
['e', 'c', 'a', 'd', 'b', 'k'] 27
['e', 'c', 'd', 'b', 'a', 'k'] 27
Ein anderer Weg, um die find_all_paths
Generator zu nennen, ist
valid_paths = sorted((pathlen, path)
for pathlen, path in find_all_paths(graph1, start, end)
if exists_in_graph(path, required)
)
for pathlen, path in valid_paths:
print(path, pathlen)
diese Weise können wir die unerwünschten Pfade filtern, bevor sie sortiert bekommen. Und wenn Sie nur den kürzesten Pfad wünschen, können Sie den Anruf zu sorted
mit min
ersetzen.
pathlen, path = min((pathlen, path)
for pathlen, path in find_all_paths(graph1, start, end)
if exists_in_graph(path, required)
)
print(path, pathlen)
Ausgang
['e', 'a', 'd', 'k'] 8
ich ein paar andere kleine Änderungen an Ihrem Code vorgenommen haben.
Wenn der Benutzer gibt nichts an der 'via'
Prompt dann wird required
auf eine Liste setzen Sie die leere Zeichenfolge, und das wird vermasseln Ihre exists_in_graph
Test enthalten, so dass wir required
auf die leere Liste gesetzt, wenn das passiert.
In Ihrer Version von find_all_paths
geben Sie path
einen Standardwert der leeren Liste. Das wird Dinge durcheinander bringen, wenn Sie mehr als einmal find_all_paths
aufrufen möchten, weil Standardargumente ausgewertet werden, wenn die Funktion erstellt wird, nicht wenn sie aufgerufen wird. Also, wenn Sie find_all_paths
erneut aufrufen, ohne eine path
Arg zur Verfügung zu stellen, wird es die gleiche Standard path
Liste verwenden, die es ursprünglich verwendete, es wird nicht eine neue leere Liste verwenden. Der übliche Weg, um damit umzugehen, ist, einen Standard von None
zu verwenden, wie ich es in meinem Code getan habe. Weitere Informationen zu diesem wichtigen Thema finden Sie unter “Least Astonishment” and the Mutable Default Argument.