web-dev-qa-db-fra.com

Différence entre les algorithmes de Prim et de Dijkstra?

Quelle est la différence exacte entre les algorithmes de Dijkstra et de Prim? Je sais que Prim donnera un MST, mais l’arbre généré par Dijkstra sera également un MST. Alors quelle est la différence exacte?

65
anuj pradhan

L'algorithme de Prim construit un minimum spanning tree pour le graphe, qui est un arbre qui connecte tous les nœuds du graphe et a le coût total le moins élevé parmi tous les arbres reliant tous les nœuds. Toutefois, la longueur d'un chemin entre deux nœuds quelconques du MST peut ne pas être le chemin le plus court entre ces deux nœuds dans le graphique d'origine. Les MST sont utiles, par exemple, si vous souhaitez câbler physiquement les nœuds du graphique pour leur fournir de l'électricité au moindre coût total. Peu importe que la longueur du chemin entre deux nœuds ne soit pas optimale, tout ce qui compte pour vous, c'est le fait qu'ils soient connectés.

L'algorithme de Dijkstra construit un arbre le plus court chemin à partir d'un noeud source. Une arborescence de chemin le plus court est une arborescence qui connecte tous les nœuds du graphique au nœud source et a la propriété de minimiser la longueur de tout chemin allant du nœud source à tout autre nœud du graphique. Ceci est utile, par exemple, si vous souhaitez construire un réseau routier qui soit le plus efficace possible pour permettre à chacun d’atteindre un point de repère important. Toutefois, il n’est pas garanti que l’arbre de chemin le plus court soit un arbre couvrant minimal, et le coût de la construction d’un tel arbre pourrait être beaucoup plus élevé que celui d’un TMS.

Une autre différence importante concerne les types de graphes sur lesquels travaillent les algorithmes. L'algorithme de Prim fonctionne uniquement sur les graphes non dirigés, car le concept de MST suppose que les graphes sont intrinsèquement non dirigés. (Il existe quelque chose appelé "arborescence minimale" pour les graphes dirigés, mais les algorithmes pour les trouver sont beaucoup plus compliqués). L'algorithme de Dijkstra fonctionnera bien sur les graphes dirigés, car les arbres des plus courts chemins peuvent effectivement être dirigés. De plus, l'algorithme de Dijkstra ne donne pas nécessairement la solution correcte dans les graphiques contenant des pondérations de bord négatives , alors que l'algorithme de Prim peut le gérer.

J'espère que cela t'aides!

114
templatetypedef

L'algorithme de Dijkstra ne crée pas de MST, il trouve le chemin le plus court.

Considérez ce graphique 

       5     5
  s *-----*-----* t
     \         /
       -------
         9

Le chemin le plus court est 9, tandis que le MST est un "chemin" différent à 10.

72
dfb

Les algorithmes Prim et Dijkstra sont presque les mêmes, sauf pour la "fonction relax".

En prim:

MST-PRIM (G, w, r) {

        for each key ∈ G.V

            u.key = ∞
            u.parent = NIL

        r.key = 0
        Q = G.V
        while (Q ≠ ø)

            u = Extract-Min(Q)
            for each v ∈ G.Adj[u]

                if (v ∈ Q) and w(u,v) < v.key

                    v.parent = u
                    v.key = w(u,v)    <== relax function, Pay attention here

}

À Dijkstra:

Dijkstra (G, w, r) {

        for each key ∈ G.V

            u.key = ∞
            u.parent = NIL

        r.key = 0
        Q = G.V
        while (Q ≠ ø)

            u = Extract-Min(Q)
            for each v ∈ G.Adj[u]

                if (v ∈ Q) and w(u,v) < v.key

                    v.parent = u
                    v.key = w(u,v) + u.key  <== relax function, Pay attention here

}

La seule différence est la dernière ligne du code, qui est la fonction relax . Le Prim, qui recherche le Spanning Tree minimum, ne se soucie que du minimum des arêtes totales couvrant tous les sommets . ressemble à: v.key = w (u, v) Le Dijkstra, qui recherche la longueur minimale du chemin d'accès, afin de se préoccuper de l'accumulation de bords . , v) + clé

