You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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);