web-dev-qa-db-fra.com

Quelle est la différence entre l'algorithme de Dijkstra et celui de Prim?

Quelqu'un peut-il me dire la différence entre les algorithmes de Dijkstra et de Prim ? Je sais ce que chacun des algorithmes font. Mais ils se ressemblent pour moi. L'algorithme de Dijkstra stocke une somme des coûts minimum alors que celui de Prim stocke au plus un coût minimal Edge. N'est-ce pas la même chose? 

25
Pradit

L'algorithme de Dijsktra détermine la distance minimale du noeud i à tous les noeuds (vous spécifiez i). Donc, en retour, vous obtenez l'arbre de distance minimale du nœud i.

L'algorithme Prims vous permet d'obtenir l'arbre d'arbre minimal pour un graphe donné . Un arbre qui connecte tous les nœuds alors que la somme de tous les coûts est le minimum possible.

Donc, avec Dijkstra vous pouvez passer du nœud sélectionné à un autre avec un coût minimal , vous ne l'obtenez pas avec Prim's

43
fersarr

La seule différence que je vois est que l'algorithme de Prim stocke un coût minimal Edge, tandis que celui de Dijkstra stocke le coût total d'un sommet source au sommet actuel.

Dijkstra vous donne un moyen de passer du noeud source au noeud de destination de sorte que le coût soit minimal. Cependant, l'algorithme de Prim vous donne un arbre de recouvrement minimal tel que tous les nœuds soient connectés et que le coût total soit minimum.

En mots simples:

Donc, si vous voulez déployer un train pour relier plusieurs villes, vous utiliserez l’algo de Prim. Mais si vous voulez aller d'une ville à l'autre pour gagner le plus de temps possible, vous utiliserez l'algo de Dijkstra.

26
Kevindra

Les deux peuvent être implémentés en utilisant exactement le même algorithme générique, comme suit:

Inputs:
  G: Graph
  s: Starting vertex (any for Prim, source for Dijkstra)
  f: a function that takes vertices u and v, returns a number

Generic(G, s, f)
    Q = Enqueue all V with key = infinity, parent = null
    s.key = 0
    While Q is not empty
        u = dequeue Q
        For each v in adj(u)
            if v is in Q and v.key > f(u,v)
                v.key = f(u,v)
                v.parent = u

Pour Prim, passez f = w(u, v) et pour Dijkstra Pass f = u.key + w(u, v).

Une autre chose intéressante est que ci-dessus, Generic peut également implémenter BFS (Breadth First Search), bien que ce soit excessif, car une file d'attente prioritaire coûteuse n'est pas vraiment nécessaire. Pour activer l’algorithme générique au-dessus de BFS, transmettez f = u.key + 1, ce qui revient au même que l’application de toutes les pondérations à 1 (c’est-à-dire que BFS donne le nombre minimum d’arêtes devant être parcourues du point A à B).

Intuition

Voici un bon moyen de réfléchir à l'algorithme générique ci-dessus: Nous commençons par deux compartiments A et B. Initialement, placez tous vos sommets dans B afin que le compartiment A soit vide. Ensuite, nous déplaçons un sommet de B vers A. Maintenant, regardons toutes les arêtes des sommets de A traversant les sommets de B. Nous avons choisi l’arête en utilisant certains critères de ces arêtes croisées et nous déplaçons le sommet correspondant de B à A. Répétez ce processus jusqu'à ce que B soit vide.

Une façon brutale de mettre en œuvre cette idée serait de maintenir une file d'attente prioritaire des arêtes pour les sommets de A qui passent à B. Bien entendu, cela serait gênant si le graphe n'était pas rare. La question serait donc de savoir si nous pouvons conserver la file d'attente prioritaire des sommets. En fait, nous pouvons finalement décider quel sommet choisir parmi B.

Contexte historique

Il est intéressant de noter que la version générique de la technique sous-jacente aux deux algorithmes est conceptuellement aussi ancienne que 1930, même en l'absence d'ordinateurs électroniques.

L'histoire commence avec Otakar Borůvka, qui avait besoin d'un algorithme pour un ami de la famille qui tentait de comprendre comment relier les villes de la Moravie (qui fait maintenant partie de la République tchèque) avec des lignes électriques à un coût minimal. Il a publié son algorithme en 1926 dans une revue liée aux mathématiques, car l’informatique n’existait pas à l’époque. Cela a attiré l'attention de Vojtěch Jarník qui a pensé à une amélioration de l'algorithme de Borůvka et l'a publié en 1930. Il a en fait découvert le même algorithme que nous connaissons maintenant sous le nom d'algorithme de Prim qui l'a redécouvert en 1957. 

