logo

Co to jest algorytm Dijkstry? | Wprowadzenie do algorytmu najkrótszej ścieżki Dijkstry

W tym artykule omówimy jeden z najbardziej znanych algorytmów najkrótszej ścieżki, czyli algorytm najkrótszej ścieżki Dijkstry, który został opracowany przez holenderskiego informatyka Edsgera W. Dijkstrę w 1956 roku. Ponadto przeprowadzimy analizę złożoności tego algorytmu, a także zobacz, czym różni się od innych algorytmów najkrótszej ścieżki.

Spis treści

Algorytm-Dijkstra-(1)



Algorytm Dijkstry:

Algorytm Dijkstry to popularny algorytm rozwiązywania wielu problemów z najkrótszą ścieżką z jednego źródła, mających nieujemną wagę krawędzi na grafach, tj. polega na znalezieniu najkrótszej odległości między dwoma wierzchołkami grafu. Został wymyślony przez holenderskiego informatyka Edsger W. Dijkstra w 1956 r.

Algorytm przechowuje zbiór odwiedzonych wierzchołków i zbiór nieodwiedzonych wierzchołków. Zaczyna się od wierzchołka źródłowego i iteracyjnie wybiera nieodwiedzony wierzchołek o najmniejszej wstępnej odległości od źródła. Następnie odwiedza sąsiadów tego wierzchołka i aktualizuje ich wstępne odległości, jeśli zostanie znaleziona krótsza ścieżka. Proces ten trwa aż do osiągnięcia wierzchołka docelowego lub odwiedzenia wszystkich osiągalnych wierzchołków.

Potrzeba algorytmu Dijkstry (cel i przypadki użycia)

Zapotrzebowanie na algorytm Dijkstry pojawia się w wielu zastosowaniach, w których kluczowe znaczenie ma znalezienie najkrótszej ścieżki między dwoma punktami.

Na przykład , Może być używany w protokołach routingu w sieciach komputerowych, a także używany przez systemy map do znalezienia najkrótszej ścieżki między punktem początkowym a miejscem docelowym (jak wyjaśniono w Jak działają Mapy Google? )

Czy algorytm Dijkstry może działać zarówno na grafach skierowanych, jak i nieskierowanych?

Tak , algorytm Dijkstry może pracować zarówno na grafach skierowanych, jak i nieskierowanych, ponieważ algorytm ten jest przeznaczony do pracy na dowolnym typie grafów, o ile spełnia wymagania dotyczące posiadania nieujemnych wag krawędzi i spójności.

  • Na grafie skierowanym każda krawędź ma kierunek, wskazujący kierunek ruchu pomiędzy wierzchołkami połączonymi krawędzią. W tym przypadku algorytm poszukuje najkrótszej ścieżki podążając za kierunkiem krawędzi.
  • Na grafie nieskierowanym krawędzie nie mają kierunku, a algorytm może przemieszczać się wzdłuż krawędzi zarówno do przodu, jak i do tyłu, szukając najkrótszej ścieżki.

Algorytm algorytmu Dijkstry:

  1. Oznacz węzeł źródłowy bieżącą odległością 0, a resztę nieskończonością.
  2. Ustaw nieodwiedzony węzeł o najmniejszej bieżącej odległości jako bieżący węzeł.
  3. Dla każdego sąsiada N bieżącego węzła dodaje bieżącą odległość sąsiedniego węzła z wagą krawędzi łączącej 0->1. Jeśli jest mniejsza niż bieżąca odległość węzła, ustaw ją jako nową aktualną odległość N.
  4. Oznacz bieżący węzeł 1 jako odwiedzony.
  5. Przejdź do kroku 2, jeśli są jakieś nieodwiedzone węzły.

Jak działa algorytm Dijkstry?

Zobaczmy, jak działa algorytm Dijkstry na przykładzie podanym poniżej:

Algorytm Dijkstry wygeneruje najkrótszą ścieżkę od węzła 0 do wszystkich pozostałych węzłów na wykresie.

Rozważ poniższy wykres:

Dijkstra

Algorytm Dijkstry

Algorytm wygeneruje najkrótszą ścieżkę od węzła 0 do wszystkich pozostałych węzłów na grafie.

W przypadku tego wykresu założymy, że waga krawędzi reprezentuje odległość między dwoma węzłami.

co to jest stos w Javie