47
Albert Chen

Dijkstra trouve le chemin le plus court entre son nœud de début et tous les autres nœuds. Donc, en retour, vous obtenez l’arbre de distance minimum depuis le nœud de début, c’est-à-dire que vous pouvez atteindre chaque nœud le plus efficacement possible.

L'algorithme Prims vous fournit le MST pour un graphe donné, c'est-à-dire un arbre qui connecte tous les nœuds alors que la somme de tous les coûts est le minimum possible.

Pour faire une histoire courte avec un exemple réaliste:

  1. Dijkstra souhaite connaître le chemin le plus court vers chaque destination en économisant temps de trajet et carburant.
  2. Prim veut savoir comment déployer efficacement un système de train, c’est-à-dire économiser sur les coûts de matériel.
14
Rahul

Directement à partir de Article sur l'algorithme de Dijkstra wikipedia:

Le processus à la base de l'algorithme de Dijkstra est similaire au processus glouton utilisé dans l'algorithme de Prim. Le but de Prim est de trouver un arbre couvrant minimal qui connecte tous les nœuds du graphique. Dijkstra ne concerne que deux nœuds. Prim's n'évalue pas le poids total du chemin à partir du nœud de départ, mais uniquement du chemin individuel.

8
im so confused

La principale différence entre les algorithmes de base réside dans leurs différents critères de sélection des arêtes. Ils utilisent généralement une file d'attente prioritaire pour sélectionner les nœuds suivants, mais ont des critères différents pour sélectionner les nœuds adjacents des nœuds de traitement actuels: L'algorithme de Prim exige que les nœuds adjacents suivants soient également conservés dans la file d'attente, contrairement à l'algorithme de Dijkstra:

def dijkstra(g, s):
    q <- make_priority_queue(VERTEX.distance)
    for each vertex v in g.vertex:
        v.distance <- infinite
        v.predecessor ~> nil
        q.add(v)
    s.distance <- 0
    while not q.is_empty:
        u <- q.extract_min()
        for each adjacent vertex v of u:
            ...

def prim(g, s):
    q <- make_priority_queue(VERTEX.distance)
    for each vertex v in g.vertex:
        v.distance <- infinite
        v.predecessor ~> nil
        q.add(v)
    s.distance <- 0
    while not q.is_empty:
        u <- q.extract_min()
        for each adjacent vertex v of u:
            if v in q and weight(u, v) < v.distance:// <-------selection--------
            ...

Les calculs de vertex.distance sont le deuxième point différent. 

3
象嘉道

Algorithme Dijkstras est utilisé uniquement pour trouver le chemin le plus court.

In Spanning Tree minimum (algorithme de Prim ou Kruskal) vous obtenez un minimum egdes avec une valeur minimale de Edge.

Par exemple: - Imaginez une situation dans laquelle vous ne voudriez pas créer un réseau énorme pour lequel vous aurez besoin d'un grand nombre de fils afin que leur comptage puisse être effectué à l'aide de Spanning Tree minimum (algorithme de Prim ou Kruskal) (c’est-à-dire qu’il vous donnera un nombre minimum de fils pour créer une connexion réseau câblée énorme avec un coût minimum).

Alors que "Algorithme de Dijkstras" sera utilisé pour obtenir le chemin le plus court entre deux nœuds tout en connectant les nœuds entre eux.

1
Dynamic Developer

@templatetypedef a couvert la différence entre MST et le plus court chemin. J'ai couvert la différence d'algorithme dans autre Donc, répondez en démontrant que les deux peuvent être implémentés en utilisant le même algorithme générique qui prend un paramètre supplémentaire en entrée: fonction f(u,v). La différence entre l'algorithme de Prim et celui de Dijkstra est simplement celle que vous utilisez f(u,v).

0
Shital Shah

