Menu
Coddy logo textTech

Algorithme de Prim

Dernière mise à jour

L'algorithme de Prim construit un arbre couvrant minimal (MST) - l'ensemble d'arêtes le moins cher reliant tous les nœuds sans cycle - en faisant croître un seul arbre vers l'extérieur à partir d'un nœud de départ. À chaque étape, il examine toutes les arêtes qui traversent de l'arbre vers un nœud extérieur et ajoute la moins chère. Appuyez sur lecture ci-dessus pour voir l'arbre s'étendre, en prenant toujours l'arête de plus faible poids qui atteint un nouveau nœud.

Comme il choisit toujours l'arête de coupe minimale, chaque ajout est sûr (garanti de faire partie d'un MST). Avec une file de priorité basée sur un tas binaire indexée par l'arête la moins chère vers chaque nœud extérieur, Prim s'exécute en O(E log V). Il contraste avec Kruskal, qui trie toutes les arêtes globalement au lieu de faire croître un seul arbre connexe.

Complexité en temps et en espace

ImplémentationComplexitéNotes
Tas binaireO(E log V)File de priorité des arêtes de coupe
Matrice d'adjacenceO(V²)Plus simple ; adaptée aux graphes denses
EspaceO(V + E)Appartenance à l'arbre + file de priorité
Idéal pourGraphes densesCroît à partir d'un seul nœud de départ

Étape par étape

ÉtapeCe qui se passe
1Démarrez l'arbre avec un seul nœud quelconque.
2Examinez toutes les arêtes qui traversent de l'arbre vers un nœud extérieur.
3Choisissez l'arête de coupe de plus faible poids.
4Ajoutez cette arête et son nouveau nœud à l'arbre.
5Répétez jusqu'à ce que tous les nœuds soient dans l'arbre.

Exemple résolu

Construction du MST d'un graphe à 4 nœuds avec les arêtes A-B=1, A-C=3, B-C=2, B-D=4, C-D=5, en partant de A :

ÉtapeArbreArêtes de coupeArête choisie
1{A}A-B=1, A-C=3A-B (poids 1)
2{A, B}A-C=3, B-C=2, B-D=4B-C (poids 2)
3{A, B, C}B-D=4, C-D=5B-D (poids 4)
4{A, B, C, D}aucune - tous les nœuds dans l'arbreterminé : poids du MST 1+2+4 = 7

Quand utiliser l'algorithme de Prim

À utiliser quandÀ éviter quand
Vous avez besoin d'un arbre couvrant minimal d'un graphe connexe, non orienté et pondéré.Le graphe est orienté ou vous avez besoin des plus courts chemins - utilisez Dijkstra ou Bellman-Ford.
Le graphe est dense (E proche de ) ; la forme matricielle O(V²) est simple et rapide.Le graphe est creux et les arêtes sont déjà triées ou faciles à trier - Kruskal est souvent plus simple.
Vous voulez que l'arbre croisse d'une région vers l'extérieur (par ex. disposition incrémentale d'un réseau).Le graphe est déconnecté - Prim ne couvre qu'un composant ; vous avez besoin d'une forêt couvrante minimale.
Vous disposez déjà d'une structure d'adjacence et d'une file de priorité.Vous devez détecter des cycles sur un ensemble global d'arêtes - union-find (Kruskal) convient mieux à ce cas.

Code de Prim's Algorithm

Une implémentation propre et exécutable de Prim's Algorithm en Python, JavaScript, Java, C++, C. Choisissez un langage, copiez le code ou ouvrez-le préchargé dans le Playground Coddy.

Code de Prim's Algorithm en Python

Python
1import heapq2
3
4def prim(graph, start):5    visited = {start}6    heap = [(w, start, v) for v, w in graph[start]]7    heapq.heapify(heap)8    mst, total = [], 09    while heap and len(visited) < len(graph):10        w, u, v = heapq.heappop(heap)11        if v in visited:12            continue13        visited.add(v)14        mst.append((u, v, w))15        total += w16        # Offer the new node's edges to the frontier17        for neighbor, weight in graph[v]:18            if neighbor not in visited:19                heapq.heappush(heap, (weight, v, neighbor))20    return mst, total21
22
23graph = {24    "A": [("B", 4), ("C", 1)],25    "B": [("A", 4), ("C", 3), ("D", 2)],26    "C": [("A", 1), ("B", 3), ("D", 5)],27    "D": [("B", 2), ("C", 5), ("E", 7)],28    "E": [("D", 7)],29}30
31mst, total = prim(graph, "A")32for u, v, w in mst:33    print(f"{u} - {v} (weight {w})")34print("Total MST weight:", total)
Exécutez ce code dans le Playground Python

FAQ sur l'algorithme de Prim

Quelle est la complexité temporelle de l'algorithme de Prim ?
Avec une file de priorité basée sur un tas binaire, Prim s'exécute en O(E log V). Une version plus simple avec matrice d'adjacence qui balaie l'arête de coupe minimale à chaque étape est en O(V²), ce qui peut être plus rapide sur les graphes denses. Les deux utilisent un espace O(V + E).
Quelle est la différence entre les algorithmes de Prim et de Kruskal ?
Tous deux trouvent un arbre couvrant minimal de manière gloutonne. Prim fait croître un seul arbre connexe à partir d'un nœud de départ, en ajoutant à répétition l'arête la moins chère qui quitte l'arbre (à l'aide d'une file de priorité). Kruskal considère toutes les arêtes triées par poids et ajoute la moins chère qui ne forme pas de cycle (à l'aide de union-find). Prim est souvent préféré sur les graphes denses, Kruskal sur les graphes creux.
L'algorithme de Prim trouve-t-il toujours le MST optimal ?
Oui. À chaque étape, l'arête la moins chère qui traverse l'arbre actuel est sûre à ajouter - elle appartient à un arbre couvrant minimal (la propriété de coupe). Ajouter à répétition des arêtes sûres donne un véritable arbre couvrant minimal, à condition que le graphe soit connexe.
Quand devrais-je utiliser l'algorithme de Prim plutôt que celui de Kruskal ?
Tournez-vous vers Prim quand le graphe est dense, car sa forme matricielle O(V²) évite de trier les E arêtes et fait croître un seul arbre à partir d'un nœud de départ. Kruskal brille sur les graphes creux où trier la liste d'arêtes est peu coûteux et où union-find garde les vérifications de cycles rapides. Les deux produisent un MST correct, donc le choix dépend surtout de la densité des arêtes et des structures de données dont vous disposez déjà.
Le nœud de départ affecte-t-il le MST obtenu ?
Non - le poids total du MST est le même quel que soit le nœud de départ, car le poids de l'arbre couvrant minimal d'un graphe connexe est unique. Les arêtes précises ne peuvent différer que lorsque plusieurs arêtes partagent le même poids et que plusieurs MST existent. Sinon, Prim atteint exactement le même arbre quel que soit le nœud de départ.
L'algorithme de Prim peut-il gérer les graphes déconnectés ?
Pas directement. Prim fait croître un seul arbre, il ne couvre donc que le composant connexe contenant le nœud de départ et laisse le reste intact. Pour couvrir chaque composant, vous exécuteriez Prim à répétition à partir d'un nœud non visité, produisant une forêt couvrante minimale plutôt qu'un seul arbre.
Coddy programming languages illustration

Maîtrisez les algorithmes avec Coddy

COMMENCER