1+ // import visualization libraries {
2+ #include " algorithm-visualizer.h"
3+ // }
4+
5+ #include < vector>
6+ #include < string>
7+ #include < limits>
8+
9+ using json = nlohmann::json;
10+
11+ // Tracers: graph, array1d (S) and log console
12+ GraphTracer tracer = GraphTracer().directed(false ).weighted().layoutCircle();
13+ Array1DTracer tracerS = Array1DTracer(" Distances" );
14+ LogTracer logger = LogTracer(" Console" );
15+
16+ int main () {
17+ const int N = 5 ;
18+ // generate random graph like JS example: Randomize.Graph({ N: 5, ratio: 1, directed: false, weighted: true })
19+ std::vector<int > Gmat (N * N);
20+ Randomize::Integer randWeight (1 , 9 );
21+ Randomize::Graph<int > Ggen (N, 1.0 , randWeight);
22+ // do NOT chain these methods: they return by value, which would modify a temporary
23+ // (so Ggen would keep its defaults). Call them separately to modify the original.
24+ Ggen.directed (false );
25+ Ggen.weighted (true );
26+ Ggen.fill (Gmat.data ());
27+
28+ // convert to 2D vector for tracer.set
29+ std::vector<std::vector<int >> G2 (N, std::vector<int >(N));
30+ for (int i = 0 ; i < N; ++i) {
31+ for (int j = 0 ; j < N; ++j) {
32+ G2[i][j] = Gmat[i * N + j];
33+ }
34+ }
35+
36+ // initialize S (distance array) with INF
37+ const int INF = std::numeric_limits<int >::max ();
38+ std::vector<int > S (N, INF);
39+
40+ // layout and initial set
41+ Layout::setRoot (VerticalLayout ({tracer, tracerS, logger}));
42+ tracer.log (logger);
43+ tracer.set (G2);
44+
45+ // prepare display array for tracerS: use strings for INF, numbers otherwise
46+ std::vector<json> Sdisplay (N);
47+ for (int i = 0 ; i < N; ++i) Sdisplay[i] = " INF" ;
48+ tracerS.set (Sdisplay);
49+ Tracer::delay ();
50+
51+ // pick random start and end (s != e)
52+ Randomize::Integer randNode (0 , N - 1 );
53+ int s = randNode.create ();
54+ int e;
55+ do { e = randNode.create (); } while (e == s);
56+
57+ logger.println (std::string (" finding the shortest path from " ) + std::to_string (s) + " to " + std::to_string (e));
58+ Tracer::delay ();
59+
60+ // Dijkstra
61+ std::vector<bool > D (N, false );
62+ S[s] = 0 ;
63+ tracerS.patch (s, 0 );
64+ Tracer::delay ();
65+ tracerS.depatch (s);
66+ tracerS.select (s);
67+
68+ int k = N;
69+ while (k--) {
70+ int minIndex = -1 ;
71+ int minDistance = INF;
72+ for (int i = 0 ; i < N; ++i) {
73+ if (!D[i] && S[i] < minDistance) {
74+ minDistance = S[i];
75+ minIndex = i;
76+ }
77+ }
78+ if (minDistance == INF) break ;
79+
80+ D[minIndex] = true ;
81+ tracerS.select (minIndex);
82+ tracer.visit (minIndex);
83+ Tracer::delay ();
84+
85+ for (int i = 0 ; i < N; ++i) {
86+ if (G2[minIndex][i] && S[i] > S[minIndex] + G2[minIndex][i]) {
87+ S[i] = S[minIndex] + G2[minIndex][i];
88+ tracerS.patch (i, S[i]);
89+ tracer.visit (i, minIndex, S[i]);
90+ Tracer::delay ();
91+ tracerS.depatch (i);
92+ tracer.leave (i, minIndex);
93+ Tracer::delay ();
94+ }
95+ }
96+
97+ tracer.leave (minIndex);
98+ Tracer::delay ();
99+ }
100+
101+ if (S[e] == INF) {
102+ logger.println (std::string (" there is no path from " ) + std::to_string (s) + " to " + std::to_string (e));
103+ } else {
104+ logger.println (std::string (" the shortest path from " ) + std::to_string (s) + " to " + std::to_string (e) + " is " + std::to_string (S[e]));
105+ }
106+
107+ Tracer::delay ();
108+ return 0 ;
109+ }
0 commit comments