L'algorithme de Dijsktra : C++, Python Exemple de code
Quel est le chemin le plus court ou la distance la plus courte ?
Un chemin allant du sommet source au sommet de destination qui coรปte un minimum est le chemin le plus court ou la distance la plus courte. En thรฉorie des graphes, il est possible dโavoir plusieurs itinรฉraires depuis une source vers une destination. Entre ces itinรฉraires, sโil existe un itinรฉraire qui coรปte un montant minimum, nous pouvons lโappeler lโalgorithme du chemin le plus court.
Ici, ยซ Coรปt ยป dรฉsigne le nombre de nลuds dans l'itinรฉraire ou la somme des coรปts sur chaque chemin. Un chemin peut avoir un ou plusieurs bords. La connexion entre deux sommets est appelรฉe ยซ arรชte ยป. Il existe diffรฉrents types d'algorithmes de chemin le plus court, comme l'algorithme de Dijkstra, l'algorithme de Bellman-Ford, etc.
Ici, nous discutons de l'algorithme de Dijkstra
Regardons le graphique pondรฉrรฉ suivant :

- Le terme ยซ pondรฉrรฉ ยป signifie dรฉplacer les coรปts dโun nลud ร un autre. Par exemple, en passant du nลud 1 au nลud 2, le coรปt ou le poids est de 1.
- Le chemin entre le nลud 1 et le nลud 2 est appelรฉ le bord.
- ยซ Non dirigรฉ ยป signifie que vous pouvez dรฉplacer un nลud vers un autre et revenir au nลud prรฉcรฉdent. Donc, si nous essayons de trouver toutes les routes du nลud 1 au nลud 7, alors ce sera :
| Itinรฉraire ou chemin | Prix |
|---|---|
| 1 2 6-7 | (1+3+3) = 7 |
| 1 2 3-7 | (1+9+1) = 11 |
| 1-3-7 | (7+1) = 8 |
| 1 4 5-7 | (6+2+5) = 13 |
Parmi ces quatre itinรฉraires, nous pouvons voir que le premier itinรฉraire nous coรปtera 7. C'est donc le chemin le plus court en termes de coรปt.
Comment fonctionne l'algorithme de Dijkstra
L'algorithme de Dijkstra peut trouver la distance la plus courte dans les graphiques pondรฉrรฉs orientรฉs et non orientรฉs. Cet algorithme est gourmand car il choisit toujours le nลud le plus court ou le plus proche de l'origine. Le terme ยซ gourmand ยป signifie que parmi un ensemble dโissues ou de rรฉsultats, lโalgorithme choisira le meilleur dโentre eux.
Ici, nous essayons de trouver les chemins les plus courts parmi tous les autres itinรฉraires. Ainsi, l'algorithme de Dijkstra trouve tous les chemins les plus courts ร partir d'un seul nลud de destination. De ce fait, il se comporte comme un algorithme gourmand.
Dans la section ยซ exemple ยป ci-dessous, vous verrez l'approche รฉtape par รฉtape. Cela fonctionne comme suit :
รtape 1) Initialisez le nลud de dรฉpart avec 0 coรปt et le reste du nลud avec Infinity Cost.
รtape 2) Maintenir un tableau ou une liste pour garder une trace des nลuds visitรฉs
รtape 3) Mettez ร jour le coรปt du nลud avec le coรปt minimum. Cela peut รชtre fait en comparant le coรปt actuel avec le coรปt du chemin. (La dรฉmonstration est prรฉsentรฉe dans la section exemple)
รtape 4) Continuez l'รฉtape 3 jusqu'ร ce que tous les nลuds soient visitรฉs.
Aprรจs avoir complรฉtรฉ toutes ces รฉtapes, nous trouverons le chemin qui coรปte le moins cher de la source ร la destination.
Diffรฉrence entre Dijkstra et BFS, DFS
La principale diffรฉrence entre Dijkstra et BFS-DFS est que Dijkstra est l'algorithme de recherche de chemin le plus court et que BFS, DFS est l'algorithme de recherche de chemin. Dans les cas gรฉnรฉraux, BFS et DFS ne prennent pas en compte le coรปt lors de la recherche du chemin. Ces algorithmes ne peuvent donc pas garantir le chemin le plus court.
Dรฉmonstration de grille 2D du fonctionnement de BFS
Cette dรฉmonstration indique que BFS trouve uniquement le chemin. Toutefois, il ne se soucie pas du poids du chemin. BFS (Recherche en largeur d'abord) suppose que voyager dโun nลud ร un autre ne coรปtera que 1.
Mais voyons un exemple de graphique :
Ici, il trouve un chemin au niveau 2. BFS parcourt le graphique dans l'ordre des niveaux. Donc รงa voyage comme :
รtape 1) Commencez par le nลud ยซ 1 ยป et visitez tous les nลuds adjacents 2,3,4
รtape 2) Marquez les nลuds 2,3,4 comme niveau 1 et visitez leurs nลuds adjacents. Il continuera ร explorer tous les nลuds adjacents jusqu'ร ce qu'il atteigne le nลud de destination.
En termes de DFS, il parcourra le chemin de 1 ร 7 comme suit :
- 1 โ 2 โ 3 โ 7 (coรปt initial 10, coรปt DFS 3)
- 1 โ 2 โ 6 โ 7 (coรปt initial 7, coรปt DFS 3)
- 1 โ 3 โ 7 (coรปt initial 8, coรปt DFS 2)
- 1 โ 4 โ 5 โ 7 (coรปt initial 13, coรปt DFS 3)
Comme nous le voyons, DFS calcule son coรปt de chemin avec le nombre de profondeur ou le nombre d'arรชtes.
DFS effectue les opรฉrations suivantes :
- DFS peut trouver un chemin depuis la source (sommet de dรฉpart) jusqu'ร la destination.
- Il ne peut pas garantir si le chemin dรฉcouvert du nลud source ร la destination est le chemin le plus court ou non.
Cependant, en termes dโalgorithme de Dijkstra, il choisira les arรชtes en fonction de leur coรปt. En tant qu'algorithme glouton, il sรฉlectionnera les chemins les meilleurs ou les moins coรปteux.
Exemple de l'algorithme de Dijkstra
L'algorithme de Dijkstra utilise le coรปt ou le poids pour calculer le coรปt total du chemin.
L'objectif de l'algorithme de Dijkstra est de minimiser ce coรปt ou ce poids total. Dans l'exemple ci-dessus, nous trouvons les meilleurs chemins du nลud 1 au nลud 7, puis calculons tous les coรปts.
Dans l'algorithme de Dijkstra, il trouvera les chemins les plus courts en calculant des poids. Il ne cherchera pas tous les chemins possibles. Dรฉmontrons l'algorithme de Dijkstra avec un exemple. Par exemple, il vous a รฉtรฉ demandรฉ de trouver le chemin le plus court entre le nลud 1 et le nลud 7.
Pour ce processus, les รฉtapes sont indiquรฉes ci-dessous :
รtape 1) Initialisez le coรปt du nลud de dรฉpart ร 0.
Reste du nลud, attribuer ยซ Inf ยป. Cela signifie qu'aucun chemin n'existe entre le sommet de dรฉpart (la source) et le nลud, ou que le chemin n'est pas encore visitรฉ.
รtape 2) Lorsque vous sรฉlectionnez le nลud 1, il sera marquรฉ comme visitรฉ. Mettez ensuite ร jour tous les voisins adjacents du nลud 1. 2,3,4 sont les nลuds voisins du nลud 1.
Lors de la mise ร jour d'un coรปt, nous devons suivre la procรฉdure ci-dessous :
Nous pouvons mettre ร jour le coรปt de chaque nลud en utilisant la formule ci-dessus. Par exemple, nous รฉtions au nลud 1 et nous devions mettre ร jour le coรปt de son nลud adjacent 2,3,4.
Aprรจs la mise ร jour, le coรปt ou le poids ressemblera ร ceci :
รtape 3) Pour le nลud ยซ 2 ยป, les voisins sont 6 et 3. Nous mettons ร jour le coรปt ร ยซ 6 ยป en comparant l'infini (valeur actuelle). Le coรปt du nลud 2 + le coรปt du chemin de 2 ร 6. En termes simples, le nลud ยซ 6 ยป aura le coรปt de 1+3 ou 4.
Le nลud 3 est voisin du nลud 2. Cependant, nous avons calculรฉ son coรปt ร l'รฉtape prรฉcรฉdente, qui รฉtait de 7. Maintenant, si notre chemin est 1-2-3, le nลud 3 aura un coรปt de 10. Chemin 1-2- 3 coรปtera 10, tandis que 1 ร 3 coรปtera 7.
รtape 4) Pour le nลud 3, le nลud voisin est 7. Ainsi, en comparant la valeur actuelle du nลud 7 avec le coรปt du chemin (7+1) ou 8, nous mettrons ร jour le coรปt du nลud 7. Soit 8.
Nous trouvons donc un chemin du nลud 1 au nลud 7, et il vaut 1 โ 3 โ 7. Le coรปt est de 8.
รtape 5) Pour le nลud 4, nous mettrons ร jour son coรปt de nลud adjacent en consรฉquence. Ainsi, le nลud ยซ 5 ยป aura un coรปt mis ร jour de 8. Aprรจs l'รฉtape 4,5, il ressemblera ร ceci :
Dรฉsormais, le chemin 1-3-7 coรปte 8 (auparavant). Le nลud ยซ 7 ยป n'a pas รฉtรฉ marquรฉ comme visitรฉ car nous pouvons atteindre le nลud ยซ 7 ยป ร partir du nลud ยซ 6 ยป. Le chemin ยซ 1-2-6 ยป avait un coรปt de 4. Le chemin 1-2-6-7 aura donc un coรปt de 7.
Comme 7 < 8, c'est pourquoi le chemin le plus court du sommet source ยซ 1 ยป au sommet de destination ยซ 7 ยป sera 1-2-6-7, et le coรปt est 7. Auparavant, c'รฉtait 1-3-7, et le coรปt avait 8 ans.
Ainsi, le graphique final ressemblera ร ceci :
Le bord marquรฉ d'une ligne noire est notre chemin le plus court de 1 ร 7, et il nous en coรปtera 7.
Algorithme du pseudo-code Dijkstra
Voici le pseudo-code de l'algorithme de Dijkstra
Dijkstra(G, S):
for each vertex V in G
distance[V] & lt; - Infinity
previous[V] & lt; - NULL
if V does not equal S, then,
(priority queue) Q.push(V)
distance[S] = 0
While Q is not empty
U & lt; - Extract the MIN from Q
For each unvisited adjacent V of U
TotalDistance & lt; - distance[U] + edge_cost(U, V)
if TotalDistance is less than distance[V], then
distance[V] & lt; - TotalDistance
previous[V] & lt; - u
return distance, previous
C++ implรฉmentation de l'algorithme de Dijkstra
Pour implรฉmenter l'algorithme de Dijkstra en utilisant C++, voici le code :
#include <bits/stdc++.h>
using namespace std;
#define size 7
int minimumDistance(int distance[], bool visited[]) {
int min = INT_MAX;
int min_index = INT_MAX;
for (int i = 0; i < size; i++) {
if (!visited[i] & amp; & distance[i] <= min) {
min = distance[i];
min_index = i;
}
}
return min_index;
}
void printParentPath(int parent[], int i) {
if (parent[i] == -1) {
return;
}
printParentPath(parent, parent[i]);
cout << i + 1 << " ";
}
void dijkstra(int graph[size][size], int source) {
int distance[size];
bool visited[size];
int parent[size];
for (int i = 0; i < size; i++) {
parent[0] = -1;
distance[i] = INT_MAX;
visited[i] = false;
}
distance[source] = 0;
for (int i = 0; i < size - 1; i++) {
int U = minimumDistance(distance, visited);
visited[U] = true;
for (int j = 0; j < size; j++) {
int curr_distance = distance[U] + graph[U][j];
if (!visited[j] & amp; & graph[U][j] & amp; &
curr_distance < distance[j]) {
parent[j] = U;
distance[j] = curr_distance;
}
}
}
cout << "Vertex\t\tDistance\tPath" << endl;
for (int i = 1; i < size; i++) {
cout << source + 1 << "->" << i + 1 << "\t\t" << distance[i] << "\t\t"
<< source + 1 << " ";
printParentPath(parent, i);
cout << endl;
}
}
int main() {
int graph[size][size] = {{0, 1, 7, 6, 0, 0, 0}, {1, 0, 9, 0, 0, 3, 0},
{7, 9, 0, 0, 0, 0, 1}, {6, 0, 0, 0, 2, 0, 0},
{0, 0, 0, 2, 0, 0, 0}, {0, 3, 0, 0, 0, 0, 3},
{0, 0, 0, 0, 5, 3, 0}};
dijkstra(graph, 0);
}
Sortie :
Vertex Distance Path 1->2 1 1 2 1->3 7 1 3 1->4 6 1 4 1->5 8 1 4 5 1->6 4 1 2 6 1->7 7 1 2 6 7
Python implรฉmentation de l'algorithme de Dijkstra
Pour implรฉmenter l'algorithme de Dijkstra en utilisant python, voici le code :
num_of_vertex = 7
def minimumDistance(distance, visited):
_min = 1e11
min_index = 1e11
for i in range(num_of_vertex):
if not visited[i] and distance[i] & lt; = _min:
_min = distance[i]
min_index = i
return min_index
def printParentNode(parent, i):
if parent[i] == -1:
return
printParentNode(parent, parent[i])
print("{} ".format(i + 1), end = "")
def dijkstra(graph, src):
distance = list()
visited = list()
parent = list()
for i in range(num_of_vertex):
parent.append(-1)
distance.append(1e11)
visited.append(False)
distance[src] = 0
for i in range(num_of_vertex - 1):
U = minimumDistance(distance, visited)
visited[U] = True
for j in range(num_of_vertex):
curr_distance = distance[U] + graph[U][j]
if not visited[j] and graph[U][j] and curr_distance & lt;
distance[j]: parent[j] = U
distance[j] = curr_distance
print("Vertex\t\tDistance\tPath")
for i in range(num_of_vertex):
print("{}->{}\t\t{}\t\t{}
".format(src + 1, i + 1, distance[i], src + 1), end = "")
printParentNode(parent, i)
print("")
graph = [
[0, 1, 7, 6, 0, 0, 0],
[1, 0, 9, 0, 0, 3, 0],
[7, 9, 0, 0, 0, 0, 1],
[6, 0, 0, 0, 2, 0, 0],
[0, 0, 0, 2, 0, 0, 0],
[0, 3, 0, 0, 0, 0, 3],
[0, 0, 0, 0, 5, 3, 0]
]
dijkstra(graph, 0)
Sortie :
Vertex Distance Path 1->1 0 1 1->2 1 1 2 1->3 7 1 3 1->4 6 1 4 1->5 8 1 4 5 1->6 4 1 2 6 1->7 7 1 2 6 7
Nous pouvons voir que l'algorithme calcule la distance la plus courte depuis le nลud source.
Application de l'algorithme de Dijkstra
Le Dijkstra Algo a un large รฉventail dโutilisations. Parmi ceux-ci, il est largement utilisรฉ dans le domaine des rรฉseaux. Voici quelques exemples d'utilisation rรฉelle de l'algorithme de Dijkstra :
Dijkstra sur la carte Google : Fondamentalement, cet algorithme est lโรฉpine dorsale de la recherche des chemins les plus courts. Comme nous pouvons le voir dans la sortie de lโextrait de code ci-dessus.
Google n'utilise pas le simple algorithme de Dijkstra. Au lieu de cela, il utilise une version modifiรฉe. Lorsque vous sรฉlectionnez une destination, plusieurs chemins sont affichรฉs sur Google Map. Parmi ces chemins, certains chemins sont triรฉs pour l'utilisateur. Ces chemins sรฉlectionnรฉs sont basรฉs sur le ยซ temps ยป. Ainsi, le ยซ temps ยป est un coรปt supplรฉmentaire pour le chemin le plus court.
Dijkstra dans le routage IP : Routage IP est une terminologie de rรฉseautage. Cela signifie comment votre paquet de donnรฉes est envoyรฉ au rรฉcepteur via diffรฉrents chemins. Ces chemins sont constituรฉs de routeurs, de serveurs, etc. Dans le routage IP, il existe diffรฉrents types de protocoles.
Ces protocoles aident le routeur ร trouver les chemins les plus courts pour envoyer les donnรฉes. L'un des noms de protocole est ยซ OSPF (Open Shortest Path First) ยป. OSPF utilise l'algorithme de Dijkstra. Le routeur gรจre une table de routes. Chaque routeur partage sa table avec les routeurs voisins. Aprรจs avoir reรงu le tableau mis ร jour, ils doivent recalculer tous les chemins. ร ce moment-lร , le routeur utilise lโalgorithme Dijkstra.
Limitation de l'algorithme de Dijkstra
L'algorithme de Dijkstra ne peut pas garantir le chemin le plus court dans le graphe des bords nรฉgatifs. L'algorithme de Dijkstra suit ces mรฉthodologies :
- Un chemin le plus court sera empruntรฉ dโun nลud ร un autre.
- Une fois le chemin le plus court entre deux nลuds sรฉlectionnรฉ, il ne sera plus calculรฉ.
Ici, remarquez deux exemples avec des bords nรฉgatifs.
Dans le graphique de gauche, il y a trois sommets. Dijkstra fonctionnera sur le graphique comme suit :
รtape 1) Le sommet de dรฉpart ยซ 1 ยป sera initialisรฉ ร zรฉro. Les autres nลuds auront l'infini.
รtape 2) Marquez le nลud ยซ 1 ยป comme visitรฉ et incluez-le dans le chemin le plus court.
รtape 3) La distance du nลud source 1 aux nลuds ยซ 2 ยป et ยซ 3 ยป est fixรฉe ร l'infini, car le chemin le plus court reste ร calculer. Ainsi, tout chemin qui coรปtera moins que lโinfini sera ajoutรฉ au chemin le plus court (approche gourmande).
รtape 4) Mise ร jour de la distance du sommet source ou du nลud source ยซ 1 ยป ร ยซ 2 ยป. Le poids actuel sera de 5 (5
รtape 5) Maintenant, si nous vรฉrifions les distances les plus courtes depuis le nลud ยซ 1 ยป, nous constatons que 5 est la distance la plus courte pour le bord 1 -> 2. Ainsi, le nลud ยซ 2 ยป sera marquรฉ comme visitรฉ.
De mรชme, le nลud ยซ 3 ยป sera รฉgalement marquรฉ comme visitรฉ car la distance la plus courte est 3.
Cependant, si nous observons, il existe un chemin 1-3-2 qui ne coรปtera que 2. Mais le Dijkstra montre que du nลud ยซ 1 ยป au nลud ยซ 2 ยป, la distance la plus courte est 5. Ainsi, Dijkstra n'a pas rรฉussi ร calculer la distance la plus courte. distance correctement. La raison pour laquelle cela s'est produit est que Dijkstra est un algorithme gourmand. Ainsi, une fois qu'un nลud est marquรฉ comme visitรฉ, il ne sera pas reconsidรฉrรฉ, mรชme s'il peut y avoir un chemin plus court disponible. Ce problรจme se produit uniquement lorsque les arรชtes ont des coรปts nรฉgatifs ou des arรชtes de poids nรฉgatifs.
Dijkstra ne parvient pas ร calculer le chemin le plus court entre deux nลuds dans ce scรฉnario. En consรฉquence, cet algorithme prรฉsente certains inconvรฉnients. Pour rรฉsoudre ce problรจme de bord nรฉgatif, un autre algorithme appelรฉ ยซ Algorithme Bellman-Ford ยป est utilisรฉ. Cet algorithme peut fonctionner avec des bords nรฉgatifs.
Complexitรฉ de l'algorithme de Dijkstra
L'implรฉmentation ci-dessus utilisait deux boucles ยซ for ยป. Ces boucles s'exรฉcutent pour le nombre de sommets. La complexitรฉ temporelle est donc O(V2). Ici, le terme ยซ 0 ยป dรฉsigne une notation qui donne une hypothรจse pour l'algorithme de Dijkstra.
Nous pouvons stocker le graphique en utilisant la ยซ file dโattente prioritaire ยป. Une file d'attente prioritaire est une structure de donnรฉes de tas binaire. Ce sera plus efficace quโune matrice 2D. Un avantage qui aura un coรปt minimum aura une haute prioritรฉ.
La complexitรฉ temporelle sera alors O (E log (V)). Ici, E est le nombre dโarรชtes et V est le nombre de sommets.
La complexitรฉ de l'espace est O(V2), car nous utilisons une matrice de contiguรฏtรฉ (tableau 2D). La complexitรฉ de l'espace peut รชtre optimisรฉe ร l'aide d'une liste de contiguรฏtรฉ ou d'une structure de donnรฉes de file d'attente.