Jak widzimy, mamy najkrótszą ścieżkę z,
Węzeł 0 do węzła 1, od
Węzeł 0 do węzła 2, od
Węzeł 0 do węzła 3, od
Węzeł 0 do węzła 4, od
Węzeł 0 do węzła 6.

Początkowo mamy zestaw zasobów podany poniżej:

  • Odległość od węzła źródłowego do niego samego wynosi 0. W tym przykładzie węzeł źródłowy wynosi 0.
  • Odległość od węzła źródłowego do wszystkich pozostałych węzłów jest nieznana, dlatego wszystkie oznaczamy jako nieskończoność.

Przykład: 0 -> 0, 1-> ∞,2-> ∞,3-> ∞,4-> ∞,5-> ∞,6-> ∞.

  • będziemy mieli także tablicę nieodwiedzonych elementów, które będą śledzić nieodwiedzone lub nieoznaczone węzły.
  • Algorytm zakończy się, gdy wszystkie węzły zostaną oznaczone jako odwiedzone, a odległość między nimi zostanie dodana do ścieżki. Nieodwiedzone węzły:- 0 1 2 3 4 5 6.

Krok 1: Zacznij od węzła 0 i oznacz węzeł jako odwiedzony, jak możesz sprawdzić na obrazku poniżej odwiedzony węzeł jest zaznaczony na czerwono.

Dijkstra

Algorytm Dijkstry

Krok 2: Sprawdź sąsiadujące węzły. Teraz mamy wybór (albo wybierz Węzeł 1 z odległością 2, albo wybierz Węzeł 2 z odległością 6) i wybierz Węzeł z minimalną odległością. W tym kroku Węzeł 1 to Minimalna odległość sąsiadującego węzła, więc oznacz go jako odwiedzony i zsumuj odległość.

Odległość: węzeł 0 -> węzeł 1 = 2

Dijkstra

Algorytm Dijkstry

Krok 3: Następnie przejdź dalej i sprawdź sąsiadujący węzeł, którym jest węzeł 3, więc oznacz go jako odwiedzony i dodaj odległość. Teraz odległość będzie wynosić:

Odległość: węzeł 0 -> węzeł 1 -> węzeł 3 = 2 + 5 = 7

Dijkstra

Algorytm Dijkstry

Krok 4: Ponownie mamy dwie możliwości dla sąsiednich węzłów (albo możemy wybrać węzeł 4 z odległością 10, albo możemy wybrać węzeł 5 z odległością 15), więc wybierz węzeł z minimalną odległością. W tym kroku Węzeł 4 to Minimalna odległość sąsiadującego węzła, więc oznacz go jako odwiedzony i zsumuj odległość.

Odległość: Węzeł 0 -> Węzeł 1 -> Węzeł 3 -> Węzeł 4 = 2 + 5 + 10 = 17

Dijkstra

Algorytm Dijkstry

prymitywne typy danych w Javie

Krok 5: Ponownie przejdź do przodu i sprawdź sąsiadujący węzeł, który jest Węzeł 6 , więc oznacz jako odwiedzone i zsumuj odległość. Teraz odległość będzie wynosić:

Odległość: Węzeł 0 -> Węzeł 1 -> Węzeł 3 -> Węzeł 4 -> Węzeł 6 = 2 + 5 + 10 + 2 = 19

Dijkstra

Algorytm Dijkstry

Zatem najkrótsza odległość od wierzchołka źródłowego wynosi 19, co jest wartością optymalną

Pseudokod algorytmu Dijkstry

funkcja Dijkstra(Wykres, źródło):
// Zainicjuj odległości do wszystkich węzłów jako nieskończoność, a do węzła źródłowego jako 0.

odległości = mapa (wszystkie węzły -> nieskończoność)

odległości = 0

połączenie sql

// Zainicjuj pusty zestaw odwiedzonych węzłów i kolejkę priorytetową, aby śledzić węzły do ​​odwiedzenia.
odwiedzony = pusty zestaw
kolejka = nowa Kolejka Priorytetów()
kolejka.enqueue(źródło, 0)

// Pętla do momentu odwiedzenia wszystkich węzłów.
póki kolejka nie jest pusta:
// Usuń z kolejki węzeł znajdujący się w najmniejszej odległości od kolejki priorytetowej.
bieżący = kolejka.dequeue()

// Jeśli węzeł był już odwiedzony, pomiń go.
jeśli aktualnie odwiedzasz:
Kontynuować

