Это потому, что вы не учли обратное отслеживание. Например, скажем, ваш DFS решает перейти на [‘crocodiles’, ‘lasers’, ‘sharks’, ‘lava’, ‘piranhas’]
, что приводит к тупику. Теперь, несмотря на то, что он зашел в тупик, ‘lava’, ‘piranhas’
уже добавлен, поэтому, когда вы возвращаетесь к 'sharks'
и правильно выбираете 'bees'
, список выводится неправильно.
Чтобы решить эту проблему, вам просто нужно записать visited
перед созданием пути от текущего узла. После создания пути проверьте, присутствует ли целевой узел, а если нет, установите visited
обратно в исходное состояние:
def dfs(graph, current_vertex, target_value, visited=None):
if visited is None:
visited = []
visited.append(current_vertex)
if current_vertex == target_value:
return visited
for neighbor in graph[current_vertex]:
if neighbor not in visited:
orig = list(visited)
path = dfs(graph, neighbor, target_value, visited)
if path and target_value in path:
return path
visited = list(orig)
EDIT:
Также я должен отметить, для чего нужны list(visited)
и list(orig)
. Причиной этого является (в данном случае) глубокое копирование списков. Это означает, что изменение одного будет полностью независимым от другого. Это работает только для списков глубины 1 . Если список имеет глубину> 1, вы просто скопируете ссылку на списки внутри списка и столкнетесь с теми же проблемами. В этом случае используйте deepcopy
из copy
, импортируя его следующим образом:
from copy import deepcopy
Редактировать 2:
Лучше сделать это следующим образом, так как вам не нужно хранить копию списка:
def dfs(graph, current_vertex, target_value, visited=None):
if visited is None:
visited = []
visited.append(current_vertex)
if current_vertex == target_value:
return visited
for neighbor in graph[current_vertex]:
if neighbor not in visited:
path = dfs(graph, neighbor, target_value, visited)
if path and target_value in path:
return path
visited.pop(-1)