data-structure-typed 0.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.idea/data-structure-typed.iml +12 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/README.md +2 -0
- package/dist/data-structures/binary-tree/aa-tree.js +6 -0
- package/dist/data-structures/binary-tree/avl-tree.js +231 -0
- package/dist/data-structures/binary-tree/b-tree.js +6 -0
- package/dist/data-structures/binary-tree/binary-indexed-tree.js +31 -0
- package/dist/data-structures/binary-tree/binary-tree.js +992 -0
- package/dist/data-structures/binary-tree/bst.js +431 -0
- package/dist/data-structures/binary-tree/index.js +20 -0
- package/dist/data-structures/binary-tree/rb-tree.js +6 -0
- package/dist/data-structures/binary-tree/segment-tree.js +151 -0
- package/dist/data-structures/binary-tree/splay-tree.js +6 -0
- package/dist/data-structures/binary-tree/tree-multiset.js +16 -0
- package/dist/data-structures/binary-tree/two-three-tree.js +6 -0
- package/dist/data-structures/graph/abstract-graph.js +648 -0
- package/dist/data-structures/graph/directed-graph.js +268 -0
- package/dist/data-structures/graph/index.js +19 -0
- package/dist/data-structures/graph/undirected-graph.js +142 -0
- package/dist/data-structures/hash/coordinate-map.js +24 -0
- package/dist/data-structures/hash/coordinate-set.js +21 -0
- package/dist/data-structures/hash/hash-table.js +2 -0
- package/dist/data-structures/hash/index.js +17 -0
- package/dist/data-structures/hash/pair.js +2 -0
- package/dist/data-structures/hash/tree-map.js +2 -0
- package/dist/data-structures/hash/tree-set.js +2 -0
- package/dist/data-structures/heap/heap.js +114 -0
- package/dist/data-structures/heap/index.js +19 -0
- package/dist/data-structures/heap/max-heap.js +22 -0
- package/dist/data-structures/heap/min-heap.js +22 -0
- package/dist/data-structures/index.js +25 -0
- package/dist/data-structures/linked-list/doubly-linked-list.js +259 -0
- package/dist/data-structures/linked-list/index.js +18 -0
- package/dist/data-structures/linked-list/singly-linked-list.js +660 -0
- package/dist/data-structures/linked-list/skip-linked-list.js +2 -0
- package/dist/data-structures/matrix/index.js +19 -0
- package/dist/data-structures/matrix/matrix.js +14 -0
- package/dist/data-structures/matrix/matrix2d.js +119 -0
- package/dist/data-structures/matrix/navigator.js +78 -0
- package/dist/data-structures/matrix/vector2d.js +161 -0
- package/dist/data-structures/priority-queue/index.js +19 -0
- package/dist/data-structures/priority-queue/max-priority-queue.js +15 -0
- package/dist/data-structures/priority-queue/min-priority-queue.js +15 -0
- package/dist/data-structures/priority-queue/priority-queue.js +174 -0
- package/dist/data-structures/queue/deque.js +132 -0
- package/dist/data-structures/queue/index.js +17 -0
- package/dist/data-structures/queue/queue.js +113 -0
- package/dist/data-structures/stack/index.js +17 -0
- package/dist/data-structures/stack/stack.js +97 -0
- package/dist/data-structures/trampoline.js +52 -0
- package/dist/data-structures/trie/index.js +17 -0
- package/dist/data-structures/trie/trie.js +141 -0
- package/dist/index.js +17 -0
- package/dist/types/data-structures/binary-tree/aa-tree.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +21 -0
- package/dist/types/data-structures/binary-tree/b-tree.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +8 -0
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +140 -0
- package/dist/types/data-structures/binary-tree/bst.d.ts +32 -0
- package/dist/types/data-structures/binary-tree/index.d.ts +4 -0
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +33 -0
- package/dist/types/data-structures/binary-tree/splay-tree.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/tree-multiset.d.ts +11 -0
- package/dist/types/data-structures/binary-tree/two-three-tree.d.ts +2 -0
- package/dist/types/data-structures/graph/abstract-graph.d.ts +126 -0
- package/dist/types/data-structures/graph/directed-graph.d.ts +51 -0
- package/dist/types/data-structures/graph/index.d.ts +3 -0
- package/dist/types/data-structures/graph/undirected-graph.d.ts +24 -0
- package/dist/types/data-structures/hash/coordinate-map.d.ts +8 -0
- package/dist/types/data-structures/hash/coordinate-set.d.ts +7 -0
- package/dist/types/data-structures/hash/hash-table.d.ts +1 -0
- package/dist/types/data-structures/hash/index.d.ts +1 -0
- package/dist/types/data-structures/hash/pair.d.ts +1 -0
- package/dist/types/data-structures/hash/tree-map.d.ts +1 -0
- package/dist/types/data-structures/hash/tree-set.d.ts +1 -0
- package/dist/types/data-structures/heap/heap.d.ts +72 -0
- package/dist/types/data-structures/heap/index.d.ts +3 -0
- package/dist/types/data-structures/heap/max-heap.d.ts +14 -0
- package/dist/types/data-structures/heap/min-heap.d.ts +14 -0
- package/dist/types/data-structures/index.d.ts +9 -0
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +59 -0
- package/dist/types/data-structures/linked-list/index.d.ts +2 -0
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +358 -0
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +1 -0
- package/dist/types/data-structures/matrix/index.d.ts +3 -0
- package/dist/types/data-structures/matrix/matrix.d.ts +9 -0
- package/dist/types/data-structures/matrix/matrix2d.d.ts +25 -0
- package/dist/types/data-structures/matrix/navigator.d.ts +31 -0
- package/dist/types/data-structures/matrix/vector2d.d.ts +74 -0
- package/dist/types/data-structures/priority-queue/index.d.ts +3 -0
- package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +4 -0
- package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +4 -0
- package/dist/types/data-structures/priority-queue/priority-queue.d.ts +36 -0
- package/dist/types/data-structures/queue/deque.d.ts +37 -0
- package/dist/types/data-structures/queue/index.d.ts +1 -0
- package/dist/types/data-structures/queue/queue.d.ts +76 -0
- package/dist/types/data-structures/stack/index.d.ts +1 -0
- package/dist/types/data-structures/stack/stack.d.ts +69 -0
- package/dist/types/data-structures/trampoline.d.ts +25 -0
- package/dist/types/data-structures/trie/index.d.ts +1 -0
- package/dist/types/data-structures/trie/trie.d.ts +28 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +17 -0
- package/dist/types/types/index.d.ts +1 -0
- package/dist/types/types/utils.d.ts +46 -0
- package/dist/types/utils.d.ts +122 -0
- package/dist/types/utils.js +53 -0
- package/dist/utils.js +569 -0
- package/package.json +75 -0
- package/src/data-structures/binary-tree/aa-tree.ts +3 -0
- package/src/data-structures/binary-tree/avl-tree.ts +232 -0
- package/src/data-structures/binary-tree/b-tree.ts +3 -0
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +33 -0
- package/src/data-structures/binary-tree/binary-tree.ts +1088 -0
- package/src/data-structures/binary-tree/bst.ts +404 -0
- package/src/data-structures/binary-tree/index.ts +4 -0
- package/src/data-structures/binary-tree/rb-tree.ts +3 -0
- package/src/data-structures/binary-tree/segment-tree.ts +164 -0
- package/src/data-structures/binary-tree/splay-tree.ts +3 -0
- package/src/data-structures/binary-tree/tree-multiset.ts +21 -0
- package/src/data-structures/binary-tree/two-three-tree.ts +3 -0
- package/src/data-structures/graph/abstract-graph.ts +789 -0
- package/src/data-structures/graph/directed-graph.ts +322 -0
- package/src/data-structures/graph/index.ts +3 -0
- package/src/data-structures/graph/undirected-graph.ts +154 -0
- package/src/data-structures/hash/coordinate-map.ts +24 -0
- package/src/data-structures/hash/coordinate-set.ts +20 -0
- package/src/data-structures/hash/hash-table.ts +1 -0
- package/src/data-structures/hash/index.ts +1 -0
- package/src/data-structures/hash/pair.ts +1 -0
- package/src/data-structures/hash/tree-map.ts +1 -0
- package/src/data-structures/hash/tree-set.ts +1 -0
- package/src/data-structures/heap/heap.ts +136 -0
- package/src/data-structures/heap/index.ts +3 -0
- package/src/data-structures/heap/max-heap.ts +22 -0
- package/src/data-structures/heap/min-heap.ts +24 -0
- package/src/data-structures/index.ts +10 -0
- package/src/data-structures/linked-list/doubly-linked-list.ts +258 -0
- package/src/data-structures/linked-list/index.ts +2 -0
- package/src/data-structures/linked-list/singly-linked-list.ts +750 -0
- package/src/data-structures/linked-list/skip-linked-list.ts +1 -0
- package/src/data-structures/matrix/index.ts +3 -0
- package/src/data-structures/matrix/matrix.ts +13 -0
- package/src/data-structures/matrix/matrix2d.ts +125 -0
- package/src/data-structures/matrix/navigator.ts +99 -0
- package/src/data-structures/matrix/vector2d.ts +189 -0
- package/src/data-structures/priority-queue/index.ts +3 -0
- package/src/data-structures/priority-queue/max-priority-queue.ts +12 -0
- package/src/data-structures/priority-queue/min-priority-queue.ts +12 -0
- package/src/data-structures/priority-queue/priority-queue.ts +208 -0
- package/src/data-structures/queue/deque.ts +139 -0
- package/src/data-structures/queue/index.ts +1 -0
- package/src/data-structures/queue/queue.ts +123 -0
- package/src/data-structures/stack/index.ts +1 -0
- package/src/data-structures/stack/stack.ts +104 -0
- package/src/data-structures/trampoline.ts +91 -0
- package/src/data-structures/trie/index.ts +1 -0
- package/src/data-structures/trie/trie.ts +153 -0
- package/src/index.ts +1 -0
- package/src/types/index.ts +1 -0
- package/src/types/patches/index.d.ts +0 -0
- package/src/types/utils.ts +158 -0
- package/src/utils.ts +605 -0
- package/tsconfig.json +52 -0
|
@@ -0,0 +1,648 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AbstractGraph = exports.AbstractEdge = exports.AbstractVertex = void 0;
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
const priority_queue_1 = require("../priority-queue");
|
|
6
|
+
class AbstractVertex {
|
|
7
|
+
get id() {
|
|
8
|
+
return this._id;
|
|
9
|
+
}
|
|
10
|
+
set id(v) {
|
|
11
|
+
this._id = v;
|
|
12
|
+
}
|
|
13
|
+
constructor(id) {
|
|
14
|
+
this._id = id;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.AbstractVertex = AbstractVertex;
|
|
18
|
+
class AbstractEdge {
|
|
19
|
+
get weight() {
|
|
20
|
+
return this._weight;
|
|
21
|
+
}
|
|
22
|
+
set weight(v) {
|
|
23
|
+
this._weight = v;
|
|
24
|
+
}
|
|
25
|
+
get hashCode() {
|
|
26
|
+
return this._hashCode;
|
|
27
|
+
}
|
|
28
|
+
set hashCode(v) {
|
|
29
|
+
this._hashCode = v;
|
|
30
|
+
}
|
|
31
|
+
constructor(weight) {
|
|
32
|
+
if (weight === undefined)
|
|
33
|
+
weight = AbstractEdge.DEFAULT_EDGE_WEIGHT;
|
|
34
|
+
this._weight = weight;
|
|
35
|
+
this._hashCode = (0, utils_1.uuidV4)();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.AbstractEdge = AbstractEdge;
|
|
39
|
+
AbstractEdge.DEFAULT_EDGE_WEIGHT = 1;
|
|
40
|
+
// Connected Component === Largest Connected Sub-Graph
|
|
41
|
+
class AbstractGraph {
|
|
42
|
+
constructor() {
|
|
43
|
+
this._vertices = new Map();
|
|
44
|
+
// unionFind() {
|
|
45
|
+
// }
|
|
46
|
+
/**--- end find cycles --- */
|
|
47
|
+
// Minimum Spanning Tree
|
|
48
|
+
}
|
|
49
|
+
getVertex(vertexOrId) {
|
|
50
|
+
const vertexId = this.getVertexId(vertexOrId);
|
|
51
|
+
return this._vertices.get(vertexId) || null;
|
|
52
|
+
}
|
|
53
|
+
getVertexId(vertexOrId) {
|
|
54
|
+
return vertexOrId instanceof AbstractVertex ? vertexOrId.id : vertexOrId;
|
|
55
|
+
}
|
|
56
|
+
containsVertex(vertexOrId) {
|
|
57
|
+
return this._vertices.has(this.getVertexId(vertexOrId));
|
|
58
|
+
}
|
|
59
|
+
vertexSet() {
|
|
60
|
+
return this._vertices;
|
|
61
|
+
}
|
|
62
|
+
addVertex(newVertex) {
|
|
63
|
+
if (this.containsVertex(newVertex)) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
this._vertices.set(newVertex.id, newVertex);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
removeVertex(vertexOrId) {
|
|
70
|
+
const vertexId = this.getVertexId(vertexOrId);
|
|
71
|
+
return this._vertices.delete(vertexId);
|
|
72
|
+
}
|
|
73
|
+
removeAllVertices(vertices) {
|
|
74
|
+
const removed = [];
|
|
75
|
+
for (const v of vertices) {
|
|
76
|
+
removed.push(this.removeVertex(v));
|
|
77
|
+
}
|
|
78
|
+
return removed.length > 0;
|
|
79
|
+
}
|
|
80
|
+
containsEdge(v1, v2) {
|
|
81
|
+
const edge = this.getEdge(v1, v2);
|
|
82
|
+
return !!edge;
|
|
83
|
+
}
|
|
84
|
+
setEdgeWeight(srcOrId, destOrId, weight) {
|
|
85
|
+
const edge = this.getEdge(srcOrId, destOrId);
|
|
86
|
+
if (edge) {
|
|
87
|
+
edge.weight = weight;
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
getAllPathsBetween(v1, v2) {
|
|
95
|
+
const paths = [];
|
|
96
|
+
const vertex1 = this.getVertex(v1);
|
|
97
|
+
const vertex2 = this.getVertex(v2);
|
|
98
|
+
if (!(vertex1 && vertex2)) {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
const dfs = (cur, dest, visiting, path) => {
|
|
102
|
+
visiting.set(cur, true);
|
|
103
|
+
if (cur === dest) {
|
|
104
|
+
paths.push([vertex1, ...path]);
|
|
105
|
+
}
|
|
106
|
+
const neighbors = this.getNeighbors(cur);
|
|
107
|
+
for (const neighbor of neighbors) {
|
|
108
|
+
if (!visiting.get(neighbor)) {
|
|
109
|
+
path.push(neighbor);
|
|
110
|
+
dfs(neighbor, dest, visiting, path);
|
|
111
|
+
(0, utils_1.arrayRemove)(path, vertex => vertex === neighbor);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
visiting.set(cur, false);
|
|
115
|
+
};
|
|
116
|
+
dfs(vertex1, vertex2, new Map(), []);
|
|
117
|
+
return paths;
|
|
118
|
+
}
|
|
119
|
+
getPathSumWeight(path) {
|
|
120
|
+
var _a;
|
|
121
|
+
let sum = 0;
|
|
122
|
+
for (let i = 0; i < path.length; i++) {
|
|
123
|
+
sum += ((_a = this.getEdge(path[i], path[i + 1])) === null || _a === void 0 ? void 0 : _a.weight) || 0;
|
|
124
|
+
}
|
|
125
|
+
return sum;
|
|
126
|
+
}
|
|
127
|
+
getMinCostBetween(v1, v2, isWeight) {
|
|
128
|
+
if (isWeight === undefined)
|
|
129
|
+
isWeight = false;
|
|
130
|
+
if (isWeight) {
|
|
131
|
+
const allPaths = this.getAllPathsBetween(v1, v2);
|
|
132
|
+
let min = Infinity;
|
|
133
|
+
for (const path of allPaths) {
|
|
134
|
+
min = Math.min(this.getPathSumWeight(path), min);
|
|
135
|
+
}
|
|
136
|
+
return min;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
// BFS
|
|
140
|
+
const vertex2 = this.getVertex(v2);
|
|
141
|
+
const vertex1 = this.getVertex(v1);
|
|
142
|
+
if (!(vertex1 && vertex2)) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
const visited = new Map();
|
|
146
|
+
const queue = [vertex1];
|
|
147
|
+
visited.set(vertex1, true);
|
|
148
|
+
let cost = 0;
|
|
149
|
+
while (queue.length > 0) {
|
|
150
|
+
for (let i = 0; i < queue.length; i++) {
|
|
151
|
+
const cur = queue.shift();
|
|
152
|
+
if (cur === vertex2) {
|
|
153
|
+
return cost;
|
|
154
|
+
}
|
|
155
|
+
// TODO consider optimizing to AbstractGraph
|
|
156
|
+
if (cur !== undefined) {
|
|
157
|
+
const neighbors = this.getNeighbors(cur);
|
|
158
|
+
for (const neighbor of neighbors) {
|
|
159
|
+
if (!visited.has(neighbor)) {
|
|
160
|
+
visited.set(neighbor, true);
|
|
161
|
+
queue.push(neighbor);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
cost++;
|
|
167
|
+
}
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
getMinPathBetween(v1, v2, isWeight) {
|
|
172
|
+
if (isWeight === undefined)
|
|
173
|
+
isWeight = false;
|
|
174
|
+
if (isWeight) {
|
|
175
|
+
const allPaths = this.getAllPathsBetween(v1, v2);
|
|
176
|
+
let min = Infinity;
|
|
177
|
+
let minIndex = -1;
|
|
178
|
+
let index = 0;
|
|
179
|
+
for (const path of allPaths) {
|
|
180
|
+
const pathSumWeight = this.getPathSumWeight(path);
|
|
181
|
+
if (pathSumWeight < min) {
|
|
182
|
+
min = pathSumWeight;
|
|
183
|
+
minIndex = index;
|
|
184
|
+
}
|
|
185
|
+
index++;
|
|
186
|
+
}
|
|
187
|
+
return allPaths[minIndex] || null;
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
// BFS
|
|
191
|
+
let minPath = [];
|
|
192
|
+
const vertex1 = this.getVertex(v1);
|
|
193
|
+
const vertex2 = this.getVertex(v2);
|
|
194
|
+
if (!(vertex1 && vertex2)) {
|
|
195
|
+
return [];
|
|
196
|
+
}
|
|
197
|
+
const dfs = (cur, dest, visiting, path) => {
|
|
198
|
+
visiting.set(cur, true);
|
|
199
|
+
if (cur === dest) {
|
|
200
|
+
minPath = [vertex1, ...path];
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const neighbors = this.getNeighbors(cur);
|
|
204
|
+
for (const neighbor of neighbors) {
|
|
205
|
+
if (!visiting.get(neighbor)) {
|
|
206
|
+
path.push(neighbor);
|
|
207
|
+
dfs(neighbor, dest, visiting, path);
|
|
208
|
+
(0, utils_1.arrayRemove)(path, vertex => vertex === neighbor);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
visiting.set(cur, false);
|
|
212
|
+
};
|
|
213
|
+
dfs(vertex1, vertex2, new Map(), []);
|
|
214
|
+
return minPath;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Dijkstra algorithm time: O(VE) space: O(V + E)
|
|
219
|
+
* @param src
|
|
220
|
+
* @param dest
|
|
221
|
+
* @param getMinDist
|
|
222
|
+
* @param genPaths
|
|
223
|
+
*/
|
|
224
|
+
dijkstraWithoutHeap(src, dest, getMinDist, genPaths) {
|
|
225
|
+
if (getMinDist === undefined)
|
|
226
|
+
getMinDist = false;
|
|
227
|
+
if (genPaths === undefined)
|
|
228
|
+
genPaths = false;
|
|
229
|
+
if (dest === undefined)
|
|
230
|
+
dest = null;
|
|
231
|
+
let minDist = Infinity;
|
|
232
|
+
let minDest = null;
|
|
233
|
+
let minPath = [];
|
|
234
|
+
const paths = [];
|
|
235
|
+
const vertices = this._vertices;
|
|
236
|
+
const distMap = new Map();
|
|
237
|
+
const seen = new Set();
|
|
238
|
+
const preMap = new Map(); // predecessor
|
|
239
|
+
const srcVertex = this.getVertex(src);
|
|
240
|
+
const destVertex = dest ? this.getVertex(dest) : null;
|
|
241
|
+
if (!srcVertex) {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
for (const vertex of vertices) {
|
|
245
|
+
distMap.set(vertex[1], Infinity);
|
|
246
|
+
}
|
|
247
|
+
distMap.set(srcVertex, 0);
|
|
248
|
+
preMap.set(srcVertex, null);
|
|
249
|
+
const getMinOfNoSeen = () => {
|
|
250
|
+
let min = Infinity;
|
|
251
|
+
let minV = null;
|
|
252
|
+
for (const [key, val] of distMap) {
|
|
253
|
+
if (!seen.has(key)) {
|
|
254
|
+
if (val < min) {
|
|
255
|
+
min = val;
|
|
256
|
+
minV = key;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return minV;
|
|
261
|
+
};
|
|
262
|
+
const getPaths = (minV) => {
|
|
263
|
+
for (const vertex of vertices) {
|
|
264
|
+
const path = [vertex[1]];
|
|
265
|
+
let parent = preMap.get(vertex[1]);
|
|
266
|
+
while (parent) {
|
|
267
|
+
path.push(parent);
|
|
268
|
+
parent = preMap.get(parent);
|
|
269
|
+
}
|
|
270
|
+
const reversed = path.reverse();
|
|
271
|
+
if (vertex[1] === minV)
|
|
272
|
+
minPath = reversed;
|
|
273
|
+
paths.push(reversed);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
for (let i = 1; i < vertices.size; i++) {
|
|
277
|
+
const cur = getMinOfNoSeen();
|
|
278
|
+
if (cur) {
|
|
279
|
+
seen.add(cur);
|
|
280
|
+
if (destVertex && destVertex === cur) {
|
|
281
|
+
if (getMinDist) {
|
|
282
|
+
minDist = distMap.get(destVertex) || Infinity;
|
|
283
|
+
}
|
|
284
|
+
if (genPaths) {
|
|
285
|
+
getPaths(destVertex);
|
|
286
|
+
}
|
|
287
|
+
return { distMap, preMap, seen, paths, minDist, minPath };
|
|
288
|
+
}
|
|
289
|
+
const neighbors = this.getNeighbors(cur);
|
|
290
|
+
for (const neighbor of neighbors) {
|
|
291
|
+
if (!seen.has(neighbor)) {
|
|
292
|
+
const edge = this.getEdge(cur, neighbor);
|
|
293
|
+
if (edge) {
|
|
294
|
+
const curFromMap = distMap.get(cur);
|
|
295
|
+
const neighborFromMap = distMap.get(neighbor);
|
|
296
|
+
// TODO after no-non-null-assertion not ensure the logic
|
|
297
|
+
if (curFromMap !== undefined && neighborFromMap !== undefined) {
|
|
298
|
+
if (edge.weight + curFromMap < neighborFromMap) {
|
|
299
|
+
distMap.set(neighbor, edge.weight + curFromMap);
|
|
300
|
+
preMap.set(neighbor, cur);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
getMinDist && distMap.forEach((d, v) => {
|
|
309
|
+
if (v !== srcVertex) {
|
|
310
|
+
if (d < minDist) {
|
|
311
|
+
minDist = d;
|
|
312
|
+
if (genPaths)
|
|
313
|
+
minDest = v;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
genPaths && getPaths(minDest);
|
|
318
|
+
return { distMap, preMap, seen, paths, minDist, minPath };
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Dijkstra algorithm time: O(logVE) space: O(V + E)
|
|
322
|
+
* @param src
|
|
323
|
+
* @param dest
|
|
324
|
+
* @param getMinDist
|
|
325
|
+
* @param genPaths
|
|
326
|
+
*/
|
|
327
|
+
dijkstra(src, dest, getMinDist, genPaths) {
|
|
328
|
+
var _a;
|
|
329
|
+
if (getMinDist === undefined)
|
|
330
|
+
getMinDist = false;
|
|
331
|
+
if (genPaths === undefined)
|
|
332
|
+
genPaths = false;
|
|
333
|
+
if (dest === undefined)
|
|
334
|
+
dest = null;
|
|
335
|
+
let minDist = Infinity;
|
|
336
|
+
let minDest = null;
|
|
337
|
+
let minPath = [];
|
|
338
|
+
const paths = [];
|
|
339
|
+
const vertices = this._vertices;
|
|
340
|
+
const distMap = new Map();
|
|
341
|
+
const seen = new Set();
|
|
342
|
+
const preMap = new Map(); // predecessor
|
|
343
|
+
const srcVertex = this.getVertex(src);
|
|
344
|
+
const destVertex = dest ? this.getVertex(dest) : null;
|
|
345
|
+
if (!srcVertex) {
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
for (const vertex of vertices) {
|
|
349
|
+
distMap.set(vertex[1], Infinity);
|
|
350
|
+
}
|
|
351
|
+
const heap = new priority_queue_1.PriorityQueue({ comparator: (a, b) => a.id - b.id });
|
|
352
|
+
heap.offer({ id: 0, val: srcVertex });
|
|
353
|
+
distMap.set(srcVertex, 0);
|
|
354
|
+
preMap.set(srcVertex, null);
|
|
355
|
+
const getPaths = (minV) => {
|
|
356
|
+
for (const vertex of vertices) {
|
|
357
|
+
const path = [vertex[1]];
|
|
358
|
+
let parent = preMap.get(vertex[1]);
|
|
359
|
+
while (parent) {
|
|
360
|
+
path.push(parent);
|
|
361
|
+
parent = preMap.get(parent);
|
|
362
|
+
}
|
|
363
|
+
const reversed = path.reverse();
|
|
364
|
+
if (vertex[1] === minV)
|
|
365
|
+
minPath = reversed;
|
|
366
|
+
paths.push(reversed);
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
while (heap.size > 0) {
|
|
370
|
+
const curHeapNode = heap.poll();
|
|
371
|
+
const dist = curHeapNode === null || curHeapNode === void 0 ? void 0 : curHeapNode.id;
|
|
372
|
+
const cur = curHeapNode === null || curHeapNode === void 0 ? void 0 : curHeapNode.val;
|
|
373
|
+
if (dist !== undefined) {
|
|
374
|
+
if (cur) {
|
|
375
|
+
seen.add(cur);
|
|
376
|
+
if (destVertex && destVertex === cur) {
|
|
377
|
+
if (getMinDist) {
|
|
378
|
+
minDist = distMap.get(destVertex) || Infinity;
|
|
379
|
+
}
|
|
380
|
+
if (genPaths) {
|
|
381
|
+
getPaths(destVertex);
|
|
382
|
+
}
|
|
383
|
+
return { distMap, preMap, seen, paths, minDist, minPath };
|
|
384
|
+
}
|
|
385
|
+
const neighbors = this.getNeighbors(cur);
|
|
386
|
+
for (const neighbor of neighbors) {
|
|
387
|
+
if (!seen.has(neighbor)) {
|
|
388
|
+
const weight = (_a = this.getEdge(cur, neighbor)) === null || _a === void 0 ? void 0 : _a.weight;
|
|
389
|
+
if (typeof weight === 'number') {
|
|
390
|
+
const distSrcToNeighbor = distMap.get(neighbor);
|
|
391
|
+
if (distSrcToNeighbor) {
|
|
392
|
+
if (dist + weight < distSrcToNeighbor) {
|
|
393
|
+
heap.offer({ id: dist + weight, val: neighbor });
|
|
394
|
+
preMap.set(neighbor, cur);
|
|
395
|
+
distMap.set(neighbor, dist + weight);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
if (getMinDist) {
|
|
405
|
+
distMap.forEach((d, v) => {
|
|
406
|
+
if (v !== srcVertex) {
|
|
407
|
+
if (d < minDist) {
|
|
408
|
+
minDist = d;
|
|
409
|
+
if (genPaths)
|
|
410
|
+
minDest = v;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
if (genPaths) {
|
|
416
|
+
getPaths(minDest);
|
|
417
|
+
}
|
|
418
|
+
return { distMap, preMap, seen, paths, minDist, minPath };
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* BellmanFord time:O(VE) space:O(V)
|
|
422
|
+
* one to rest pairs
|
|
423
|
+
* @param src
|
|
424
|
+
* @param scanNegativeCycle
|
|
425
|
+
* @param getMin
|
|
426
|
+
* @param genPath
|
|
427
|
+
*/
|
|
428
|
+
bellmanFord(src, scanNegativeCycle, getMin, genPath) {
|
|
429
|
+
if (getMin === undefined)
|
|
430
|
+
getMin = false;
|
|
431
|
+
if (genPath === undefined)
|
|
432
|
+
genPath = false;
|
|
433
|
+
const srcVertex = this.getVertex(src);
|
|
434
|
+
const paths = [];
|
|
435
|
+
const distMap = new Map();
|
|
436
|
+
const preMap = new Map(); // predecessor
|
|
437
|
+
let min = Infinity;
|
|
438
|
+
let minPath = [];
|
|
439
|
+
// TODO
|
|
440
|
+
let hasNegativeCycle = undefined;
|
|
441
|
+
if (scanNegativeCycle)
|
|
442
|
+
hasNegativeCycle = false;
|
|
443
|
+
if (!srcVertex)
|
|
444
|
+
return { hasNegativeCycle, distMap, preMap, paths, min, minPath };
|
|
445
|
+
const vertices = this._vertices;
|
|
446
|
+
const numOfVertices = vertices.size;
|
|
447
|
+
const edges = this.edgeSet();
|
|
448
|
+
const numOfEdges = edges.length;
|
|
449
|
+
this._vertices.forEach(vertex => {
|
|
450
|
+
distMap.set(vertex, Infinity);
|
|
451
|
+
});
|
|
452
|
+
distMap.set(srcVertex, 0);
|
|
453
|
+
for (let i = 1; i < numOfVertices; ++i) {
|
|
454
|
+
for (let j = 0; j < numOfEdges; ++j) {
|
|
455
|
+
const ends = this.getEndsOfEdge(edges[j]);
|
|
456
|
+
if (ends) {
|
|
457
|
+
const [s, d] = ends;
|
|
458
|
+
const weight = edges[j].weight;
|
|
459
|
+
const sWeight = distMap.get(s);
|
|
460
|
+
const dWeight = distMap.get(d);
|
|
461
|
+
if (sWeight !== undefined && dWeight !== undefined) {
|
|
462
|
+
if (distMap.get(s) !== Infinity && sWeight + weight < dWeight) {
|
|
463
|
+
distMap.set(d, sWeight + weight);
|
|
464
|
+
genPath && preMap.set(d, s);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
let minDest = null;
|
|
471
|
+
if (getMin) {
|
|
472
|
+
distMap.forEach((d, v) => {
|
|
473
|
+
if (v !== srcVertex) {
|
|
474
|
+
if (d < min) {
|
|
475
|
+
min = d;
|
|
476
|
+
if (genPath)
|
|
477
|
+
minDest = v;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
if (genPath) {
|
|
483
|
+
for (const vertex of vertices) {
|
|
484
|
+
const path = [vertex[1]];
|
|
485
|
+
let parent = preMap.get(vertex[1]);
|
|
486
|
+
while (parent !== undefined) {
|
|
487
|
+
path.push(parent);
|
|
488
|
+
parent = preMap.get(parent);
|
|
489
|
+
}
|
|
490
|
+
const reversed = path.reverse();
|
|
491
|
+
if (vertex[1] === minDest)
|
|
492
|
+
minPath = reversed;
|
|
493
|
+
paths.push(reversed);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
for (let j = 0; j < numOfEdges; ++j) {
|
|
497
|
+
const ends = this.getEndsOfEdge(edges[j]);
|
|
498
|
+
if (ends) {
|
|
499
|
+
const [s] = ends;
|
|
500
|
+
const weight = edges[j].weight;
|
|
501
|
+
const sWeight = distMap.get(s);
|
|
502
|
+
if (sWeight) {
|
|
503
|
+
if (sWeight !== Infinity && sWeight + weight < sWeight)
|
|
504
|
+
hasNegativeCycle = true;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
return { hasNegativeCycle, distMap, preMap, paths, min, minPath };
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Floyd algorithm time: O(V^3) space: O(V^2), not support graph with negative weight cycle
|
|
512
|
+
* all pairs
|
|
513
|
+
*/
|
|
514
|
+
floyd() {
|
|
515
|
+
var _a;
|
|
516
|
+
const idAndVertices = [...this._vertices];
|
|
517
|
+
const n = idAndVertices.length;
|
|
518
|
+
const costs = [];
|
|
519
|
+
const predecessor = [];
|
|
520
|
+
// successors
|
|
521
|
+
for (let i = 0; i < n; i++) {
|
|
522
|
+
costs[i] = [];
|
|
523
|
+
predecessor[i] = [];
|
|
524
|
+
for (let j = 0; j < n; j++) {
|
|
525
|
+
predecessor[i][j] = null;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
for (let i = 0; i < n; i++) {
|
|
529
|
+
for (let j = 0; j < n; j++) {
|
|
530
|
+
costs[i][j] = ((_a = this.getEdge(idAndVertices[i][1], idAndVertices[j][1])) === null || _a === void 0 ? void 0 : _a.weight) || Infinity;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
for (let k = 0; k < n; k++) {
|
|
534
|
+
for (let i = 0; i < n; i++) {
|
|
535
|
+
for (let j = 0; j < n; j++) {
|
|
536
|
+
if (costs[i][j] > costs[i][k] + costs[k][j]) {
|
|
537
|
+
costs[i][j] = costs[i][k] + costs[k][j];
|
|
538
|
+
predecessor[i][j] = idAndVertices[k][1];
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
return { costs, predecessor };
|
|
544
|
+
}
|
|
545
|
+
/**--- start find cycles --- */
|
|
546
|
+
/**
|
|
547
|
+
* Tarjan is an algorithm based on DFS,which is used to solve the connectivity problem of graphs.
|
|
548
|
+
* Tarjan can find cycles in directed or undirected graph
|
|
549
|
+
* Tarjan can find the articulation points and bridges(critical edges) of undirected graphs in linear time,
|
|
550
|
+
* Tarjan solve the bi-connected components of undirected graphs;
|
|
551
|
+
* Tarjan can find the SSC(strongly connected components), articulation points, and bridges of directed graphs.
|
|
552
|
+
*/
|
|
553
|
+
tarjan(needArticulationPoints, needBridges, needSCCs, needCycles) {
|
|
554
|
+
// !! in undirected graph we will not let child visit parent when DFS
|
|
555
|
+
// !! articulation point(in DFS search tree not in graph): (cur !== root && cur.has(child)) && (low(child) >= dfn(cur)) || (cur === root && cur.children() >= 2)
|
|
556
|
+
// !! bridge: low(child) > dfn(cur)
|
|
557
|
+
const defaultConfig = false;
|
|
558
|
+
if (needArticulationPoints === undefined)
|
|
559
|
+
needArticulationPoints = defaultConfig;
|
|
560
|
+
if (needBridges === undefined)
|
|
561
|
+
needBridges = defaultConfig;
|
|
562
|
+
if (needSCCs === undefined)
|
|
563
|
+
needSCCs = defaultConfig;
|
|
564
|
+
if (needCycles === undefined)
|
|
565
|
+
needCycles = defaultConfig;
|
|
566
|
+
const dfnMap = new Map();
|
|
567
|
+
const lowMap = new Map();
|
|
568
|
+
const vertices = this._vertices;
|
|
569
|
+
vertices.forEach(v => {
|
|
570
|
+
dfnMap.set(v, -1);
|
|
571
|
+
lowMap.set(v, Infinity);
|
|
572
|
+
});
|
|
573
|
+
const [root] = vertices.values();
|
|
574
|
+
const articulationPoints = [];
|
|
575
|
+
const bridges = [];
|
|
576
|
+
let dfn = 0;
|
|
577
|
+
const dfs = (cur, parent) => {
|
|
578
|
+
dfn++;
|
|
579
|
+
dfnMap.set(cur, dfn);
|
|
580
|
+
lowMap.set(cur, dfn);
|
|
581
|
+
const neighbors = this.getNeighbors(cur);
|
|
582
|
+
let childCount = 0; // child in DFS tree not child in graph
|
|
583
|
+
for (const neighbor of neighbors) {
|
|
584
|
+
if (neighbor !== parent) {
|
|
585
|
+
if (dfnMap.get(neighbor) === -1) {
|
|
586
|
+
childCount++;
|
|
587
|
+
dfs(neighbor, cur);
|
|
588
|
+
}
|
|
589
|
+
const childLow = lowMap.get(neighbor);
|
|
590
|
+
const curLow = lowMap.get(cur);
|
|
591
|
+
// TODO after no-non-null-assertion not ensure the logic
|
|
592
|
+
if (curLow !== undefined && childLow !== undefined) {
|
|
593
|
+
lowMap.set(cur, Math.min(curLow, childLow));
|
|
594
|
+
}
|
|
595
|
+
const curFromMap = dfnMap.get(cur);
|
|
596
|
+
if (childLow !== undefined && curFromMap !== undefined) {
|
|
597
|
+
if (needArticulationPoints) {
|
|
598
|
+
if ((cur === root && childCount >= 2) || ((cur !== root) && (childLow >= curFromMap))) {
|
|
599
|
+
// todo not ensure the logic if (cur === root && childCount >= 2 || ((cur !== root) && (childLow >= curFromMap))) {
|
|
600
|
+
articulationPoints.push(cur);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
if (needBridges) {
|
|
604
|
+
if (childLow > curFromMap) {
|
|
605
|
+
const edgeCurToNeighbor = this.getEdge(cur, neighbor);
|
|
606
|
+
if (edgeCurToNeighbor) {
|
|
607
|
+
bridges.push(edgeCurToNeighbor);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
dfs(root, null);
|
|
616
|
+
let SCCs = new Map();
|
|
617
|
+
const getSCCs = () => {
|
|
618
|
+
const SCCs = new Map();
|
|
619
|
+
lowMap.forEach((low, vertex) => {
|
|
620
|
+
var _a;
|
|
621
|
+
if (!SCCs.has(low)) {
|
|
622
|
+
SCCs.set(low, [vertex]);
|
|
623
|
+
}
|
|
624
|
+
else {
|
|
625
|
+
(_a = SCCs.get(low)) === null || _a === void 0 ? void 0 : _a.push(vertex);
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
return SCCs;
|
|
629
|
+
};
|
|
630
|
+
if (needSCCs) {
|
|
631
|
+
SCCs = getSCCs();
|
|
632
|
+
}
|
|
633
|
+
const cycles = new Map();
|
|
634
|
+
if (needCycles) {
|
|
635
|
+
let SCCs = new Map();
|
|
636
|
+
if (SCCs.size < 1) {
|
|
637
|
+
SCCs = getSCCs();
|
|
638
|
+
}
|
|
639
|
+
SCCs.forEach((SCC, low) => {
|
|
640
|
+
if (SCC.length > 1) {
|
|
641
|
+
cycles.set(low, SCC);
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
return { dfnMap, lowMap, bridges, articulationPoints, SCCs, cycles };
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
exports.AbstractGraph = AbstractGraph;
|