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