Алгоритм Дейкстры, в котором следующий узел ищется перебором всех необработанных узлов — как в реализации из книги. В графе V вершин и E рёбер. Определите время выполнения.
Поиск минимума перебором
Код
import math
def find_lowest(costs: dict[str, float], processed: set[str]) -> str | None:
lowest, lowest_node = math.inf, None
for node, cost in costs.items():
if cost < lowest and node not in processed:
lowest, lowest_node = cost, node
return lowest_node
def dijkstra(graph: dict[str, dict[str, int]], costs: dict[str, float]) -> dict[str, float]:
processed: set[str] = set()
node = find_lowest(costs, processed)
while node is not None:
for neighbor, weight in graph[node].items():
if costs[node] + weight < costs[neighbor]:
costs[neighbor] = costs[node] + weight
processed.add(node)
node = find_lowest(costs, processed)
return costsКакое время выполнения?
Ответ: O(V²)
Цикл выполняется V раз, и каждый раз find_lowest просматривает все V вершин — это O(V²). Обновления соседей в сумме занимают O(E), а рёбер не больше V², поэтому O(V² + E) = O(V²). Если хранить кандидатов в очереди с приоритетом (heapq), выйдет O((V + E) log V) — это быстрее на разреженных графах.
- Подсказка 1
Сколько раз выполняется внешний цикл while? Каждый раз одна вершина становится обработанной.
- Подсказка 2
Сколько стоит find_lowest при V вершинах? А сколько всего раз выполняется обновление соседей, если сложить по всем вершинам?