UNPKG

tstruct

Version:

Data structures & basic algorithms library

381 lines (380 loc) 15.2 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __values = (this && this.__values) || function(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spread = (this && this.__spread) || function () { for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); return ar; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Graph = void 0; var UnionFind_1 = require("../UnionFind/UnionFind"); var PriorityQueue_1 = require("../Queue/PriorityQueue"); var CompareFunction_1 = require("../CompareFunction"); var Graph = (function () { function Graph() { this._adjacencyList = new Map(); this._hasNegativeWeights = false; } Graph.prototype.add = function (vertex) { if (!this._adjacencyList.has(vertex)) { this._adjacencyList.set(vertex, this.newConnectionPriorityQueue()); } }; Graph.prototype.connect = function (connection) { var e_1, _a; if (!this._adjacencyList.has(connection.from) || !this._adjacencyList.has(connection.to)) { return; } var edges = this._adjacencyList.get(connection.from); try { for (var edges_1 = __values(edges), edges_1_1 = edges_1.next(); !edges_1_1.done; edges_1_1 = edges_1.next()) { var e = edges_1_1.value; if (e.from == connection.from && e.to == connection.to) { return; } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (edges_1_1 && !edges_1_1.done && (_a = edges_1.return)) _a.call(edges_1); } finally { if (e_1) throw e_1.error; } } edges.enqueue(connection); if (connection.weight < 0) { this._hasNegativeWeights = true; } if (connection.bidirectional) { edges.enqueue(__assign(__assign({}, connection), { from: connection.to, to: connection.from })); } }; Graph.prototype.exists = function (node) { return this._adjacencyList.has(node); }; Graph.prototype.connectionExists = function (connection) { var _this = this; if (connection.from == connection.to) return true; var check = function (currentLocation, haveBeenHere) { var e_2, _a; if (haveBeenHere === void 0) { haveBeenHere = []; } if (haveBeenHere.includes(currentLocation)) return false; if (connection.to == currentLocation) { return true; } try { for (var _b = __values(_this._adjacencyList.get(currentLocation)), _c = _b.next(); !_c.done; _c = _b.next()) { var edge = _c.value; if (check(edge.to, __spread(haveBeenHere, [currentLocation]))) { return true; } } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_2) throw e_2.error; } } return false; }; return check(connection.from); }; Graph.prototype.getVertices = function () { var e_3, _a; var result = []; try { for (var _b = __values(this._adjacencyList.keys()), _c = _b.next(); !_c.done; _c = _b.next()) { var e = _c.value; result.push(e); } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_3) throw e_3.error; } } return result; }; Graph.prototype.getEdges = function () { var e_4, _a, e_5, _b; var result = this.newConnectionPriorityQueue(); try { for (var _c = __values(this._adjacencyList.values()), _d = _c.next(); !_d.done; _d = _c.next()) { var edges = _d.value; try { for (var edges_2 = (e_5 = void 0, __values(edges)), edges_2_1 = edges_2.next(); !edges_2_1.done; edges_2_1 = edges_2.next()) { var edge = edges_2_1.value; result.enqueue(edge); } } catch (e_5_1) { e_5 = { error: e_5_1 }; } finally { try { if (edges_2_1 && !edges_2_1.done && (_b = edges_2.return)) _b.call(edges_2); } finally { if (e_5) throw e_5.error; } } } } catch (e_4_1) { e_4 = { error: e_4_1 }; } finally { try { if (_d && !_d.done && (_a = _c.return)) _a.call(_c); } finally { if (e_4) throw e_4.error; } } return result.toArray(); }; Graph.prototype.getEdgesFor = function (vertex) { var e_6, _a; if (!this._adjacencyList.has(vertex)) return []; var result = []; var edges = this._adjacencyList.get(vertex); try { for (var edges_3 = __values(edges), edges_3_1 = edges_3.next(); !edges_3_1.done; edges_3_1 = edges_3.next()) { var edge = edges_3_1.value; result.push(edge); } } catch (e_6_1) { e_6 = { error: e_6_1 }; } finally { try { if (edges_3_1 && !edges_3_1.done && (_a = edges_3.return)) _a.call(edges_3); } finally { if (e_6) throw e_6.error; } } return result; }; Graph.prototype.minimumSpanningTree = function () { var e_7, _a, e_8, _b; var unionFind = new UnionFind_1.UnionFind(); var graph = new Graph(); var nodes = this.getVertices(); try { for (var nodes_1 = __values(nodes), nodes_1_1 = nodes_1.next(); !nodes_1_1.done; nodes_1_1 = nodes_1.next()) { var node = nodes_1_1.value; graph.add(node); unionFind.add(node); } } catch (e_7_1) { e_7 = { error: e_7_1 }; } finally { try { if (nodes_1_1 && !nodes_1_1.done && (_a = nodes_1.return)) _a.call(nodes_1); } finally { if (e_7) throw e_7.error; } } var edges = this.getEdges(); try { for (var edges_4 = __values(edges), edges_4_1 = edges_4.next(); !edges_4_1.done; edges_4_1 = edges_4.next()) { var edge = edges_4_1.value; if (!unionFind.isConnected(edge.from, edge.to)) { graph.connect(edge); unionFind.union(edge.from, edge.to); } } } catch (e_8_1) { e_8 = { error: e_8_1 }; } finally { try { if (edges_4_1 && !edges_4_1.done && (_b = edges_4.return)) _b.call(edges_4); } finally { if (e_8) throw e_8.error; } } if (unionFind.numberOfComponents != 1) { return undefined; } return graph; }; Graph.prototype.shortestPath = function (from, to) { if (this._hasNegativeWeights) { return this.bellmanFord(from, to).path; } else { return this.dijkstra(from, to).path; } }; Graph.prototype.bellmanFord = function (from, to) { var e_9, _a, e_10, _b, e_11, _c; var distances = new Map(); var vertices = this.getVertices(); try { for (var vertices_1 = __values(vertices), vertices_1_1 = vertices_1.next(); !vertices_1_1.done; vertices_1_1 = vertices_1.next()) { var vertex = vertices_1_1.value; distances.set(vertex, { distance: vertex == from ? 0 : Number.MAX_SAFE_INTEGER, }); } } catch (e_9_1) { e_9 = { error: e_9_1 }; } finally { try { if (vertices_1_1 && !vertices_1_1.done && (_a = vertices_1.return)) _a.call(vertices_1); } finally { if (e_9) throw e_9.error; } } var edges = this.getEdges(); for (var i = 0; i < vertices.length; i++) { try { for (var edges_5 = (e_10 = void 0, __values(edges)), edges_5_1 = edges_5.next(); !edges_5_1.done; edges_5_1 = edges_5.next()) { var edge = edges_5_1.value; var newDistance = distances.get(edge.from).distance + edge.weight; if (newDistance < distances.get(edge.to).distance) { distances.set(edge.to, { distance: newDistance, previous: edge.from, }); } } } catch (e_10_1) { e_10 = { error: e_10_1 }; } finally { try { if (edges_5_1 && !edges_5_1.done && (_b = edges_5.return)) _b.call(edges_5); } finally { if (e_10) throw e_10.error; } } } try { for (var edges_6 = __values(edges), edges_6_1 = edges_6.next(); !edges_6_1.done; edges_6_1 = edges_6.next()) { var e = edges_6_1.value; if (distances.get(e.from).distance + (e === null || e === void 0 ? void 0 : e.weight) < distances.get(e.to).distance) { throw "Negative Cycle Exists in Graph"; } } } catch (e_11_1) { e_11 = { error: e_11_1 }; } finally { try { if (edges_6_1 && !edges_6_1.done && (_c = edges_6.return)) _c.call(edges_6); } finally { if (e_11) throw e_11.error; } } var distance = distances.get(to); var path = []; while ((distance === null || distance === void 0 ? void 0 : distance.previous) != undefined) { path.unshift(distance.previous); distance = distances.get(distance.previous); } if (path.length > 0) { path.push(to); } return { distance: distance.distance, path: path, }; }; Graph.prototype.dijkstra = function (from, to) { var e_12, _a, e_13, _b; if (this._hasNegativeWeights) { throw "Dijkstra only works on graph with no negative weights"; } var distances = new Map(); var priorityQueue = new PriorityQueue_1.PriorityQueue(function (e) { return e === null || e === void 0 ? void 0 : e.distance; }, CompareFunction_1.ascendingCompareFunction); var vertices = this.getVertices(); try { for (var vertices_2 = __values(vertices), vertices_2_1 = vertices_2.next(); !vertices_2_1.done; vertices_2_1 = vertices_2.next()) { var vertex = vertices_2_1.value; var distance_1 = { distance: vertex == from ? 0 : Number.MAX_SAFE_INTEGER, vertex: vertex, }; distances.set(vertex, distance_1); priorityQueue.enqueue(distance_1); } } catch (e_12_1) { e_12 = { error: e_12_1 }; } finally { try { if (vertices_2_1 && !vertices_2_1.done && (_a = vertices_2.return)) _a.call(vertices_2); } finally { if (e_12) throw e_12.error; } } while (!priorityQueue.isEmpty) { var distance_2 = priorityQueue.dequeue(); var edges = this.getEdgesFor(distance_2.vertex); try { for (var edges_7 = (e_13 = void 0, __values(edges)), edges_7_1 = edges_7.next(); !edges_7_1.done; edges_7_1 = edges_7.next()) { var e = edges_7_1.value; var newWeight = distances.get(e.from).distance + e.weight; if (newWeight < distances.get(e.to).distance) { var obj = distances.get(e.to); obj.distance = newWeight; obj.previous = e.from; priorityQueue.rearrange(); } } } catch (e_13_1) { e_13 = { error: e_13_1 }; } finally { try { if (edges_7_1 && !edges_7_1.done && (_b = edges_7.return)) _b.call(edges_7); } finally { if (e_13) throw e_13.error; } } } var distance = distances.get(to); var path = []; while ((distance === null || distance === void 0 ? void 0 : distance.previous) != undefined) { path.unshift(distance.previous); distance = distances.get(distance.previous); } if (path.length > 0) { path.push(to); } return { distance: distance.distance, path: path, }; }; Graph.prototype.newConnectionPriorityQueue = function () { return new PriorityQueue_1.PriorityQueue(function (e) { return (e === null || e === void 0 ? void 0 : e.weight) || 0; }, CompareFunction_1.ascendingCompareFunction); }; return Graph; }()); exports.Graph = Graph;