web-dev-qa-db-fra.com

Dijkstra vs. Floyd-Warshall: Trouver la route optimale sur toutes les paires de nœuds

Je lis sur l'algorithme de Dijkstra et l'algorithme Floyd-Warshall. Je comprends que Dijkstra trouve la route optimale d'un nœud à tous les autres nœuds et Floyd-Warshall trouve la route optimale pour tous les couples de nœuds.

Ma question est si l'algorithme de Dijkstra serait plus efficace que celui de Floyd si je l'exécutais sur chaque nœud afin de trouver la route optimale entre tous les appariements.

Le runtime de Dijkstra est O (E + VlogV) où Floyd est O (V3). Si Dijkstra échoue, quel serait son temps d'exécution dans ce cas? Merci!

27
pyt

Comme d'autres l'ont souligné, Floyd-Warshall s'exécute dans le temps O (n3) et l'exécution d'une recherche Dijkstra de chaque nœud à chaque autre nœud, en supposant que vous utilisez un tas Fibonacci pour sauvegarder l'implémentation de votre Dijkstra, prend O (mn + n2 log n). Cependant, vous ne pouvez pas toujours exécuter Dijkstra en toute sécurité sur un graphe arbitraire car l'algorithme de Dijkstra ne fonctionne pas avec des poids de bord négatifs.

Il existe un algorithme vraiment remarquable appelé algorithme de Johnson qui est une légère modification de l'exécution de l'algorithme de Dijkstra à partir de chaque nœud qui permet cette approche pour fonctionner même si le graphique contient des bords négatifs (tant qu'il n'y a pas de cycles négatifs). L'algorithme fonctionne en exécutant d'abord Bellman-Ford sur le graphique pour le transformer en un graphique sans bords négatifs, puis en utilisant l'algorithme de Dijkstra en commençant à chaque sommet. Étant donné que Bellman-Ford fonctionne dans le temps O (mn), le temps d'exécution asymptotique global est toujours O (mn + n2 log n), donc si m = o (n2) (notez que c'est little-o sur n), cette approche est asymptotiquement plus rapide que d'utiliser Floyd-Warshall.

Le seul problème ici est que cela suppose que vous avez l'algorithme de Dijkstra soutenu par un tas de Fibonacci. Si vous n'avez pas de tas Fibonacci disponible et que vous n'êtes pas prêt à consacrer les 72 heures nécessaires pour en créer, déboguer et tester un, alors vous pouvez toujours utiliser un tas binaire pour l'algorithme de Dijkstra; il augmente simplement le temps d'exécution à O (m log n), donc cette version de l'algorithme de Johnson s'exécute en O (mn log n). Ce n'est plus toujours asymptotiquement plus rapide que Floyd-Warshall, car si m = Ω (n2) puis Floyd-Warshall s'exécute en O (n3) tandis que l'algorithme de Johnson s'exécute en O (n3 log n). Cependant, pour les graphiques clairsemés, où m = o (n2/log n), cette implémentation de l'algorithme de Johnson est encore mieux asymptotiquement que Floyd-Warshall

En bref:

  • Avec un tas de Fibonacci, l'algorithme de Johnson est toujours asymptotiquement au moins aussi bon que Floyd-Warshall, bien qu'il soit plus difficile à coder.
  • Avec un tas binaire, l'algorithme de Johnson est généralement asymptotiquement au moins aussi bon que Floyd-Warshall, mais n'est pas une bonne option lorsqu'il s'agit de graphiques volumineux et denses.

J'espère que cela t'aides!

33
templatetypedef

La complexité de l'exécution de Dijkstra sur tous les nœuds sera O (EV + V2logV). Cette complexité est inférieure à O (V3) si E <V2.

10
Andreas Brinck

Ça dépend. L'exécution de Dijkstra pour tous les nœuds vous donne O(VE + V^2log V), tandis que celle de Floyd est O(V^3). Si E = O(V^2), alors les deux sont théoriquement identiques, Floyd étant plus rapide en pratique. Si vous E = O(V), alors exécuter Dijkstra pour tous les nœuds si c'est mieux en théorie et en pratique.

Fondamentalement, exécutez Dijkstra à partir de tous les nœuds si vous prévoyez d'avoir autant d'arêtes que de nœuds et exécutez Floyd si vous prévoyez d'avoir des graphiques presque complets.

3
IVlad