Publié en 1959, l'algorithme de Edgser Wybe Dijkstra (1930-2002) est une alternative à Floyd, plus complexe mais plus rapide.
Ici, on se fixe un sommet source, et l'algorithme retourne tous les chemins les plus courts de ce sommet à chacun des autres sommets (légèrement différent du retour de Floyd)
L'algorithme de Dijkstra est un algorithme de type glouton : à chaque nouvelle étape, on traite un nouveau sommet. Reste à définir le choix du sommet à traiter, et le traitement à lui infliger...
Tout au long du calcul, on met à jour deux ensembles :
L'algorithme se termine quand $C$ est vide.
Pour chaque sommet $s$ dans $D$, on conservera :
Ainsi, pour retrouver un chemin le plus court, il suffira de remonter de prédécesseur en prédécesseur jusqu'à la source, ce qui pourra se faire grâce à un unique appel récursif (beaucoup moins coûteux que dans le cas de Floyd).
Au début de l'algorithme, le chemin le plus court connu entre la source et chacun des sommets est le chemin direct, avec une arête de poids infini s'il n'y a pas de liaison entre les deux sommets.
On initialise donc le tableau distances par les poids des arêtes reliant la source à chacun des sommets, et le tableau parcours par source pour tous les sommets.
On suppose avoir déjà traité i sommets, parcours et distances contiennent respectivement les poids et le prédécesseur des plus courts chemins pour chacun des sommets déjà traités.
Soit s le sommet de C réalisant le minimum de distances[s].
distances[s] + F(s,t) < distances[t],
alors on remplace :
Et c'est tout !
Au départ, il y a (n-1) sommets à visiter, mais la dernière étape est inutile (elle n'apporte rien). Dès la (n-2)ème étape, distances et parcours contiennent toute l'information nécessaire pour trouver des plus courts chemins.
Si $n$ est le nombre de sommets du graphe, et $a$ son nombre d'arêtes, alors l'algorithme de Dijkstra renvoie le résultat au bout de $O(a^2 ln n)$ opérations.
Pour un même résultat, Floyd nécessite $O(n^3)$ opérations.
Le protocole open shortest path first, qui permet un routage internet très efficace des informations, utilise Dijkstra.
Le réseau Internet utilise pour le moment un autre type d'algorithme pour déterminer le chemin à suivre pour transmettre des données entre deux serveurs : Routing Information Protocol (RIP). Dijkstra commence cependant à s'implanter, et remplace progressivement ce protocole : il est le plus rapide.
Les sites d'itinéraires routiers l'utilisent de la même manière et permettent de nombreuses adaptations en ajustant le poids des arcs (trajet le plus économique, le plus rapide, etc.)
Numérotons les sommets du graphe $G = (V,E)$ de $1$ à $n$.
Supposons que l'on s'intéresse aux chemins partant du sommet 1.
On construit un vecteur $l = (l(1); l(2); ...; l(n))$ ayant $n$ composantes tel que $l(j)$ soit égal à la longueur du plus court chemin allant de 1 au sommet j.
On initialise ce vecteur à $c_{1,j}$, c'est-à-dire à la première ligne de la matrice des coûts du graphe, définie comme indiqué ci-dessous :
où $\delta (i,j)$ est le poids (la longueur) de l'arc $(i,j)$. Les $c_{i,j}$ doivent être strictement positifs.
On construit un autre vecteur $p$ pour mémoriser le chemin pour aller du sommet 1 au sommet voulu. La valeur $p(i)$ donne le sommet qui précède $i$ dans le chemin.
On considère ensuite deux ensembles de sommets, $S$ initialisé à ${1}$ et $T$ initialisé à ${2, 3, ..., n}$.
À chaque pas de l'algorithme, on ajoute à $S$ un sommet jusqu'à ce que $S = V$ de telle sorte que le vecteur $l$ donne à chaque étape le coût minimal des chemins de 1 aux sommets de $S$.
On suppose ici que le sommet de départ (qui sera la racine de l'arborescence) est le sommet 1. Notons qu'on peut toujours renuméroter les sommets pour que ce soit le cas.
Le chemin minimal de 1 à 4 par exemple est de coût 9. C'est le chemin 1-5-4, car $p(4) = 5$ et $p(5) = 1$.
Montrons comment calculer le plus court chemin d'un graphe pondéré, et sa longueur (son temps), en utilisant la méthode de Dijkstra de networkx :
>>> path.dijkstra_path(G,(0,0),(3,4)) [(0, 0), (1, 0), (1, 1), (1, 2), (1, 3), (2, 3), (2, 4), (3, 4)] >>> path.dijkstra_path_length(G,(0,0),(3,4)) 38
Si la programmation de cet algorithme est un peu plus compliquée, son utilisation est plus simple.