Menu
Coddy logo textTech

Algorytm Dijkstry

Ostatnia aktualizacja

Algorytm Dijkstry znajduje najkrótszą ścieżkę od węzła źródłowego do każdego innego węzła w grafie z nieujemnymi wagami krawędzi. Przechowuje tymczasową odległość każdego węzła, wielokrotnie ustala nieustalony węzeł o najmniejszej tymczasowej odległości i relaksuje jego krawędzie, czyli aktualizuje odległość sąsiada za każdym razem, gdy znajdzie krótszą trasę przez bieżący węzeł. Kliknij odtwarzanie powyżej i zobacz, jak odległości maleją, gdy kolejne węzły są ustalane.

Kluczowa idea jest zachłanna: gdy wybrany zostanie najbliższy nieustalony węzeł, jego odległość jest ostateczna, bo każda inna trasa do niego musiałaby prowadzić przez węzeł, który jest już dalej. Z kolejką priorytetową opartą na kopcu binarnym algorytm Dijkstry działa w czasie O((V + E) log V). Wymaga nieujemnych wag: jeśli krawędzie mogą być ujemne, użyj algorytmu Bellmana-Forda.

Złożoność czasowa i pamięciowa

ImplementacjaZłożonośćUwagi
Kopiec binarnyO((V + E) log V)Popularny, praktyczny wybór
Przeglądanie tablicyO(V²)Prostsze; dobre dla gęstych grafów
PamięćO(V)Odległości + kolejka priorytetowa
WymagaNieujemnych wagUjemne krawędzie psują wybór zachłanny

Krok po kroku

KrokCo się dzieje
1Ustaw odległość źródła na 0, a wszystkich pozostałych na nieskończoność.
2Wybierz nieustalony węzeł o najmniejszej tymczasowej odległości.
3Oznacz go jako ustalony: jego najkrótsza odległość jest teraz ostateczna.
4Dla każdego sąsiada oblicz odległość przez bieżący węzeł + wagę krawędzi.
5Jeśli jest mniejsza niż bieżąca odległość sąsiada, zrelaksuj ją.
6Powtarzaj, aż wszystkie osiągalne węzły będą ustalone.

Przykład krok po kroku

Najkrótsze ścieżki od źródła A w grafie z krawędziami A-B=4, A-C=1, C-B=2, C-D=5, B-D=1:

KrokUstalOdległościDziałanie
0-A=0, B=∞, C=∞, D=∞Inicjalizacja: źródło A=0, wszystkie pozostałe nieskończoność.
1A (0)B=4, C=1, D=∞Relaksuj krawędzie z A: ustaw B=4, C=1.
2C (1)B=3, D=6Przez C: B=1+2=3 jest lepsze niż 4; D=1+5=6.
3B (3)D=4Przez B: D=3+1=4 jest lepsze niż 6.
4D (4)A=0, C=1, B=3, D=4Ustal D; nie ma już nic do relaksacji. Koniec.

Kiedy używać algorytmu Dijkstry

Używaj, gdyUnikaj, gdy
Wszystkie wagi krawędzi są nieujemneKtóraś krawędź może być ujemna: użyj algorytmu Bellmana-Forda
Potrzebujesz najkrótszych ścieżek z jednego źródła do wszystkich węzłówPotrzebujesz najkrótszych ścieżek między wszystkimi parami: Floyd-Warshall jest prostszy
Graf jest ważony i chcesz dokładnych odległościGraf nie ma wag: zwykłe BFS jest szybsze i prostsze
Masz do dyspozycji dobry kopiec lub kolejkę priorytetowąChcesz szybko dotrzeć do jednego celu z pomocą heurystyki: użyj A*

Dijkstra's Algorithm: kod

Przejrzysta, gotowa do uruchomienia implementacja algorytmu Dijkstra's Algorithm w językach: Python, JavaScript, Java, C++, C. Wybierz język, skopiuj kod albo otwórz go od razu w edytorze online Coddy.

