Dijkstra:Shortest Route Calculation - Object Oriented






4.32/5 (23 votes)
Calculation of the shortest path between x points
In this example, the shortest route from 0 to 4 is going through location 2, 1 and then 4.
Introduction
Dijkstra was a Dutch computer scientist who invented a fast and simple way to calculate the shortest path between two points. Many examples I have found on the Internet implement that algorithm but none of them have done it in an Object Oriented way. So I thought of making my own.
Background
Information about Dijkstra can be found here.
Using the Code
The code contains two Project classes:
GUI
: Shows the information visually- To add locations, click on the 'Add Location' button and then click on the map where you want to add locations.
- To add routes, click on the 'Add Location' button to deactivate the add location, then click on a start location, then click on a end location. The weight of the route can be configured on top.
RouteEngine
: Calculates the route
I will only go into details about the RouteEngine
. How the UI is handled is not so important for this article but if you need information about it, you can always ask.
Project RouteEngine
Connection
: This class holds the information about the connection between two dots. This is a one directional connection from A (the startpoint is visually shown with a dot) to B with a specific weight attached.Location
: Just a location (for example 1).RouteEngine
: This class will calculate all routes from one givenstartPoint
.Route
: This class holds the information about a route between two points (generated with theRouteEngine
class).
Location
The most simple class. It only holds a name to display.
Connection
This class contains two Location
objects and a weight
.
public Connection(Location a, Location b, int weight)
{
this._a = a;
this._b = b;
this._weight = weight;
}
Route
This class contains a route. It has only a list of connections and the total weight. This class is generated by the route engine.
Route Engine
This is the class that drives the component. The algorithm is as follows:
- Set the
startPosition
as active - Set the total weight to all routes to infinite
- Iterate through all connections of the active position and store their weight if their weight is smaller than their current weight
- Set the active position as used
- Set the nearest point (on whatever location) that isn't used as active
- Repeat 3, 4, 5 until all positions are used
The following method will perform all these steps (and some extra checking and thinking). The Dictionary
returned is a list of destination locations and the corresponding route to each destination location.
///
/// Calculates the shortest route to all the other locations
///
/// List of all locations and their shortest route
public Dictionary CalculateMinCost(Location _startLocation)
{
//Initialise a new empty route list
Dictionary _shortestPaths = new Dictionary ();
//Initialise a new empty handled locations list
List _handledLocations = new List ();
//Initialise the new routes. the constructor will set the route weight to in.max
foreach (Location location in _locations)
{
_shortestPaths.Add(location, new Route(location.Identifier));
}
//The startPosition has a weight 0.
_shortestPaths[_startLocation].Cost = 0;
//If all locations are handled, stop the engine and return the result
while (_handledLocations.Count != _locations.Count)
{
//Order the locations
List _shortestLocations = (List < Location > )(from s in _shortestPaths
orderby s.Value.Cost
select s.Key).ToList();
Location _locationToProcess = null;
//Search for the nearest location that isn't handled
foreach (Location _location in _shortestLocations)
{
if (!_handledLocations.Contains(_location))
{
//If the cost equals int.max, there are no more possible connections
//to the remaining locations
if (_shortestPaths[_location].Cost == int.MaxValue)
return _shortestPaths;
_locationToProcess = _location;
break;
}
}
//Select all connections where the startposition is the location to Process
var _selectedConnections = from c in _connections
where c.A == _locationToProcess
select c;
//Iterate through all connections and search for a connection which is shorter
foreach (Connection conn in _selectedConnections)
{
if (_shortestPaths[conn.B].Cost > conn.Weight + _shortestPaths[conn.A].Cost)
{
_shortestPaths[conn.B].Connections =
_shortestPaths[conn.A].Connections.ToList();
_shortestPaths[conn.B].Connections.Add(conn);
_shortestPaths[conn.B].Cost = conn.Weight + _shortestPaths[conn.A].Cost;
}
}
//Add the location to the list of processed locations
_handledLocations.Add(_locationToProcess);
}
return _shortestPaths;
}
History
- 24 December, 2007: First release