Rozważmy wykres tak:
A---(3)-----B
| |
\-(1)-C--(1)/
najkrótszej ścieżki od A do B jest przez C (z całkowitej masy 2). Normalny BFS przejdzie ścieżką bezpośrednio z punktu A do punktu B, oznaczając B jako widoczny i od A do C, oznaczając literę C, jak widać.
W następnym etapie propagowanie z C, B jest już oznaczone jako widoczne, więc ścieżka od C do B nie będzie traktowana jako potencjalnie krótsza ścieżka, a BFS poinformuje cię, że najkrótsza ścieżka od A do B ma wagę 3.
Możesz użyć Dijkstra's algorithm zamiast BFS, aby znaleźć najkrótszą ścieżkę na ważonym wykresie. Funkcjonalnie algorytm jest bardzo podobny do BFS i może być napisany w sposób podobny do BFS. Jedyną zmianą jest kolejność, w której rozpatrujesz węzły.
Na przykład na powyższym wykresie, zaczynając od A, BFS przetworzy A -> B, następnie A -> C, i zatrzyma się tam, ponieważ widoczne są wszystkie węzły.
Z drugiej strony, algorytm Dijkstry działa w następujący sposób:
- Rozważmy -> C (ponieważ jest to waga najniższej krawędzi od a)
- Rozważmy C -> B (ponieważ jest to najniższa waga z każdego węzła, do którego dotarliśmy do tej pory, którego jeszcze nie rozważaliśmy)
- Rozważ i zignoruj A -> B, ponieważ B było już widziane.
Należy zauważyć, że różnica leży po prostu w zamówieniu, w której sprawdzane są krawędzie. BFS rozważy wszystkie krawędzie z jednego węzła przed przejściem do innych węzłów, podczas gdy Algorytm Dijkstry zawsze rozważyć najniższą masy niewidzialny kant, ze zbioru krawędzi podłączonego do wszystkie węzły, które były widoczne tak daleko.Brzmi to dziwne, ale pseudokod jest bardzo prosta:
create a heap or priority queue
place the starting node in the heap
dist[2...n] = {∞}
dist[1] = 0
while the heap contains items:
vertex v = top of heap
pop top of heap
for each vertex u connected to v:
if dist[u] > dist[v] + weight of v-->u:
dist[u] = dist[v] + weight of edge v-->u
place u on the heap with weight dist[u]
Ten GIF z Wikipedii zapewnia dobrą wizualizację tego, co się dzieje:
Zauważ, że wygląda to bardzo podobny do kodu BFS, jedyną istotną różnicą jest użycie sterty, posortowanej według odległości do węzła, zamiast zwykłej struktury danych kolejki o nazwie.
Dziękuję, ale mam wątpliwości. Wyjaśniłeś, jak Dijkstra pracował dla powyższego przykładu i wybrał ścieżkę z A-> C, ponieważ ma najniższą wagę krawędzi do C. Załóżmy, że krawędź z C-> B miała wagę 4 i była krawędź od A -> D (waga 3) i D-> B (waga 1). Przechodząc według tego, co powiedziałeś, krawędź A-> C i C-> B przechodzi najpierw, prawda? Wtedy myślę, że krawędź z A-> D i D-> B musi być pokonywana, chociaż B było widziane inaczej, gdybyśmy nie mieli najkrótszej ścieżki. Jak więc możemy zignorować tę ścieżkę? Sądzę, że wspomniałeś o tym w punkcie 3. Popraw mnie, jeśli się mylę? :/.. Dzięki – user2125722
@ user2125722 A-> C będzie wykonywany najpierw, ponieważ jest to najniższa krawędź wagi, następnie A-> B i A-> D, następnie D-> B, a następnie C-> B. Jeśli nie rozumiesz, dlaczego tak jest, spróbuj przejść przez pseudokod dla algorytmu dla tego wykresu. – Greg
@ user2125722 zauważ, że definicja * seen * w algorytmie Dijkstry jest nieco inna. Zaktualizowałem kod, aby wyraźniej odzwierciedlać faktyczne wydarzenia. – Greg