Dijkstra's Algorithm: kod (Python)

Python
1import heapq2
3
4def dijkstra(graph, start):5    dist = {node: float("inf") for node in graph}6    dist[start] = 07    pq = [(0, start)]8    while pq:9        d, node = heapq.heappop(pq)10        if d > dist[node]:11            continue  # stale entry, a shorter path was already found12        for neighbor, weight in graph[node]:13            new_dist = d + weight14            if new_dist < dist[neighbor]:15                dist[neighbor] = new_dist16                heapq.heappush(pq, (new_dist, neighbor))17    return dist18
19
20graph = {21    "A": [("B", 4), ("C", 1)],22    "B": [("D", 1)],23    "C": [("B", 2), ("D", 5)],24    "D": [("E", 3)],25    "E": [],26}27
28for node, d in dijkstra(graph, "A").items():29    print(f"A -> {node}: {d}")
Uruchom ten kod w edytorze Python online

Algorytm Dijkstry: najczęstsze pytania

Jaka jest złożoność czasowa algorytmu Dijkstry?
Z kolejką priorytetową opartą na kopcu binarnym działa w O((V + E) log V). Prosta wersja, która w każdym kroku przegląda tablicę w poszukiwaniu minimum, ma złożoność O(V²) i w gęstych grafach może być nawet szybsza. Obie zużywają O(V) pamięci.
Dlaczego algorytm Dijkstry nie działa z ujemnymi wagami krawędzi?
Algorytm Dijkstry zakłada, że gdy ustali najbliższy nieustalony węzeł, jego odległość jest ostateczna. Ujemna krawędź mogłaby później utworzyć krótszą ścieżkę do już ustalonego węzła i złamać to założenie. W grafach z ujemnymi wagami użyj algorytmu Bellmana-Forda.
Czym różni się algorytm Dijkstry od BFS?
BFS znajduje najkrótsze ścieżki, licząc krawędzie (każda krawędź ma w praktyce wagę 1), za pomocą zwykłej kolejki. Algorytm Dijkstry uogólnia to na grafy ważone, zawsze rozwijając węzeł o najmniejszej łącznej odległości za pomocą kolejki priorytetowej. W grafie bez wag oba dają te same ścieżki.
Czym różni się algorytm Dijkstry od A*?
A* to algorytm Dijkstry z heurystyką szacującą pozostałą odległość do celu, dzięki czemu kieruje przeszukiwanie w stronę celu, zamiast rozszerzać je równomiernie we wszystkich kierunkach. Gdy heurystyka wynosi zero, A* staje się dokładnie algorytmem Dijkstry. Używaj A*, gdy masz jeden cel i dobrą, dopuszczalną heurystykę; używaj algorytmu Dijkstry, gdy potrzebujesz odległości do każdego węzła.
Kiedy użyć algorytmu Dijkstry zamiast Bellmana-Forda?
Używaj algorytmu Dijkstry zawsze, gdy wszystkie wagi krawędzi są nieujemne: jest szybszy, O((V + E) log V) wobec O(V·E) w algorytmie Bellmana-Forda. Wybierz Bellmana-Forda tylko wtedy, gdy krawędzie mogą być ujemne albo musisz wykrywać ujemne cykle. W grafach z nieujemnymi wagami Dijkstra jest prawie zawsze lepszym wyborem.
Czy algorytm Dijkstry może ponownie odwiedzić ustalony węzeł?
Nie. Gdy węzeł zostanie ustalony, jego odległość jest ostateczna i nigdy nie jest ponownie relaksowana. Częsta pułapka w implementacjach z kopcem to nieaktualne wpisy w kolejce priorytetowej po poprawie odległości węzła; musisz pominąć pobrany węzeł, jeśli jest już ustalony (jego pobrana odległość przekracza zapisaną). Pominięcie tego sprawdzenia nadal daje poprawne wyniki, ale marnuje pracę.
Ilustracja języków programowania w Coddy

Opanuj algorytmy z Coddy

ZACZNIJ