-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprims.go
More file actions
125 lines (105 loc) · 4.02 KB
/
Copy pathprims.go
File metadata and controls
125 lines (105 loc) · 4.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package main
import (
sh "algo/shared"
"container/heap"
"fmt"
"math"
)
func runPrims() {
// sommets
a := &sh.Vertex{Name: "a"}
b := &sh.Vertex{Name: "b"}
c := &sh.Vertex{Name: "c"}
d := &sh.Vertex{Name: "d"}
e := &sh.Vertex{Name: "e"}
f := &sh.Vertex{Name: "f"}
g := &sh.Vertex{Name: "g"}
h := &sh.Vertex{Name: "h"}
i := &sh.Vertex{Name: "i"}
vertices := []*sh.Vertex{a, b, c, d, e, f, g, h, i}
edges := []*sh.Edge{
{Weight: 10, Origin: a, Destination: b}, // a → b
{Weight: 12, Origin: a, Destination: c}, // a → c
{Weight: 9, Origin: b, Destination: c}, // b → c
{Weight: 8, Origin: b, Destination: d}, // b → d
{Weight: 1, Origin: c, Destination: f}, // c → f
{Weight: 3, Origin: c, Destination: e}, // c → e
{Weight: 7, Origin: d, Destination: e}, // d → e
{Weight: 5, Origin: d, Destination: h}, // d → h
{Weight: 3, Origin: e, Destination: f}, // e → f
{Weight: 9, Origin: h, Destination: g}, // h → g
{Weight: 2, Origin: g, Destination: i}, // g → i
{Weight: 11, Origin: h, Destination: i}, // h → i
{Weight: 6, Origin: h, Destination: f}, // h → f
{Weight: 8, Origin: d, Destination: g}, // d → g
}
adjacents := make(map[*sh.Vertex][]*sh.Vertex)
for _, edge := range edges {
adjacents[edge.Origin] = append(adjacents[edge.Origin], edge.Destination)
adjacents[edge.Destination] = append(adjacents[edge.Destination], edge.Origin)
}
initialVertex := a
queue := sh.PriorityQueue(make([]*sh.PriorityItem, 0, len(vertices)))
heap.Init(&queue)
// Map pour garder une référence aux items dans la queue
itemMap := make(map[*sh.Vertex]*sh.PriorityItem)
for _, vertex := range vertices {
item := &sh.PriorityItem{
Value: vertex,
Priority: math.MaxInt,
}
if vertex == initialVertex {
item.Priority = 0
}
vertex.Color = sh.ColorGray // dans la queue
heap.Push(&queue, item)
itemMap[vertex] = item
}
// on veut stocker les edges du graphe minimum
minimumSpanningTreeEdges := make([]*sh.Edge, 0)
// va garder en mémoire la meilleure arête pour chaque sommet
// celle qui est connectée au graphe minimum
// et la plus proche
bestEdge := make(map[*sh.Vertex]*sh.Edge)
for len(queue) > 0 {
// On récupère le sommet avec la plus petite distance
item := heap.Pop(&queue).(*sh.PriorityItem)
vertex := item.Value.(*sh.Vertex)
// On ignore les sommets déjà traités (peuvent être présents plusieurs fois dans la queue)
if vertex.Color == sh.ColorBlack {
continue
}
vertex.Color = sh.ColorBlack // Marquer le sommet comme traité
fmt.Printf("On traite le sommet %s avec une priorité de %d\n", vertex.Name, item.Priority)
if e := bestEdge[vertex]; e != nil {
minimumSpanningTreeEdges = append(minimumSpanningTreeEdges, bestEdge[vertex])
}
for _, neighbor := range adjacents[vertex] {
if neighbor.Color == sh.ColorBlack {
fmt.Printf("Le voisin %s de %s est déjà traité, on l'ignore\n", neighbor.Name, vertex.Name)
continue
}
var edge *sh.Edge
for _, e := range edges {
if (e.Origin == vertex && e.Destination == neighbor) || (e.Destination == vertex && e.Origin == neighbor) {
edge = e
break
}
}
neigh := itemMap[neighbor]
fmt.Printf("On a un voisin (%s) de %s sur un chemin de poids %d (priorité %d)\n", neighbor.Name, vertex.Name, edge.Weight, neigh.Priority)
if (neighbor.Color == sh.ColorGray && edge != nil) && (edge.Weight < neigh.Priority) {
fmt.Printf("Le poids de l'arête %s --(%d)--> %s est inférieur à la priorité actuelle %d\n", vertex.Name, edge.Weight, neighbor.Name, neigh.Priority)
// Mettre à jour la priorité du voisin
fmt.Printf("Mise à jour de la priorité de %s avec le poids %d\n", neighbor.Name, edge.Weight)
queue.Update(neigh, neigh.Value, edge.Weight)
bestEdge[neighbor] = edge
}
}
}
fmt.Println("Arêtes du graphe minimum :")
for _, edge := range minimumSpanningTreeEdges {
fmt.Printf("%s --(%d)--> %s\n", edge.Origin.Name, edge.Weight, edge.Destination.Name)
}
fmt.Println("Graphe minimum construit avec Prim's algorithm.")
}