126 lines
3.9 KiB
JavaScript
126 lines
3.9 KiB
JavaScript
|
(function (exports) {
|
||
|
'use strict';
|
||
|
|
||
|
var dijkstra = (function () {
|
||
|
|
||
|
var Heap = require('../../data-structures/heap.js').Heap;
|
||
|
var current;
|
||
|
var visited;
|
||
|
var distance;
|
||
|
var unvisited;
|
||
|
|
||
|
/**
|
||
|
* Creates a new node instance.
|
||
|
*
|
||
|
* @constructor
|
||
|
* @private
|
||
|
* @param {Number} id Id of the node.
|
||
|
* @param {Number} distance Distance from the beginning.
|
||
|
*/
|
||
|
function Node(id, distance) {
|
||
|
this.node = id;
|
||
|
this.distance = distance;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Compares the distances between two nodes.
|
||
|
*
|
||
|
* @private
|
||
|
* @param {Node} a 1st node.
|
||
|
* @param {Node} b 2nd node.
|
||
|
* @returns {number} diff between node distances.
|
||
|
*/
|
||
|
function compareNodesDistance(a, b) {
|
||
|
return b.distance - a.distance;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Initialize all variables used for the algorithm.
|
||
|
*
|
||
|
* @private
|
||
|
* @param {number} src Start node.
|
||
|
* @param {Array} graph A distance matrix of the graph.
|
||
|
*/
|
||
|
function init(src, graph) {
|
||
|
var currentTemp;
|
||
|
current = {};
|
||
|
visited = [];
|
||
|
distance = [];
|
||
|
unvisited = new Heap(compareNodesDistance);
|
||
|
for (var i = 0; i < graph.length; i += 1) {
|
||
|
currentTemp = new Node();
|
||
|
if (src === i) {
|
||
|
currentTemp.distance = 0;
|
||
|
} else {
|
||
|
currentTemp.distance = Infinity;
|
||
|
}
|
||
|
currentTemp.node = i;
|
||
|
visited[i] = false;
|
||
|
distance[i] = currentTemp;
|
||
|
unvisited.add(currentTemp);
|
||
|
}
|
||
|
current.node = src;
|
||
|
current.distance = 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Dijkstra's shortest path algorithm. Finds the minimum
|
||
|
* distance between two given nodes using a distance matrix.<br><br>
|
||
|
* For the implementation is not used the most suitable data structure
|
||
|
* (Fibonacci heap) but the Binary heap gives also good results.<br><br>
|
||
|
*
|
||
|
* Time complexity: O(|E|+|V|log(|V|)) where V and E are the number of
|
||
|
* vertices and edges respectively.
|
||
|
*
|
||
|
* @public
|
||
|
* @module graphs/shortest-path/dijkstra
|
||
|
* @param {Number} src Source node.
|
||
|
* @param {Number} dest Destination node.
|
||
|
* @param {Array} graph A distance matrix of the graph.
|
||
|
* @returns {Number} The shortest distance between two nodes.
|
||
|
*
|
||
|
* @example
|
||
|
* var dijkstra =
|
||
|
* require('path-to-algorithms/src/graphs/shortest-path/dijkstra').dijkstra;
|
||
|
* var distMatrix =
|
||
|
* [[Infinity, 7, 9, Infinity, Infinity, 16],
|
||
|
* [7, Infinity, 10, 15, Infinity, Infinity],
|
||
|
* [9, 10, Infinity, 11, Infinity, 2],
|
||
|
* [Infinity, 15, 11, Infinity, 6, Infinity],
|
||
|
* [Infinity, Infinity, Infinity, 6, Infinity, 9],
|
||
|
* [16, Infinity, 2, Infinity, 9, Infinity]];
|
||
|
* var shortestDist = dijkstra(0, 2, distMatrix); // 9
|
||
|
*/
|
||
|
return function (src, dest, graph) {
|
||
|
var tempDistance = 0;
|
||
|
init(src, graph);
|
||
|
while (current.node !== dest && isFinite(current.distance)) {
|
||
|
for (var i = 0; i < graph.length; i += 1) {
|
||
|
if (current.node !== i && //if it's not the current node
|
||
|
!visited[i] && //and if we haven't visited this node
|
||
|
//and this node is sibling of the current...
|
||
|
Number.isFinite(graph[i][current.node])) {
|
||
|
|
||
|
tempDistance = current.distance + graph[i][current.node];
|
||
|
if (tempDistance < distance[i].distance) {
|
||
|
distance[i].distance = tempDistance;
|
||
|
current.distance = tempDistance;
|
||
|
unvisited.update(current);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
visited[current.node] = true;
|
||
|
current = unvisited.extract();
|
||
|
}
|
||
|
if (distance[dest]) {
|
||
|
return distance[dest].distance;
|
||
|
}
|
||
|
return Infinity;
|
||
|
};
|
||
|
|
||
|
})();
|
||
|
|
||
|
exports.dijkstra = dijkstra;
|
||
|
|
||
|
})(typeof window === 'undefined' ? module.exports : window);
|