// Oznacz węzeł jako odwiedzony.
odwiedził.add(bieżący)

// Sprawdź wszystkie sąsiednie węzły, aby zobaczyć, czy ich odległości wymagają aktualizacji.
dla sąsiada w Graph.neighbors(current):
// Oblicz wstępną odległość do sąsiada przez bieżący węzeł.
tentative_distance = odległości [bieżący] + Graph.distance (bieżący, sąsiad)

// Jeśli wstępna odległość jest mniejsza niż bieżąca odległość do sąsiada, zaktualizuj odległość.
jeśli wstępna_odległość
odległości[sąsiad] = odległość_wstępna

// Kolejkuj sąsiada z jego nową odległością, aby uwzględnić go w przyszłych wizytach.
kolejka.enqueue(sąsiad, odległości[sąsiad])

// Zwraca obliczone odległości od źródła do wszystkich pozostałych węzłów na wykresie.
odległości powrotne

Implementacja algorytmu Dijkstry:

Istnieje kilka sposobów implementacji algorytmu Dijkstry, ale najczęstsze z nich to:

  1. Kolejka priorytetowa (implementacja oparta na stercie):
  2. Implementacja oparta na tablicach:

1. Algorytm najkrótszej ścieżki Dijkstry wykorzystujący kolejkę priorytetową (sterta)

W tej implementacji otrzymujemy graf i wierzchołek źródłowy na grafie, znajdując najkrótszą ścieżkę od źródła do wszystkich wierzchołków w danym grafie.

Przykład:

Wejście: Źródło = 0

Rohit Shetty, aktor

Przykład

Wyjście: Wierzchołek

Odległość wierzchołka od źródła

0 -> 0
1 -> 2
2 -> 6
3 -> 7
4 -> 17
5 -> 22
6 -> 19

Poniżej znajduje się algorytm oparty na powyższym pomyśle:

  • Zainicjuj wartości odległości i kolejkę priorytetową.
  • Wstaw węzeł źródłowy do kolejki priorytetowej z odległością 0.
  • Chociaż kolejka priorytetowa nie jest pusta:
    • Wyodrębnij węzeł z minimalną odległością od kolejki priorytetowej.
    • Zaktualizuj odległości sąsiadów, jeśli zostanie znaleziona krótsza ścieżka.
    • Wstaw zaktualizowanych sąsiadów do kolejki priorytetowej.

Poniżej znajduje się implementacja C++ powyższego podejścia:

