Algorytm Dijkstry znajdowania najkrótszej ścieżki w grafie Używane struktury danych: V - zbiór wierzchołków grafu, V = {1,2,3...,n} E - zbiór krawędzi grafu, E = {(i,j),...}, gdzie i, j Î V i istnieje krawędź pomiędzy i,j (graf nieskierowany) lub od i do j (graf skierowany) v o - wybrany wierzchołek grafu, v o Î V, który jest początkiem wyznaczania najkrótszych ścieżek do wszystkich pozostałych wierzchołków d(i) - koszt dojścia od wierzchołka vo do wierzchołka i-tego wzdłuż najkrótszej ścieżki. Koszt dojścia jest sumą wag krawędzi, przez które przechodzimy posuwając się wzdłuż wyznaczonej najkrótszej ścieżki. p(i) - dla i-tego wierzchołka grafu p(i) zawiera numer wierzchołka poprzedzającego na najkrótszej ścieżce waga(i,j) - waga ścieżki pomiędzy wierzchołkami i oraz j (graf nieskierowany) lub od wierzchołka i-tego do j-tego (graf skierowany) S - zbiór wierzchołków grafu o policzonych już najkrótszych ścieżkach od wybranego wierzchołka v o Q - zbiór wierzchołków grafu, dla których najkrótsze ścieżki nie zostały jeszcze policzone Dane wejściowe n, V, E, v o Dane wyjściowe Dla każdego wierzchołka i należącego do V algorytm wyznacza koszt dojścia d(i) oraz poprzednika p(i) na najkrótszej ścieżce. K01: S Ø; Q V K02: Dla i = 1,2,...,n : p(i) 0; d(i) K03: d(v o ) 0 K04: Dopóki Q Ø wykonuj kroki od K05 do K07 K05: u wierzchołek ze zbioru Q o najmniejszym d(u) K06: Q Q \ u; S S u K07: Dla każdego v Q, takiego że krawędź (u,v) E, jeśli d(v) > d(u) + waga(u,v), to d(v) d(u) + waga(u,v); p(v) u K08: Zakończ algorytm
Działanie algorytmu Dijkstry dla przykładowego grafu. Dany jest graf skierowany G = (V,E): V = {1,2,3,4,5,6} E = {(1-2,3),(1-4,3),(2-3,2),(3-1,6),(3-6,1),(4-5,1),(5-3,1),(5-6,2),(6-4,3)} W grafie wyróżniamy jeden z wierzchołków. Tutaj jest to wierzchołek 1. Będziemy wyznaczać najniższe koszty dojścia od wyróżnionego wierzchołka do wszystkich pozostałych wierzchołków w grafie oraz najkrótsze ścieżki pomiędzy wyróżnionym wierzchołkiem, a wszystkimi pozostałymi wierzchołkami w grafie. Tworzymy dwa zbiory S (wierzchołki, dla których są policzone najkrótsze ścieżki) oraz Q (wierzchołki jeszcze nie przetworzone). Zbiór S jest początkowo pusty. Zbiór Q obejmuje wszystkie wierzchołki grafu. Dla każdego wierzchołka v ustawiamy d(v). Dla wybranego wierzchołka v o ustawiamy d(v o ) 0. Ustawiamy również p(v) 0. d(indeks) 0 p(indeks) 0 0 0 0 0 0 Jest to wierzchołek 1 (czyli nasze v o ). Wierzchołek ten przenosimy do zbioru S. Następnie sprawdzamy wartość d wszystkich sąsiadów przeniesionego wierzchołka (2 i 4). Jeśli ich d jest większe od kosztu d(1) + waga krawędzi do sprawdzanego wierzchołka, to modyfikujemy odpowiednio d i p dla tych wierzchołków. d(indeks) 0 3 3 p(indeks) 0 1 0 1 0 0
Są dwa takie wierzchołki: 2 i 4 o d=3. Wybieramy arbitralnie wierzchołek nr 2 i przenosimy go do zbioru S. Wierzchołek 2 posiada tylko jednego sąsiada - 3. Modyfikujemy odpowiednio d[3] i p[3]. d(indeks) 0 3 5 3 p(indeks) 0 1 2 1 0 0 Teraz jest to wierzchołek 4 o d[4] = 3. Przenosimy go do zbioru S. Wierzchołek 4 posiada tylko jednego sąsiada - 5. Modyfikujemy odpowiednio d[5] i p[5]. d(indeks) 0 3 5 3 4 p(indeks) 0 1 2 1 4 0 Jest to wierzchołek 5 o d[5] = 4. Przenosimy go do zbioru S. Wierzchołek 5 posiada dwóch sąsiadów: 3 i 6. Ponieważ d[3]=5 jest takie samo jak d[5] + waga(5-3) = 4+1=5, nie modyfikujemy parametrów d i p dla wierzchołka 3. Do modyfikacji jest tylko wierzchołek 6. Jest to wierzchołek 3 o d[3] = 5. Przenosimy go do zbioru S. Wierzchołek 3 posiada dwóch sąsiadów: 1 i 6. Ponieważ wierzchołek 1 jest już w zbiorze S, to nie bierzemy go pod uwagę. Drugi wierzchołek posiada d[6]=6, czyli takie samo jak d[3]+waga(3-6)=5+1=6. Nie modyfikujemy zatem wierzchołka 6.
Do zbioru S przenosimy ostatni wierzchołek z Q. Wierzchołek ten nie posiada sąsiadów w Q połączonych z nim krawędzią, dlatego nic nie modyfikujemy. Ponieważ zbiór Q stał się pusty, algorytm kończymy. Po zakończeniu algorytmu w tablicy d mamy najmniejsze koszty dojścia do poszczególnych wierzchołków w grafie. Np. minimalny koszt przejścia z wierzchołka 1 do 6 wynosi d(6)=6, a z 1 do 5 wynosi d(5)=4. Informacja o najkrótszych ścieżkach zakodowana jest w tablicy p, która dla węzła i-tego określa jego bezpośredniego poprzednika p(i) na tej ścieżce. Informacja podana w ten sposób pozwala nam się cofać po ścieżce wstecz, czyli przejść ją od jej końca do początku. Aby uzyskać odpowiedni ciąg wierzchołków musimy postępować wg poniższego algorytmu: Wejście i - numer wierzchołka grafu, do którego ma prowadzić ścieżka z wybranego wierzchołka p - tablica poprzedników na najkrótszej ścieżce dla poszczególnych wierzchołków grafu Wyjście L - lista kolejnych wierzchołków najkrótszej ścieżki od wybranego wierzchołka grafu do wierzchołka i-tego K01: L Ø K02: Dopóki i 0, wykonuj kroki od K03 do K04 K03: Wstaw i na początek listy L K04: i p(i) K05: Zakończ algorytm Do odwrócenia kolejności wierzchołków można również wykorzystać strukturę stosu. K01: Zeruj stos K02: Dopóki i 0, wykonuj kroki od K03 do K04 K03: Umieść i na stosie K04: i p(i)
K05: Dopóki stos nie jest pusty, pobierz wierzchołek ze stosu i prześlij go na wyjście K06: Zakończ algorytm