Shortest path now uses a heap

Use a heap in dijkstra's algoritm to keep track of the shortest path. Change time from O(v^2) to O(u + v log(v)).

@companje tijdens een college kwam een algoritme aan bod wat ik gebruikt heb in de slicer. Ik kwam er achter dat ik een fout had gemaakt waardoor het algoritme een stuk trager was als zou moeten. Door een binary heap te gebruiken is het algoritme een stuk sneller. Dit algoritme rekent een kortste pad uit en wordt gebruikt in de `comb` functie.
This commit is contained in:
Casper Lamboo 2019-04-04 23:02:01 +02:00
parent 3b440b346a
commit 13ffea4115
3 changed files with 2266 additions and 3729 deletions

5961
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -24,6 +24,7 @@
"@doodle3d/doodle3d-core": "github:doodle3d/doodle3d-core",
"babel-plugin-transform-class-properties": "^6.24.1",
"file-saver": "^1.3.3",
"heap": "^0.2.6",
"lodash": "^4.17.4",
"material-ui": "^0.19.4",
"material-ui-icons": "^1.0.0-beta.17",

View File

@ -1,3 +1,4 @@
import Heap from 'heap';
import { angle, subtract, distanceTo } from './vector2.js';
const graphs = new WeakMap();
@ -147,40 +148,36 @@ function betweenAngles(n, a, b) {
// dijkstra's algorithm
function shortestPath(graph, start, end) {
const traverse = graph.map(() => -1);
traverse[start] = start;
const visited = graph.map(() => false);
const distances = graph.map(() => Infinity);
distances[start] = 0;
const traverse = [];
const queue = [];
for (let i = 0; i < distances.length; i ++) {
queue.push(i);
}
while (queue.length > 0) {
let queueIndex;
let minDistance = Infinity;
for (let index = 0; index < queue.length; index ++) {
const nodeIndex = queue[index];
const distance = distances[nodeIndex];
if (distances[nodeIndex] < minDistance) {
queueIndex = index;
minDistance = distance;
}
}
const heap = new Heap((a, b) => a.distance - b.distance);
heap.push({ nodeIndex: start, distance: 0 });
for (let i = 0; i < graph.length; i ++) {
let nodeIndex;
do { nodeIndex = heap.pop().nodeIndex } while (visited[nodeIndex]);
if (nodeIndex === end) break;
const [nodeIndex] = queue.splice(queueIndex, 1);
const node = graph[nodeIndex];
visited[nodeIndex] = true;
for (let i = 0; i < node.length; i ++) {
const child = node[i];
const distance = distances[nodeIndex] + child.distance;
if (distance < distances[child.to]) {
heap.push({ nodeIndex: child.to, distance });
distances[child.to] = distance;
traverse[child.to] = nodeIndex;
}
}
}
if (!traverse.hasOwnProperty(end)) return null;
if (traverse[end] === -1) return null;
const path = [end];
let nodeIndex = end;