Algorytm Dijkstry

Algorytm Dijkstry
Ilustracja
Ilustracja działania algorytmu
Rodzaj

Znajdowanie najkrótszej ścieżki

Struktura danych

graf

Złożoność
Czasowa

Pamięciowa

- przy użyciu kopca Fibonacciego

Algorytm Dijkstry, opracowany przez holenderskiego informatyka Edsgera Dijkstrę, służy do znajdowania najkrótszych ścieżek z wybranego wierzchołka do pozostałych wierzchołków w grafie o nieujemnych wagach krawędzi.

Działanie

Mając dany graf z wyróżnionym wierzchołkiem (źródłem) algorytm znajduje odległości od źródła do wszystkich pozostałych wierzchołków. Łatwo jest zmodyfikować go tak, aby szukał wyłącznie (najkrótszej) ścieżki do jednego ustalonego wierzchołka, po prostu przerywając działanie w momencie dojścia do wierzchołka docelowego, bądź transponując tablicę incydencji grafu.

Algorytm Dijkstry znajduje w grafie wszystkie najkrótsze ścieżki pomiędzy wybranym wierzchołkiem a wszystkimi pozostałymi, przy okazji wyliczając również koszt przejścia każdej z tych ścieżek.

Algorytm Dijkstry jest przykładem algorytmu zachłannego.

Algorytm

Przez oznaczamy wierzchołek źródłowy, to waga krawędzi w grafie.

Na końcu tablica zawiera najkrótsze odległości do wszystkich wierzchołków.

Dodatkowo możemy w tablicy poprzednik przechowywać dla każdego wierzchołka numer jego bezpośredniego poprzednika na najkrótszej ścieżce, co pozwoli na odtworzenie pełnej ścieżki od źródła do każdego wierzchołka – przy każdej relaksacji w ostatnim punkcie staje się poprzednikiem

Zastosowanie

Z algorytmu Dijkstry można skorzystać przy obliczaniu najkrótszej drogi do danej miejscowości. Wystarczy przyjąć, że każdy z punktów skrzyżowań dróg to jeden z wierzchołków grafu, a odległości między punktami to wagi krawędzi.

Jest często używany w sieciach komputerowych, np. przy trasowaniu (przykładowo w protokole OSPF).

Pseudokod

Dijkstra(G,w,s):
   dla każdego wierzchołka v w V[G] wykonaj
      d[v] := nieskończoność
      poprzednik[v] := niezdefiniowane
   d[s] := 0
   Q := V
   dopóki Q niepuste wykonaj
      u := Zdejmij_Min(Q)
      dla każdego wierzchołka v – sąsiada u wykonaj
         jeżeli d[v] > d[u] + w(u, v) to
            d[v] := d[u] + w(u, v)
            poprzednik[v] := u
 

   Wyświetl("Droga wynosi: " + d[v])

Dowód poprawności

Oznaczmy przez zbiór wierzchołków, które zostały już zdjęte z kolejki. Dowód opiera się na następujących dwóch faktach (niezmiennikach), prawdziwych przez cały czas trwania algorytmu:

  1. Dla każdego wierzchołka liczba jest długością najkrótszej ścieżki od do
  2. Dla każdego wierzchołka jest długością najkrótszej ścieżki do prowadzącej tylko przez wierzchołki z

Na początku oba fakty są oczywiste ( jest zbiorem pustym). Przy zdejmowaniu wierzchołka z kolejki wiemy, na podstawie faktu 2, że nie da się do niego dojść żadną krótszą drogą przez wierzchołki z Z drugiej strony, ponieważ ma najniższy priorytet, przejście przez jakikolwiek inny wierzchołek spoza dałoby od razu co najmniej tak samo długą ścieżkę. A zatem dołączając wierzchołek do zachowujemy prawdziwość faktu 1. Następnie musimy uwzględnić fakt, że najkrótsza ścieżka do jakiegoś wierzchołka po wierzchołkach z nowego zbioru może teraz zawierać wierzchołek Ale wtedy musi on być ostatnim na niej wierzchołkiem (do każdego innego dałoby się dojść krócej, nie używając ), a zatem jej długość równa jest i zostanie prawidłowo obliczona w następnym kroku algorytmu.

Złożoność

Złożoność obliczeniowa algorytmu Dijkstry zależy od liczby wierzchołków i krawędzi grafu. O rzędzie złożoności decyduje implementacja kolejki priorytetowej:

Pierwszy wariant jest optymalny dla grafów gęstych (czyli jeśli ), drugi jest szybszy dla grafów rzadkich trzeci jest bardzo rzadko używany ze względu na duży stopień skomplikowania i niewielki w porównaniu z nim zysk czasowy.

Problemy i algorytmy pokrewne

Algorytm Dijkstry nie działa, jeśli w grafie występują krawędzie z ujemnymi wagami – w tym wypadku używa się wolniejszego, lecz bardziej ogólnego algorytmu Bellmana-Forda. Jeśli graf nie jest ważony (wszystkie wagi mają wielkość 1), zamiast algorytmu Dijkstry wystarczy algorytm przeszukiwania grafu wszerz.

Algorytm A* jest pewnym uogólnieniem algorytmu Dijkstry, które pozwala przeszukiwać tylko część grafu, jednak wymaga dodatkowej wstępnej informacji (heurystyki) o odległościach wierzchołków.

Algorytm Prima znajdowania minimalnego drzewa rozpinającego oparty jest na koncepcji bardzo podobnej do algorytmu Dijkstry.

Przypisy

  1. ↑ Algorytm Dijkstry. edu.i-lo.tarnow.pl. [zarchiwizowane z tego adresu (2009-01-25)]..
  2. ↑ Algorytm Dijkstry.

Bibliografia

Linki zewnętrzne