Indépendant de tout cela, Dijkstra doit écrire en 1956 un programme démontrant les capacités d’un nouvel ordinateur développé par son institut. Il a pensé que ce serait bien d’avoir un ordinateur pour relier deux villes des Pays-Bas. Il a conçu l'algorithme en 20 minutes. Il créa un graphique de 64 villes avec quelques simplifications (car son ordinateur était de 6 bits) et écrivit du code pour cet ordinateur de 1956. Cependant, il n'a pas publié son algorithme car, à la base, il n'existait pas de revues d'informatique et il pensait que ce n'était peut-être pas très important. L'année suivante, il découvrit le problème de la connexion des terminaux de nouveaux ordinateurs de manière à minimiser la longueur des fils. Il réfléchit à ce problème et redécouvrit l'algorithme de Jarník/Prim, qui utilise à nouveau la même technique que l'algorithme de chemin le plus court qu'il avait découvert l'année précédente. Il a mentionné que ses deux algorithmes ont été conçus sans stylo ni papier. En 1959, il publia les deux algorithmes dans un paper qui ne faisait que 2 pages et demie.

18
Shital Shah

L'algorithme de Dijkstra est un problème de chemin le plus court source unique entre les noeuds i et j, mais l'algorithme de Prim est un problème d'envergure minimale. Ces algorithmes utilisent un concept de programmation nommé 'algorithme glouton'

Si vous vérifiez ces notions, veuillez visiter 

  1. Note de cours sur l'algorithme Greedy: http://jeffe.cs.illinois.edu/teaching/algorithms/notes/07-greedy.pdf
  2. Arbre de recouvrement minimum: http://jeffe.cs.illinois.edu/teaching/algorithms/notes/20-mst.pdf
  3. Le chemin le plus court source unique: http://jeffe.cs.illinois.edu/teaching/algorithms/notes/21-sssp.pdf
2
user1732445

La même question me dérangeait ces derniers temps, et je pense que je pourrais partager ma compréhension ...

Je pense que la différence essentielle entre ces deux algorithmes (Dijkstra et Prim) trouve son origine dans le problème qu’ils sont censés résoudre, à savoir le chemin le plus court entre deux nœuds et l’espacement minimal (Spanning Tree, MST). Le formel consiste à trouver le chemin le plus court entre, par exemple, noeud s et t, et il est rationnel de visiter chaque bord du graphique au plus une fois. Cependant, il ne faut pas que _ nous rende visite à tous les nœuds. Ce dernier (MST) doit nous inciter à visiter TOUS le nœud (au plus une fois), et avec la même exigence rationnelle de visiter chaque bord au plus une fois également.

Cela dit, Dijkstra nous permet de "prendre des raccourcis" si longtemps que je peux aller de s à t, sans s’inquiéter des conséquences - une fois que j’arrive à t, j’en ai terminé! Bien qu'il y ait aussi un chemin de s à t dans le MST, mais ce chemin s -t est créé en tenant compte de tous les nœuds restants. Par conséquent, ce chemin peut être plus long que le chemin s -t trouvé par l'algorithme de Dijstra. Vous trouverez ci-dessous un exemple rapide avec 3 nœuds:

                                  2       2  
                          (s) o ----- o ----- o (t)     
                              |               |
                              -----------------
                                      3

Supposons que chaque bord supérieur a un coût de 2 et que le bord inférieur a un coût de 3, alors Dijktra nous dira de prendre le chemin du bas, car nous ne nous soucions pas du nœud du milieu. D'autre part, Prim nous retournera un MST avec les 2 bords supérieurs, en rejetant le bord inférieur. 

Cette différence se reflète également dans la différence subtile entre les implémentations: dans l’algorithme de Dijkstra, une étape de tenue de livre (pour chaque nœud) est nécessaire pour mettre à jour le chemin le plus court à partir de s, après absorption d’un nouveau nœud, alors que dans L'algorithme de Prim, il n'y a pas un tel besoin.

1
ccy

L'explication la plus simple est dans Prims, vous ne spécifiez pas le nœud de départ, mais dans la dijsktra vous (Besoin d’un nœud de départ) devez trouver le chemin le plus court du nœud donné à tous les autres nœuds.

0
Deepak Yadav