Википедия на самом деле имеет довольно неплохой псевдокод для обхода в глубину. Эти алгоритмы обхода маркируют все узлы на графике в порядке их появления в обходе. Вместо этого вы хотите сразу же вернуть путь к цели, когда цель найдена.
Итак, давайте изменим алгоритм Википедии:
( INCORRECT ALGORITHM DELETED WHICH THE OP COMMENTED ON CORRECTLY BELOW )
Вот реализация Python:
g = {
'A': ['B', 'C', 'D'],
'B': ['C', 'E', 'F'],
'C': ['A'],
'D': ['B', 'F', 'G', 'H'],
'E': ['G'],
'F': ['A', 'F'],
'G': ['H', 'I'],
'H': [],
'I': []
}
def DFS(g, v, goal, explored, path_so_far):
""" Returns path from v to goal in g as a string (Hack) """
explored.add(v)
if v == goal:
return path_so_far + v
for w in g[v]:
if w not in explored:
p = DFS(g, w, goal, explored, path_so_far + v)
if p:
return p
return ""
# Hack unit test
assert DFS(g, 'A', 'I', set(), "") == "ABEGI"
assert DFS(g, 'A', 'E', set(), "") == "ABE"
assert DFS(g, 'B', 'B', set(), "") == "B"
assert DFS(g, 'B', 'B', set(), "") == "B"
assert DFS(g, 'A', 'M', set(), "") == ""
assert DFS(g, 'B', 'A', set(), "") == "BCA"
assert DFS(g, 'E', 'A', set(), "") == ""
Идея в том, что вы хотите найти в графе g
путь от v
до goal
, учитывая, что вы уже прошли по пути в path_so_far
. path_so_far
должен закончиться как раз перед v
.
Если v
является целью, вы можете добавить v
к этому пути и все.
В противном случае вам нужно будет исследовать все ребра, исходящие из v
, которые еще не исследовали узлы на другом конце ребра. Для каждого из этих ребер вы можете выполнять поиск (рекурсивно), используя ваш путь до текущего узла плюс Если от v
нет пути к цели, вы вернете пустой путь.
Приятно то, что вы используете рекурсию для "автоматического возврата", потому что вы передаете расширенный путь в рекурсивный вызов.