I wrote this article in order to share
the source-code of a basic implementation of
the the Dijkstra's algorithm. Readers
after
full-featured,
industrial-strength
Java implementations
of Dijkstra's shortest path algorithm should look into JGL and JDSL,
among others (Thanks to Renaud Waldura for the links taken from his article).

Credits - about the author of this article and the license
to respect if you want to use the code

Important :Update from
the 04/03/2004 : there was a bug in the PriorityQueue
class which was generated inaccurate results. I'd like to thank Olivier Daroux
for telling me about the problem and fixing it. I have updated the source-code
and it is available for download.

If you are not familiar with graph theory, I suggest you to read a bit of
literature
about it see Links.

What is a weighted directed graph ?

A graph is a set of vertices, connected by edges.

In an directed graph, each edge has a direction (represented by an arrow).

In a weighted graph, each edge is assigned a weight. The weight can be
assimilated to the distance between 2 vertices.

Structures that can be represented as graphs are ubiquitous, and many
problems of practical interest can be formulated as questions about certain
graphs. One of the best example is a railway network :

Each train station is a vertex

The railways between 2 stations are an edge

The distance between 2 train stations is equivalent to the weight

Typical problems which can be solved with graphs :

Shortest path problem

Route inspection problem (aka "Chinese Postman Problem")

Traveling salesman problem

The Dijkstra's algorithm

Definition

The Dijkstra's algorithm is used to find the shortest paths from a single source
vertex to all other vertices in a weighted, directed graph. All weights must
be nonnegative. You can have a look to the formal
definition of this algorithm if it can help you (it did not help me !).

Implementation in java

Let's define the following data structures :

shortestPathMap, the result map of the shortest path distances from a start
vertex after running the algorithm

predecessorsMap, the result map of predecessors of the shortest path from
a start vertex after running the algorithm

determindedVerticesSet, the set of vertices whose shortest paths from the
source have already been determined

remainingVerticesQueue, the list of remaining vertices, implemented as a
priority queue

runAlgorihtm(Object sourceVertex, Object destinationVertex) {
// Initialization, empty all data structures
shortestPathMap.clear();
predecessorsMap.clear();
determinedVerticesSet.clear();
remainingVerticesQueue.clear();
// add source vertex with a distance of 0
shortestPathMap.put(sourceVertex, new Integer(0));
// Insert source vertex with a distance of 0
remainingVerticesQueue.insert(sourceVertex, 0);
// While the priority queue is not empty
while ( !remainingVerticesQueue.isEmpty() ) {
// Sort the vertices in the Remaining vertices according to their distance from the source
// and select the closest one (i.e. dequeue the element with the lowest priority in the queue)
Object closest = remainingVerticesQueue.dequeueLowestPriorityElement();
// if the destination is reached, stop the execution
if ( closest.equals(destinationVertex) ) {
break;
}
// Add the closest vertex to the determined Vertices set
determinedVerticesSet.add(closest);
// Relaxation, see explanations below
relax(closest);
}
}

The PriorityQueue

I have used a Priority Queue to solve the problem of finding the closest
element. A Priority Queue is a collection of elements ordered by a priority
(positive integer).

The relax method

/**
* The relaxation process updates the costs of all the vertices v connected to a vertex u
* if we could improve the best estimate of the shortest path to v by including (u,v) in the path to v.
* @param vertex whose adjacent's vertices should be relaxed
*/
private void relax(Object vertex) {
// Iterate on adjacent vertices to the vertex which is relaxed
Iterator adjacentVertices = graph.getAdjacentVertices(vertex);
while (adjacentVertices.hasNext()) {
Object adjVertex = adjacentVertices.next();
// Do not relax elements which are already determined
if (!determinedVerticesSet.contains(adjVertex)) {
// distance = shortest distance from source + distance(vertex, adjacent vertex)
int distance = getShortestPathFromSource(vertex) + graph.getEdgeWeight(vertex, adjVertex);
// Have we found a shortest path ?
if (getShortestPathFromSource(adjVertex) > distance) {
// update shortest path result map
setShortestPathFromStart(adjVertex, distance);
// update predessors map result
predecessorsMap.put(adjVertex, vertex);
// re-balance the remaining vertices according to the new shortest distance found
remainingVerticesQueue.insert(adjVertex, distance);
}
}
} // end while
}

The best way to understand how the algorithm works is to have a look to the
applet
demo.

There is an IMAGE MAP on the diagram : click on a class to see its javadoc.

IGraph is the Interface
which specifies a weighted oriented graph. All search algorithms and client
classes use that Interface to deal with graphs. If the implementation changes,
no change will be needed in the clients classes (that's the advantages of using
Interfaces !).

Doing Simple Design. The implementation of IGraph is the simplest as possible
: an adjacency matrix AM, with AM[start][destination] = weight. If AM[start][destination]
= 0, the path does not exist. This implementation is probably not the fastest.
Moreover, if the graph has a big number of vertices and a few edges, it wastes
a lot of memory. That's why choosing an implementation of the graph depending
the number of vertices / edges would be great for performances. Others possible
implementations are adjacency list and edge list.

I have chosen to design the graph class as generic as possible. So it is a
graph of objects Object ! The objects in the graphs are supposed to be Cloneable
or the Finders methods will get some troubles !

Tests

Of course, I have written Junit tests (before the implementation as XP
practice advises) to test the algorithms. I have also used a MockGraph class
to simulate a graph in order to test search algorithms used by PathFinder and
Dijkstra.

I am an European software engineer who lives and works in London. For any
comments / suggestions : send an e-mail to g a r n i e r j m @ y a h o o.f
r (remove the spaces to get my e-mail, I have done that bc the sobig virus
has filled my mailbox!)