forked from algorithm-visualizer/tracers.cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdijkstra.cpp
More file actions
109 lines (92 loc) · 3.28 KB
/
dijkstra.cpp
File metadata and controls
109 lines (92 loc) · 3.28 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
// import visualization libraries {
#include "algorithm-visualizer.h"
// }
#include <vector>
#include <string>
#include <limits>
using json = nlohmann::json;
// Tracers: graph, array1d (S) and log console
GraphTracer tracer = GraphTracer().directed(false).weighted().layoutCircle();
Array1DTracer tracerS = Array1DTracer("Distances");
LogTracer logger = LogTracer("Console");
int main() {
const int N = 5;
// generate random graph like JS example: Randomize.Graph({ N: 5, ratio: 1, directed: false, weighted: true })
std::vector<int> Gmat(N * N);
Randomize::Integer randWeight(1, 9);
Randomize::Graph<int> Ggen(N, 1.0, randWeight);
// do NOT chain these methods: they return by value, which would modify a temporary
// (so Ggen would keep its defaults). Call them separately to modify the original.
Ggen.directed(false);
Ggen.weighted(true);
Ggen.fill(Gmat.data());
// convert to 2D vector for tracer.set
std::vector<std::vector<int>> G2(N, std::vector<int>(N));
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
G2[i][j] = Gmat[i * N + j];
}
}
// initialize S (distance array) with INF
const int INF = std::numeric_limits<int>::max();
std::vector<int> S(N, INF);
// layout and initial set
Layout::setRoot(VerticalLayout({tracer, tracerS, logger}));
tracer.log(logger);
tracer.set(G2);
// prepare display array for tracerS: use strings for INF, numbers otherwise
std::vector<json> Sdisplay(N);
for (int i = 0; i < N; ++i) Sdisplay[i] = "INF";
tracerS.set(Sdisplay);
Tracer::delay();
// pick random start and end (s != e)
Randomize::Integer randNode(0, N - 1);
int s = randNode.create();
int e;
do { e = randNode.create(); } while (e == s);
logger.println(std::string("finding the shortest path from ") + std::to_string(s) + " to " + std::to_string(e));
Tracer::delay();
// Dijkstra
std::vector<bool> D(N, false);
S[s] = 0;
tracerS.patch(s, 0);
Tracer::delay();
tracerS.depatch(s);
tracerS.select(s);
int k = N;
while (k--) {
int minIndex = -1;
int minDistance = INF;
for (int i = 0; i < N; ++i) {
if (!D[i] && S[i] < minDistance) {
minDistance = S[i];
minIndex = i;
}
}
if (minDistance == INF) break;
D[minIndex] = true;
tracerS.select(minIndex);
tracer.visit(minIndex);
Tracer::delay();
for (int i = 0; i < N; ++i) {
if (G2[minIndex][i] && S[i] > S[minIndex] + G2[minIndex][i]) {
S[i] = S[minIndex] + G2[minIndex][i];
tracerS.patch(i, S[i]);
tracer.visit(i, minIndex, S[i]);
Tracer::delay();
tracerS.depatch(i);
tracer.leave(i, minIndex);
Tracer::delay();
}
}
tracer.leave(minIndex);
Tracer::delay();
}
if (S[e] == INF) {
logger.println(std::string("there is no path from ") + std::to_string(s) + " to " + std::to_string(e));
} else {
logger.println(std::string("the shortest path from ") + std::to_string(s) + " to " + std::to_string(e) + " is " + std::to_string(S[e]));
}
Tracer::delay();
return 0;
}