La première distinction est que l’algorithme de Dijkstra résout un problème différent de celui de Kruskal et de Prim. Dijkstra résout le problème du plus court chemin (à partir d'un nœud spécifié), tandis que Kruskal et Prim trouvent un arbre recouvrant à coût minimal. Ce qui suit est une forme modifiée d’une description que j’ai écrite sur cette page: Algorithmes de graphes.

Pour tout graphe, un spanning-tree est un ensemble d'arêtes suffisant pour fournir exactement un chemin entre chaque paire de sommets. Cette restriction signifie qu'il ne peut y avoir aucun circuit formé par les bords choisis.

Un arbre de recouvrement à coût minimal est un arbre dont le poids total est le plus petit possible (le poids représentant le coût ou la distance). Il pourrait y avoir plus d'un arbre de ce type, mais Prim et Kruskal sont tous deux assurés de trouver l'un d'entre eux.

Pour un sommet spécifié (par exemple X), l’arbre de chemin le plus court est un arbre de recouvrement tel que le chemin de X à tout autre sommet soit aussi court que possible (c’est-à-dire qu’il a le poids le plus faible possible).

Prim et Dijkstra "poussent" l'arbre à partir d'un sommet de départ. En d'autres termes, ils ont un accent "local"; à chaque étape, nous ne considérons que les arêtes adjacentes aux sommets précédemment choisis, en choisissant l'option la moins chère qui répond à nos besoins. Dans le même temps, Kruskal est un algorithme "global", ce qui signifie que chaque Edge est choisi (avec gourmandise) dans l'ensemble du graphique. (En fait, Dijkstra pourrait être considéré comme présentant un aspect global, comme indiqué ci-dessous.)

Pour trouver un arbre recouvrant à coût minimum:

Kruskal (approche globale): à chaque étape, choisissez l’Edge disponible le moins cher n’importe où n’enfreignant pas l’objectif de création d’un Spanning Tree . Prim (approche locale): Choisissez un sommet de départ. À chaque étape successive, choisissez l’arête disponible la moins chère attachée à tout sommet précédemment sélectionné qui ne viole pas l’objectif de la création d’un arbre recouvrant .. Pour trouver un arbre recouvrant le plus court chemin:

Dijkstra: à chaque étape, choisissez l’arête attachée à tout sommet précédemment sélectionné (aspect local), ce qui rend la distance totale par rapport au sommet de départ (aspect global) aussi petite que possible et ne viole pas l’objectif de la création d’un arbre recouvrant. .

Les arbres à coûts minimums et les arbres les plus courts sont facilement confondus, de même que les algorithmes Prim et Dijkstra qui les résolvent. Les deux algorithmes "se développent" à partir du sommet de départ, choisissant à chaque étape un bord qui relie un sommet Y situé dans l'arbre à un sommet Z qui ne l'est pas. Cependant, même si Prim choisit Edge le moins cher, Dijkstra choisit Edge, ce qui donne le chemin le plus court de X à Z.

Une illustration simple est utile pour comprendre la différence entre ces algorithmes et les arbres qu’ils produisent. Dans le graphique ci-dessous, en commençant par le sommet A, Prim et Dijkstra commencent par choisir Edge AB, puis par ajouter Edge BD. Voici où les deux algorithmes divergent: Prim complète l'arborescence en ajoutant Edge DC, tandis que Dijkstra ajoute AC ou BC, car les chemins A-C et A-B-C (les deux avec une distance totale de 30) sont plus courts que le chemin A-B-D-C (distance totale de 31).

0
Naren

Au niveau du code, l’autre différence est l’API.

Vous initialisez Prim avec un sommet source, s , c'est-à-dire, Prim.new(s); s peut être n’importe quel sommet et, quel que soit le s , le résultat final correspondant aux bords de l’espacement minimal (MST) est identique. Pour obtenir les arêtes MST, nous appelons la méthode edges().

Vous initialisez Dijkstra avec un sommet source, s , c.-à-d. Dijkstra.new(s), selon lequel vous voulez obtenir le chemin/la distance le plus court possible vers tous les autres sommets. Les résultats finaux, qui sont le plus court chemin/distance de s à tous les autres sommets; sont différents selon les s . Pour obtenir les chemins/distances les plus courts entre s et tout sommet, v , nous appelons les méthodes distanceTo(v) et pathTo(v) respectivement.

0
nethsix