C++
// Program to find Dijkstra's shortest path using // priority_queue in STL #include  using namespace std; #define INF 0x3f3f3f3f // iPair ==>Para całkowita typedef para iPara; // Ta klasa reprezentuje graf skierowany za pomocą // klasy reprezentacji listy sąsiedztwa Graph { int V; // Liczba wierzchołków // W grafie ważonym musimy przechowywać wierzchołki // i parę wag dla każdej listy krawędzi>* przym.; public: Graph(int V); // Konstruktor // funkcja dodająca krawędź do wykresu void addEdge(int u, int v, int w);  // drukuje najkrótszą ścieżkę z s void shortestPath(int s); }; // Przydziela pamięć dla listy sąsiedztwa Graph::Graph(int V) { this->V = V;  adj = nowa lista [V]; } void Graph::addEdge(int u, int v, int w) { adj[u].push_back(make_pair(v, w));  adj[v].push_back(make_pair(u, w)); } // Drukuje najkrótsze ścieżki od src do wszystkich pozostałych wierzchołków void Graph::shortestPath(int src) { // Utwórz kolejkę priorytetową do przechowywania wierzchołków, które // są wstępnie przetwarzane. To dziwna składnia w C++.  // Link poniżej zawiera szczegółowe informacje na temat tej składni // https://www.techcodeview.com priorytet_queue , większy > pq;  // Utwórz wektor odległości i zainicjuj // wszystkie odległości jako wektory nieskończone (INF). odst(V, INF);  // Wstaw źródło do kolejki priorytetowej i zainicjuj // jego odległość jako 0. pq.push(make_pair(0, src));  odległość[źródło] = 0;  /* Zapętlanie do momentu, aż kolejka priorytetowa stanie się pusta (lub nie zostaną sfinalizowane wszystkie odległości) */ while (!pq.empty()) { // Pierwszy wierzchołek pary to minimalna odległość // wierzchołek, wyodrębnij go z kolejki priorytetowej.  // etykieta wierzchołka jest przechowywana w drugiej parze ( // należy to zrobić w ten sposób, // aby zachować // posortowaną odległość wierzchołków (odległość musi być pierwszym elementem // w parze) int u = pq.top().sekunda; pq.pop(); // 'i' służy do pobrania wszystkich sąsiadujących wierzchołków // listy wierzchołków>::iterator i;  for (i = adj[u].begin(); i != adj[u].end(); ++i) { // Uzyskaj etykietę wierzchołka i wagę bieżącego // sąsiadującego z u.  int v = (*i).pierwszy;  int waga = (*i).sekunda;  // Jeśli ścieżka od v do u jest krótka.  if (dist[v]> dist[u] + waga) { // Aktualizowanie odległości v dist[v] = dist[u] + waga;  pq.push(make_pair(odległość[v], v));  } } } // Wydrukuj najkrótsze odległości zapisane w dist[] printf('Odległość wierzchołka od źródła
');  for (int i = 0; tj< V; ++i)  printf('%d 		 %d
', i, dist[i]); } // Driver program to test methods of graph class int main() {  // create the graph given in above figure  int V = 7;  Graph g(V);  // making above shown graph  g.addEdge(0, 1, 2);  g.addEdge(0, 2, 6);  g.addEdge(1, 3, 5);  g.addEdge(2, 3, 8);  g.addEdge(3, 4, 10);  g.addEdge(3, 5, 15);  g.addEdge(4, 6, 2);  g.addEdge(5, 6, 6);  g.shortestPath(0);  return 0; }>
Jawa
import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.PriorityQueue; public class DijkstraAlgoForShortestDistance {  static class Node implements Comparable{  w telewizji;  int odległość;  public Node(int v, int odległość) { this.v = v;  this.distance = odległość;  } @Override public int CompareTo(węzeł n) { if (this.distance<= n.distance) {  return -1;  }  else {  return 1;  }  }  }  static int[] dijkstra(  int V,  ArrayList >> adj, int S) { boolean[] odwiedzone = nowe boolean[V];  HashMapa mapa = nowa HashMap();  Kolejka priorytetowaq = nowa Kolejka Priorytetów();  map.put(S, nowy węzeł(S, 0));  q.add(nowy węzeł(S, 0));  while (!q.isEmpty()) { Węzeł n = q.poll();  int v = n.v;  int odległość = n.odległość;  odwiedziliśmy[v] = prawda;  Lista tablic > adjList = adj.get(v);  dla (ArrayList adjLink : adjList) { if (visited[adjLink.get(0)] == false) { if (!map.containsKey(adjLink.get(0))) { map.put( adjLink.get(0), nowy węzeł (v, odległość + adjLink.get(1)));  } else { Węzeł sn = map.get(adjLink.get(0));  if (odległość + adjLink.get(1)< sn.distance) {  sn.v = v;  sn.distance  = distance + adjLink.get(1);  }  }  q.add(new Node(adjLink.get(0),  distance  + adjLink.get(1)));  }  }  }  int[] result = new int[V];  for (int i = 0; i < V; i++) {  result[i] = map.get(i).distance;  }  return result;  }  public static void main(String[] args)  {  ArrayList >> adj = nowa ArrayList();  HashMapa >> mapa = nowa HashMap();  int V = 6;  int E = 5;  int[] u = { 0, 0, 1, 2, 4 };  int[] v = { 3, 5, 4, 5, 5 };  int[] w = { 9, 4, 4, 10, 3 };  for (int i = 0; tj< E; i++) {  ArrayList krawędź = nowa ArrayList();  krawędź.add(v[i]);  krawędź.add(w[i]);  Lista tablic > adjLista;  if (!map.containsKey(u[i])) { adjList = nowa ArrayList();  } else { adjList = map.get(u[i]);  } adjList.add(krawędź);  map.put(u[i], adjList);  Lista tablic krawędź2 = nowa ArrayList();  Edge2.add(u[i]);  Edge2.add(w[i]);  Lista tablic > adjLista2;  if (!map.containsKey(v[i])) { adjList2 = nowa ArrayList();  } else { adjList2 = map.get(v[i]);  } adjList2.add(krawędź2);  map.put(v[i], adjList2);  } for (int i = 0; tj< V; i++) {  if (map.containsKey(i)) {  adj.add(map.get(i));  }  else {  adj.add(null);  }  }  int S = 1;  // Input sample  //[0 [[3, 9], [5, 4]],  // 1 [[4, 4]],  // 2 [[5, 10]],  // 3 [[0, 9]],  // 4 [[1, 4], [5, 3]],  // 5 [[0, 4], [2, 10], [4, 3]]  //]  int[] result  = DijkstraAlgoForShortestDistance.dijkstra(  V, adj, S);  System.out.println(Arrays.toString(result));  } }>
Pyton
# Python implementation of Dijkstra Algorithm import heapq class Node: def __init__(self, v, distance): self.v = v self.distance = distance def __lt__(self, other): return self.distance < other.distance def dijkstra(V, adj, S): visited = [False] * V map = {} q = [] map[S] = Node(S, 0) heapq.heappush(q, Node(S, 0)) while q: n = heapq.heappop(q) v = n.v distance = n.distance visited[v] = True adjList = adj[v] for adjLink in adjList: if not visited[adjLink[0]]: if adjLink[0] not in map: map[adjLink[0]] = Node(v, distance + adjLink[1]) else: sn = map[adjLink[0]] if distance + adjLink[1] < sn.distance: sn.v = v sn.distance = distance + adjLink[1] heapq.heappush(q, Node(adjLink[0], distance + adjLink[1])) result = [0] * V for i in range(V): result[i] = map[i].distance return result def main(): adj = [[] for _ in range(6)] V = 6 E = 5 u = [0, 0, 1, 2, 4] v = [3, 5, 4, 5, 5] w = [9, 4, 4, 10, 3] for i in range(E): edge = [v[i], w[i]] adj[u[i]].append(edge) edge2 = [u[i], w[i]] adj[v[i]].append(edge2) S = 1 result = dijkstra(V, adj, S) print(result) if __name__ == '__main__': main() # This code is contributed by ragul21>
C#
// C# Code: using System; using System.Collections.Generic; public class Graph {  // No. of vertices  private int V;  // adjacency list  private List>[] przym.;  // Konstruktor public Graph(int v) { V = v;  adj = nowa lista>[v];  for (int i = 0; tj< v; ++i)  adj[i] = new List>();  } // funkcja dodająca krawędź do wykresu public void addEdge(int u, int v, int w) { adj[u].Add(Tuple.Create(v, w));  adj[v].Add(Tuple.Create(u, w));  } // drukuje najkrótszą ścieżkę z publicznego void shortestPath(int s) { // Utwórz kolejkę priorytetową do przechowywania wierzchołków, które // są wstępnie przetwarzane.  var pq = nowa kolejka priorytetów>();  // Utwórz wektor odległości i zainicjalizuj // wszystkie odległości jako nieskończone (INF) var dist = new int[V];  for (int i = 0; tj< V; i++)  dist[i] = int.MaxValue;  // Insert source itself in priority queue and  // initialize its distance as 0.  pq.Enqueue(Tuple.Create(0, s));  dist[s] = 0;  /* Looping till priority queue becomes empty (or all  distances are not finalized) */  while (pq.Count != 0) {  // The first vertex in pair is the minimum  // distance vertex, extract it from priority  // queue. vertex label is stored in second of  // pair (it has to be done this way to keep the  // vertices sorted distance (distance must be  // first item in pair)  var u = pq.Dequeue().Item2;  // 'i' is used to get all adjacent vertices of a  // vertex  foreach(var i in adj[u])  {  // Get vertex label and weight of current  // adjacent of u.  int v = i.Item1;  int weight = i.Item2;  // If there is shorted path to v through u.  if (dist[v]>dist[u] + waga) { // Aktualizacja odległości v dist[v] = dist[u] + waga;  pq.Enqueue(Tuple.Create(odległość[v], v));  } } } // Wydrukuj najkrótsze odległości zapisane w dist[] Console.WriteLine('Odległość wierzchołka od źródła');  for (int i = 0; tj< V; ++i)  Console.WriteLine('{0}		{1}', i, dist[i]);  } } public class PriorityQueue{prywatna lista tylko do odczytu_dane;  Porównanie prywatne tylko do odczytu_porównane;  public PriorityQueue(): this(Porównaj.Default) { } public PriorityQueue(IComparerporównaj): this(compare.Compare) { } public PriorityQueue(Comparisonporównanie) { _data = nowa lista();  _porównaj = porównanie;  } public void Kolejka(T pozycja) { _data.Add(item);  var childIndex = _data.Count - 1;  while (childIndex> 0) { var parentIndex = (childIndex - 1) / 2;  if (_compare(_data[childIndex], _data[parentIndex])>= 0) przerwa;  T tmp = _data[indekspodrzędny];  _data[childIndex] = _data[parentIndex];  _data[indeks_nadrzędny] = tmp;  Indeks Dziecka = Indeks Rodzica;  } } public T Dequeue() { // zakłada, że ​​pq nie jest puste; do wywołania kodu var lastElement = _data.Count - 1;  var frontItem = _data[0];  _data[0] = _data[ostatniElement];  _data.RemoveAt(lastElement);  --ostatniElement;  varindeks rodzica = 0;  while (true) { var childIndex = parentIndex * 2 + 1;  if (childIndex> lastElement) przerwa; // Koniec drzewa varrightChild = childIndex + 1;  jeśli (prawoDziecko<= lastElement  && _compare(_data[rightChild],  _data[childIndex])  < 0)  childIndex = rightChild;  if (_compare(_data[parentIndex],  _data[childIndex])  <= 0)  break; // Correct position  T tmp = _data[parentIndex];  _data[parentIndex] = _data[childIndex];  _data[childIndex] = tmp;  parentIndex = childIndex;  }  return frontItem;  }  public T Peek()  {  T frontItem = _data[0];  return frontItem;  }  public int Count  {  get { return _data.Count; }  } } class Program {  // Driver program to test methods of graph class  static void Main(string[] args)  {  // create the graph given in above figure  int V = 7;  Graph g = new Graph(V);  // making above shown graph  g.addEdge(0, 1, 2);  g.addEdge(0, 2, 6);  g.addEdge(1, 3, 5);  g.addEdge(2, 3, 8);  g.addEdge(3, 4, 10);  g.addEdge(3, 5, 15);  g.addEdge(4, 6, 2);  g.addEdge(5, 6, 6);  g.shortestPath(0);  } }>
JavaScript
class PriorityQueue {  constructor() {  this.queue = [];  }  enqueue(element, priority) {  this.queue.push({ element, priority });  this.queue.sort((a, b) =>a.priorytet - b.priorytet);  } dequeue() { if (this.isEmpty()) { return null;  } zwróć this.queue.shift().element;  } isEmpty() { zwróć tę.długość.kolejki === 0;  } } klasa Wykres { konstruktor(V) { this.V = V;  this.adj = nowa tablica(V);  dla (niech i = 0; tj< V; i++) {  this.adj[i] = [];  }  }  addEdge(u, v, w) {  this.adj[u].push({ v, w });  this.adj[v].push({ v: u, w });  }  shortestPath(src) {  const pq = new PriorityQueue();  const dist = new Array(this.V).fill(Infinity);  const visited = new Array(this.V).fill(false);  pq.enqueue(src, 0);  dist[src] = 0;  while (!pq.isEmpty()) {  const u = pq.dequeue();  if (visited[u]) continue;  visited[u] = true;  for (const { v, w } of this.adj[u]) {  if (!visited[v] && dist[u] + w < dist[v]) {  dist[v] = dist[u] + w;  pq.enqueue(v, dist[v]);  }  }  }  console.log('Vertex Distance from Source');  for (let i = 0; i < this.V; i++) {  console.log(`${i}		${dist[i] === Infinity ? 'Infinity' : dist[i]}`);  }  } } function main() {  const V = 7;  const g = new Graph(V);  g.addEdge(0, 1, 2);  g.addEdge(0, 2, 6);  g.addEdge(1, 3, 5);  g.addEdge(2, 3, 8);  g.addEdge(3, 4, 10);  g.addEdge(3, 5, 15);  g.addEdge(4, 6, 2);  g.addEdge(5, 6, 6);  g.shortestPath(0); } main();>

Ostatnia odpowiedź:

Wyjście

Analiza złożoności algorytmu Dijkstry :

  • Złożoność czasowa: O((V + E) log V) , gdzie V to liczba wierzchołków, a E to liczba krawędzi.
  • Przestrzeń pomocnicza: O(V), gdzie V to liczba wierzchołków, a E to liczba krawędzi grafu.

2.Implementacja algorytmu Dijkstry w oparciu o tablice (podejście naiwne):

Algorytm Dijkstry można również zaimplementować przy użyciu tablic bez użycia kolejki priorytetowej. Ta implementacja jest prosta, ale może być mniej wydajna, szczególnie w przypadku dużych wykresów.

Algorytm przebiega w następujący sposób:

  • Zainicjuj tablicę do przechowywania odległości od źródła do każdego węzła.
  • Oznacz wszystkie węzły jako nieodwiedzone.
  • Ustaw odległość do węzła źródłowego na 0 i nieskończoność dla wszystkich pozostałych węzłów.
  • Powtarzaj, aż wszystkie węzły zostaną odwiedzone:
    • Znajdź nieodwiedzony węzeł z najmniejszą znaną odległością.
    • Dla bieżącego węzła zaktualizuj odległości do jego nieodwiedzonych sąsiadów.
    • Oznacz bieżący węzeł jako odwiedzony.

Analiza złożoności:

  • Złożoność czasowa: W najgorszym przypadku O(V^2), gdzie V jest liczbą wierzchołków. Można to poprawić do O(V^2) za pomocą pewnych optymalizacji.
  • Przestrzeń pomocnicza: O(V), gdzie V to liczba wierzchołków, a E to liczba krawędzi grafu.

Algorytmy Dijkstry a algorytm Bellmana-Forda

Algorytm Dijkstry i Algorytm Bellmana-Forda oba służą do znajdowania najkrótszej ścieżki na wykresie ważonym, ale mają pewne kluczowe różnice. Oto główne różnice między algorytmem Dijkstry a algorytmem Bellmana-Forda:

Funkcja:DijkstryBellmana Forda
Optymalizacjazoptymalizowany pod kątem znajdowania najkrótszej ścieżki między pojedynczym węzłem źródłowym a wszystkimi innymi węzłami na wykresie z nieujemnymi wagami krawędziAlgorytm Bellmana-Forda jest zoptymalizowany pod kątem znajdowania najkrótszej ścieżki pomiędzy pojedynczym węzłem źródłowym a wszystkimi pozostałymi węzłami na wykresie z ujemnymi wagami krawędzi.
RelaksAlgorytm Dijkstry wykorzystuje podejście zachłanne, w którym wybiera węzeł o najmniejszej odległości i aktualizuje swoich sąsiadówalgorytm Bellmana-Forda rozluźnia wszystkie krawędzie w każdej iteracji, aktualizując odległość każdego węzła, biorąc pod uwagę wszystkie możliwe ścieżki do tego węzła
Złożoność czasuAlgorytm Dijkstry ma złożoność czasową O(V^2) dla grafu gęstego i O(E log V) dla grafu rzadkiego, gdzie V to liczba wierzchołków, a E to liczba krawędzi w grafie.Algorytm Bellmana-Forda ma złożoność czasową O(VE), gdzie V jest liczbą wierzchołków, a E jest liczbą krawędzi grafu.
Wagi ujemneAlgorytm Dijkstry nie działa z grafami, które mają ujemne wagi krawędzi, ponieważ zakłada, że ​​wszystkie wagi krawędzi są nieujemne.Algorytm Bellmana-Forda radzi sobie z ujemnymi wagami krawędzi i może wykrywać cykle z ujemną wagą na grafie.

Algorytm Dijkstry kontra algorytm Floyda-Warshalla

Algorytm Dijkstry i Algorytm Floyda-Warshalla oba służą do znajdowania najkrótszej ścieżki na wykresie ważonym, ale mają pewne kluczowe różnice. Oto główne różnice między algorytmem Dijkstry a algorytmem Floyda-Warshalla:

Funkcja:DijkstryAlgorytm Floyda-Warshalla
OptymalizacjaZoptymalizowany pod kątem znajdowania najkrótszej ścieżki między pojedynczym węzłem źródłowym a wszystkimi innymi węzłami na wykresie z nieujemnymi wagami krawędziAlgorytm Floyda-Warshalla jest zoptymalizowany pod kątem znajdowania najkrótszej ścieżki pomiędzy wszystkimi parami węzłów na grafie.
TechnikaAlgorytm Dijkstry to algorytm najkrótszej ścieżki z jednego źródła, który wykorzystuje podejście zachłanne i oblicza najkrótszą ścieżkę od węzła źródłowego do wszystkich pozostałych węzłów na wykresie.Z drugiej strony algorytm Floyda-Warshalla jest algorytmem najkrótszej ścieżki dla wszystkich par, który wykorzystuje programowanie dynamiczne do obliczenia najkrótszej ścieżki między wszystkimi parami węzłów na wykresie.
Złożoność czasuAlgorytm Dijkstry ma złożoność czasową O(V^2) dla grafu gęstego i O(E log V) dla grafu rzadkiego, gdzie V to liczba wierzchołków, a E to liczba krawędzi w grafie.Z drugiej strony algorytm Floyda-Warshalla jest algorytmem najkrótszej ścieżki dla wszystkich par, który wykorzystuje programowanie dynamiczne do obliczenia najkrótszej ścieżki między wszystkimi parami węzłów na wykresie.
Wagi ujemneAlgorytm Dijkstry nie działa z grafami, które mają ujemne wagi krawędzi, ponieważ zakłada, że ​​wszystkie wagi krawędzi są nieujemne.Z drugiej strony algorytm Floyda-Warshalla jest algorytmem najkrótszej ścieżki dla wszystkich par, który wykorzystuje programowanie dynamiczne do obliczenia najkrótszej ścieżki między wszystkimi parami węzłów na wykresie.

Algorytm Dijkstry a algorytm A*

Algorytm Dijkstry i Algorytm A* oba służą do znajdowania najkrótszej ścieżki na wykresie ważonym, ale mają pewne kluczowe różnice. Oto główne różnice między algorytmem Dijkstry a algorytmem A*:

Funkcja: Algorytm A*
Technika wyszukiwaniaZoptymalizowany pod kątem znajdowania najkrótszej ścieżki między pojedynczym węzłem źródłowym a wszystkimi innymi węzłami na wykresie z nieujemnymi wagami krawędziAlgorytm A* to świadomy algorytm wyszukiwania, który wykorzystuje funkcję heurystyczną do kierowania wyszukiwaniem w kierunku węzła docelowego.
Funkcja heurystycznaAlgorytm Dijkstry nie wykorzystuje żadnej funkcji heurystycznej i uwzględnia wszystkie węzły grafu.Algorytm A* wykorzystuje funkcję heurystyczną, która szacuje odległość od bieżącego węzła do węzła docelowego. Ta funkcja heurystyczna jest dopuszczalna, co oznacza, że ​​nigdy nie zawyża rzeczywistej odległości do węzła docelowego
Złożoność czasuAlgorytm Dijkstry ma złożoność czasową O(V^2) dla grafu gęstego i O(E log V) dla grafu rzadkiego, gdzie V to liczba wierzchołków, a E to liczba krawędzi w grafie.Złożoność czasowa algorytmu A* zależy od jakości funkcji heurystycznej.
AplikacjaAlgorytm Dijkstry jest używany w wielu zastosowaniach, takich jak algorytmy wyznaczania tras, systemy nawigacji GPS i analiza sieci. Algorytm A* jest powszechnie stosowany w problemach związanych ze znajdowaniem ścieżki i przechodzeniem po grafach, takich jak gry wideo, robotyka i algorytmy planowania.

Zadania praktyczne dotyczące algorytmu Dijkstry:

  1. Algorytm najkrótszej ścieżki Dijkstry | Chciwy Algo-7
  2. Algorytm Dijkstry do reprezentacji listy sąsiedztwa | Chciwy Algo-8
  3. Algorytm Dijkstry – implementacja kolejek priorytetowych i tablic
  4. Algorytm najkrótszej ścieżki Dijkstry wykorzystujący zestaw w STL
  5. Algorytm najkrótszej ścieżki Dijkstry wykorzystujący STL w C++
  6. Algorytm najkrótszej ścieżki Dijkstry wykorzystujący kolejkę priorytetów STL
  7. Algorytm najkrótszej ścieżki Dijkstry wykorzystujący macierz w C++
  8. Algorytm Dijkstry dla najkrótszej ścieżki z jednego źródła w DAG
  9. Algorytm Dijkstry wykorzystujący stertę Fibonacciego
  10. Algorytm najkrótszej ścieżki Dijkstry dla grafów skierowanych z ujemnymi wagami
  11. Drukowanie ścieżek w algorytmie najkrótszej ścieżki Dijkstry
  12. Algorytm najkrótszej ścieżki Dijkstry z kolejką priorytetową w Javie