1
+ /**
2
+ * Djkalgo's algorithm,is a graph search algorithm that solves the single-source
3
+ * shortest path problem for a graph with nonnegative edge path costs, producing
4
+ * a shortest path tree.
5
+ * Help from RosettaCode
6
+ Visual representation
7
+ */
8
+
9
+ import java .util .*;
10
+
11
+ public class Djkalgo {
12
+ private static final Graph .Edge [] GRAPH = {
13
+ // Distance from node "a" to node "b" is 7.
14
+ // In the current Graph there is no way to move the other way (e,g, from "b" to "a"),
15
+ // a new edge would be needed for that
16
+ new Graph .Edge ("a" , "b" , 8 ),
17
+ new Graph .Edge ("a" , "c" , 5 ),
18
+ new Graph .Edge ("a" , "f" , 3 ),
19
+ new Graph .Edge ("b" , "c" , 0 ),
20
+ new Graph .Edge ("b" , "d" , 16 ),
21
+ new Graph .Edge ("c" , "d" , 11 ),
22
+ new Graph .Edge ("c" , "f" , 84 ),
23
+ new Graph .Edge ("d" , "e" , 43 ),
24
+ new Graph .Edge ("e" , "f" , 11 ),
25
+ };
26
+ private static final String START = "a" ;
27
+ private static final String END = "e" ;
28
+
29
+ /**
30
+ *
31
+ * Runs graph
32
+ */
33
+ public static void main (String [] args ) {
34
+ Graph g = new Graph (GRAPH );
35
+ g .Djkalgo (START );
36
+ g .printPath (END );
37
+ //g.printAllPaths();
38
+ }
39
+ }
40
+
41
+ class Graph {
42
+ private final Map <String , Vertex > graph ;
43
+
44
+ /**
45
+ * One edge of the graph (only used by Graph constructor)
46
+ */
47
+ public static class Edge {
48
+ public final String v1 , v2 ;
49
+ public final int dist ;
50
+
51
+ public Edge (String v1 , String v2 , int dist ) {
52
+ this .v1 = v1 ;
53
+ this .v2 = v2 ;
54
+ this .dist = dist ;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * One vertex of the graph, complete with mappings to neighbouring vertices
60
+ */
61
+ public static class Vertex implements Comparable <Vertex > {
62
+ public final String name ;
63
+ // MAX_VALUE assumed to be infinity
64
+ public int dist = Integer .MAX_VALUE ;
65
+ public Vertex previous = null ;
66
+ public final Map <Vertex , Integer > neighbours = new HashMap <>();
67
+
68
+ public Vertex (String name ) {
69
+ this .name = name ;
70
+ }
71
+
72
+ private void printPath () {
73
+ if (this == this .previous ) {
74
+ System .out .printf ("%s" , this .name );
75
+ } else if (this .previous == null ) {
76
+ System .out .printf ("%s(unreached)" , this .name );
77
+ } else {
78
+ this .previous .printPath ();
79
+ System .out .printf (" -> %s(%d)" , this .name , this .dist );
80
+ }
81
+ }
82
+
83
+ public int compareTo (Vertex other ) {
84
+ if (dist == other .dist )
85
+ return name .compareTo (other .name );
86
+
87
+ return Integer .compare (dist , other .dist );
88
+ }
89
+
90
+ @ Override
91
+ public String toString () {
92
+ return "(" + name + ", " + dist + ")" ;
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Builds a graph from a set of edges
98
+ */
99
+ public Graph (Edge [] edges ) {
100
+ graph = new HashMap <>(edges .length );
101
+
102
+ // one pass to find all vertices
103
+ for (Edge e : edges ) {
104
+ if (!graph .containsKey (e .v1 )) graph .put (e .v1 , new Vertex (e .v1 ));
105
+ if (!graph .containsKey (e .v2 )) graph .put (e .v2 , new Vertex (e .v2 ));
106
+ }
107
+
108
+ // another pass to set neighbouring vertices
109
+ for (Edge e : edges ) {
110
+ graph .get (e .v1 ).neighbours .put (graph .get (e .v2 ), e .dist );
111
+ // graph.get(e.v2).neighbours.put(graph.get(e.v1), e.dist); // also do this for an undirected graph
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Runs Djkalgo using a specified source vertex
117
+ */
118
+ public void Djkalgo (String startName ) {
119
+ if (!graph .containsKey (startName )) {
120
+ System .err .printf ("Graph doesn't contain start vertex \" %s\" \n " , startName );
121
+ return ;
122
+ }
123
+ final Vertex source = graph .get (startName );
124
+ NavigableSet <Vertex > q = new TreeSet <>();
125
+
126
+ // set-up vertices
127
+ for (Vertex v : graph .values ()) {
128
+ v .previous = v == source ? source : null ;
129
+ v .dist = v == source ? 0 : Integer .MAX_VALUE ;
130
+ q .add (v );
131
+ }
132
+
133
+ Djkalgo (q );
134
+ }
135
+
136
+ /**
137
+ * Implementation of Djkalgo's algorithm using a binary heap.
138
+ */
139
+ private void Djkalgo (final NavigableSet <Vertex > q ) {
140
+ Vertex u , v ;
141
+ while (!q .isEmpty ()) {
142
+ // vertex with shortest distance (first iteration will return source)
143
+ u = q .pollFirst ();
144
+ if (u .dist == Integer .MAX_VALUE )
145
+ break ; // we can ignore u (and any other remaining vertices) since they are unreachable
146
+
147
+ // look at distances to each neighbour
148
+ for (Map .Entry <Vertex , Integer > a : u .neighbours .entrySet ()) {
149
+ v = a .getKey (); // the neighbour in this iteration
150
+
151
+ final int alternateDist = u .dist + a .getValue ();
152
+ if (alternateDist < v .dist ) { // shorter path to neighbour found
153
+ q .remove (v );
154
+ v .dist = alternateDist ;
155
+ v .previous = u ;
156
+ q .add (v );
157
+ }
158
+ }
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Prints a path from the source to the specified vertex
164
+ */
165
+ public void printPath (String endName ) {
166
+ if (!graph .containsKey (endName )) {
167
+ System .err .printf ("Graph doesn't contain end vertex \" %s\" \n " , endName );
168
+ return ;
169
+ }
170
+
171
+ graph .get (endName ).printPath ();
172
+ System .out .println ();
173
+ }
174
+
175
+ /**
176
+ * Prints the path from the source to every vertex (output order is not guaranteed)
177
+ */
178
+ public void printAllPaths () {
179
+ for (Vertex v : graph .values ()) {
180
+ v .printPath ();
181
+ System .out .println ();
182
+ }
183
+ }
184
+ }
0 commit comments