data-structure-typed 2.5.3 → 2.6.1
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/.github/workflows/ci.yml +7 -2
- package/.github/workflows/release-package.yml +9 -2
- package/.husky/pre-commit +3 -0
- package/CHANGELOG.md +1 -1
- package/MIGRATION.md +48 -0
- package/README.md +20 -2
- package/README_CN.md +20 -2
- package/SPECIFICATION.md +24 -0
- package/SPECIFICATION.zh-CN.md +24 -0
- package/dist/cjs/binary-tree.cjs +1897 -19
- package/dist/cjs/graph.cjs +174 -0
- package/dist/cjs/hash.cjs +33 -0
- package/dist/cjs/heap.cjs +71 -0
- package/dist/cjs/index.cjs +2383 -3
- package/dist/cjs/linked-list.cjs +224 -2
- package/dist/cjs/matrix.cjs +24 -0
- package/dist/cjs/priority-queue.cjs +71 -0
- package/dist/cjs/queue.cjs +221 -1
- package/dist/cjs/stack.cjs +59 -0
- package/dist/cjs/trie.cjs +62 -0
- package/dist/cjs-legacy/binary-tree.cjs +1897 -19
- package/dist/cjs-legacy/graph.cjs +174 -0
- package/dist/cjs-legacy/hash.cjs +33 -0
- package/dist/cjs-legacy/heap.cjs +71 -0
- package/dist/cjs-legacy/index.cjs +2383 -3
- package/dist/cjs-legacy/linked-list.cjs +224 -2
- package/dist/cjs-legacy/matrix.cjs +24 -0
- package/dist/cjs-legacy/priority-queue.cjs +71 -0
- package/dist/cjs-legacy/queue.cjs +221 -1
- package/dist/cjs-legacy/stack.cjs +59 -0
- package/dist/cjs-legacy/trie.cjs +62 -0
- package/dist/esm/binary-tree.mjs +1897 -19
- package/dist/esm/graph.mjs +174 -0
- package/dist/esm/hash.mjs +33 -0
- package/dist/esm/heap.mjs +71 -0
- package/dist/esm/index.mjs +2383 -3
- package/dist/esm/linked-list.mjs +224 -2
- package/dist/esm/matrix.mjs +24 -0
- package/dist/esm/priority-queue.mjs +71 -0
- package/dist/esm/queue.mjs +221 -1
- package/dist/esm/stack.mjs +59 -0
- package/dist/esm/trie.mjs +62 -0
- package/dist/esm-legacy/binary-tree.mjs +1897 -19
- package/dist/esm-legacy/graph.mjs +174 -0
- package/dist/esm-legacy/hash.mjs +33 -0
- package/dist/esm-legacy/heap.mjs +71 -0
- package/dist/esm-legacy/index.mjs +2383 -3
- package/dist/esm-legacy/linked-list.mjs +224 -2
- package/dist/esm-legacy/matrix.mjs +24 -0
- package/dist/esm-legacy/priority-queue.mjs +71 -0
- package/dist/esm-legacy/queue.mjs +221 -1
- package/dist/esm-legacy/stack.mjs +59 -0
- package/dist/esm-legacy/trie.mjs +62 -0
- package/dist/types/data-structures/base/iterable-element-base.d.ts +17 -0
- package/dist/types/data-structures/base/linear-base.d.ts +6 -0
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +36 -0
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +42 -0
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +75 -0
- package/dist/types/data-structures/binary-tree/bst.d.ts +72 -0
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +57 -0
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +18 -0
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +375 -0
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +389 -0
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +330 -0
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +438 -0
- package/dist/types/data-structures/graph/directed-graph.d.ts +30 -0
- package/dist/types/data-structures/graph/undirected-graph.d.ts +27 -0
- package/dist/types/data-structures/hash/hash-map.d.ts +33 -0
- package/dist/types/data-structures/heap/heap.d.ts +42 -0
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +75 -2
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +45 -0
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +54 -0
- package/dist/types/data-structures/matrix/matrix.d.ts +24 -0
- package/dist/types/data-structures/queue/deque.d.ts +90 -1
- package/dist/types/data-structures/queue/queue.d.ts +36 -0
- package/dist/types/data-structures/stack/stack.d.ts +30 -0
- package/dist/types/data-structures/trie/trie.d.ts +36 -0
- package/dist/umd/data-structure-typed.js +2383 -3
- package/dist/umd/data-structure-typed.min.js +3 -3
- package/docs-site-docusaurus/docs/api/classes/AVLTree.md +108 -108
- package/docs-site-docusaurus/docs/api/classes/BST.md +101 -101
- package/docs-site-docusaurus/docs/api/classes/BinaryIndexedTree.md +13 -13
- package/docs-site-docusaurus/docs/api/classes/BinaryTree.md +66 -66
- package/docs-site-docusaurus/docs/api/classes/Deque.md +235 -51
- package/docs-site-docusaurus/docs/api/classes/DirectedGraph.md +21 -21
- package/docs-site-docusaurus/docs/api/classes/DoublyLinkedList.md +231 -67
- package/docs-site-docusaurus/docs/api/classes/FibonacciHeap.md +9 -9
- package/docs-site-docusaurus/docs/api/classes/FibonacciHeapNode.md +1 -1
- package/docs-site-docusaurus/docs/api/classes/HashMap.md +14 -14
- package/docs-site-docusaurus/docs/api/classes/Heap.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/IterableElementBase.md +83 -13
- package/docs-site-docusaurus/docs/api/classes/LinearBase.md +124 -20
- package/docs-site-docusaurus/docs/api/classes/LinearLinkedBase.md +140 -32
- package/docs-site-docusaurus/docs/api/classes/LinkedHashMap.md +30 -26
- package/docs-site-docusaurus/docs/api/classes/LinkedListQueue.md +159 -51
- package/docs-site-docusaurus/docs/api/classes/MapGraph.md +20 -20
- package/docs-site-docusaurus/docs/api/classes/Matrix.md +23 -23
- package/docs-site-docusaurus/docs/api/classes/MaxHeap.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/MaxPriorityQueue.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/MinHeap.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/MinPriorityQueue.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/PriorityQueue.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/Queue.md +142 -34
- package/docs-site-docusaurus/docs/api/classes/RedBlackTree.md +117 -117
- package/docs-site-docusaurus/docs/api/classes/SegmentTree.md +8 -8
- package/docs-site-docusaurus/docs/api/classes/SinglyLinkedList.md +158 -50
- package/docs-site-docusaurus/docs/api/classes/SkipList.md +21 -21
- package/docs-site-docusaurus/docs/api/classes/Stack.md +108 -26
- package/docs-site-docusaurus/docs/api/classes/TreeMap.md +33 -33
- package/docs-site-docusaurus/docs/api/classes/TreeMultiMap.md +75 -39
- package/docs-site-docusaurus/docs/api/classes/TreeSet.md +301 -39
- package/docs-site-docusaurus/docs/api/classes/Trie.md +110 -28
- package/docs-site-docusaurus/docs/api/classes/UndirectedGraph.md +20 -20
- package/jest.integration.config.js +1 -2
- package/package.json +51 -50
- package/src/common/error.ts +15 -32
- package/src/common/index.ts +0 -3
- package/src/data-structures/base/iterable-element-base.ts +32 -3
- package/src/data-structures/base/linear-base.ts +13 -36
- package/src/data-structures/binary-tree/avl-tree.ts +31 -493
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +47 -530
- package/src/data-structures/binary-tree/binary-tree.ts +326 -1236
- package/src/data-structures/binary-tree/bst.ts +158 -1010
- package/src/data-structures/binary-tree/red-black-tree.ts +451 -1233
- package/src/data-structures/binary-tree/segment-tree.ts +73 -333
- package/src/data-structures/binary-tree/tree-map.ts +462 -4749
- package/src/data-structures/binary-tree/tree-multi-map.ts +310 -4530
- package/src/data-structures/binary-tree/tree-multi-set.ts +300 -3652
- package/src/data-structures/binary-tree/tree-set.ts +437 -4443
- package/src/data-structures/graph/abstract-graph.ts +98 -167
- package/src/data-structures/graph/directed-graph.ts +137 -532
- package/src/data-structures/graph/map-graph.ts +0 -3
- package/src/data-structures/graph/undirected-graph.ts +132 -484
- package/src/data-structures/hash/hash-map.ts +154 -549
- package/src/data-structures/heap/heap.ts +200 -753
- package/src/data-structures/linked-list/doubly-linked-list.ts +153 -809
- package/src/data-structures/linked-list/singly-linked-list.ts +122 -749
- package/src/data-structures/linked-list/skip-linked-list.ts +211 -864
- package/src/data-structures/matrix/matrix.ts +179 -494
- package/src/data-structures/matrix/navigator.ts +0 -1
- package/src/data-structures/priority-queue/max-priority-queue.ts +1 -6
- package/src/data-structures/priority-queue/min-priority-queue.ts +6 -11
- package/src/data-structures/priority-queue/priority-queue.ts +1 -2
- package/src/data-structures/queue/deque.ts +241 -807
- package/src/data-structures/queue/queue.ts +102 -589
- package/src/data-structures/stack/stack.ts +76 -475
- package/src/data-structures/trie/trie.ts +98 -592
- package/src/types/common.ts +0 -10
- package/src/types/data-structures/binary-tree/bst.ts +0 -7
- package/src/types/data-structures/binary-tree/red-black-tree.ts +0 -1
- package/src/types/data-structures/graph/abstract-graph.ts +0 -2
- package/src/types/data-structures/hash/hash-map.ts +0 -3
- package/src/types/data-structures/hash/index.ts +0 -1
- package/src/types/data-structures/matrix/navigator.ts +0 -2
- package/src/types/utils/utils.ts +0 -7
- package/src/types/utils/validate-type.ts +0 -7
- package/src/utils/number.ts +0 -2
- package/src/utils/utils.ts +0 -5
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
|
-
|
|
9
8
|
import type { GraphOptions, TopologicalStatus, VertexKey } from '../../types';
|
|
10
9
|
import { AbstractEdge, AbstractGraph, AbstractVertex } from './abstract-graph';
|
|
11
10
|
import { IGraph } from '../../interfaces';
|
|
@@ -133,10 +132,6 @@ export class DirectedGraph<
|
|
|
133
132
|
super(options);
|
|
134
133
|
}
|
|
135
134
|
|
|
136
|
-
protected override get _edgeConnector(): string {
|
|
137
|
-
return '->';
|
|
138
|
-
}
|
|
139
|
-
|
|
140
135
|
protected _outEdgeMap: Map<VO, EO[]> = new Map<VO, EO[]>();
|
|
141
136
|
|
|
142
137
|
get outEdgeMap(): Map<VO, EO[]> {
|
|
@@ -157,6 +152,10 @@ export class DirectedGraph<
|
|
|
157
152
|
this._inEdgeMap = v;
|
|
158
153
|
}
|
|
159
154
|
|
|
155
|
+
protected override get _edgeConnector(): string {
|
|
156
|
+
return '->';
|
|
157
|
+
}
|
|
158
|
+
|
|
160
159
|
/**
|
|
161
160
|
* Construct a directed graph from keys with value initializer `v => v`.
|
|
162
161
|
* @template K - Vertex key type.
|
|
@@ -164,7 +163,9 @@ export class DirectedGraph<
|
|
|
164
163
|
* @returns DirectedGraph with all keys added.
|
|
165
164
|
* @remarks Time O(V), Space O(V)
|
|
166
165
|
*/
|
|
167
|
-
static fromKeys<K extends VertexKey>(
|
|
166
|
+
static fromKeys<K extends VertexKey>(
|
|
167
|
+
keys: Iterable<K>
|
|
168
|
+
): DirectedGraph<K, undefined, DirectedVertex<K>, DirectedEdge<undefined>> {
|
|
168
169
|
const g: DirectedGraph<K, undefined, DirectedVertex<K>, DirectedEdge<undefined>> = new DirectedGraph<K, undefined>({
|
|
169
170
|
vertexValueInitializer: (k: VertexKey) => k as K
|
|
170
171
|
});
|
|
@@ -182,7 +183,10 @@ export class DirectedGraph<
|
|
|
182
183
|
static fromEntries<V>(
|
|
183
184
|
entries: Iterable<[VertexKey, V]>
|
|
184
185
|
): DirectedGraph<V, undefined, DirectedVertex<V>, DirectedEdge<undefined>> {
|
|
185
|
-
const g: DirectedGraph<V, undefined, DirectedVertex<V>, DirectedEdge<undefined>> = new DirectedGraph<
|
|
186
|
+
const g: DirectedGraph<V, undefined, DirectedVertex<V>, DirectedEdge<undefined>> = new DirectedGraph<
|
|
187
|
+
V,
|
|
188
|
+
undefined
|
|
189
|
+
>();
|
|
186
190
|
for (const [k, v] of entries) g.addVertex(k, v);
|
|
187
191
|
return g;
|
|
188
192
|
}
|
|
@@ -217,58 +221,20 @@ export class DirectedGraph<
|
|
|
217
221
|
* @param destOrKey - Destination vertex or key.
|
|
218
222
|
* @returns Edge instance or `undefined`.
|
|
219
223
|
* @remarks Time O(1) avg, Space O(1)
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
* @example
|
|
257
|
-
* // Get edge between vertices
|
|
258
|
-
* const g = new DirectedGraph();
|
|
259
|
-
* g.addVertex('A');
|
|
260
|
-
* g.addVertex('B');
|
|
261
|
-
* g.addEdge('A', 'B', 5);
|
|
262
|
-
* const edge = g.getEdge('A', 'B');
|
|
263
|
-
* console.log(edge?.weight); // 5;
|
|
224
|
+
* @example
|
|
225
|
+
* // Get edge between vertices
|
|
226
|
+
* const g = new DirectedGraph();
|
|
227
|
+
* g.addVertex('A');
|
|
228
|
+
* g.addVertex('B');
|
|
229
|
+
* g.addEdge('A', 'B', 5);
|
|
230
|
+
* const edge = g.getEdge('A', 'B');
|
|
231
|
+
* console.log(edge?.weight); // 5;
|
|
264
232
|
*/
|
|
265
233
|
getEdge(srcOrKey: VO | VertexKey | undefined, destOrKey: VO | VertexKey | undefined): EO | undefined {
|
|
266
234
|
let edgeMap: EO[] = [];
|
|
267
|
-
|
|
268
235
|
if (srcOrKey !== undefined && destOrKey !== undefined) {
|
|
269
236
|
const src: VO | undefined = this._getVertex(srcOrKey);
|
|
270
237
|
const dest: VO | undefined = this._getVertex(destOrKey);
|
|
271
|
-
|
|
272
238
|
if (src && dest) {
|
|
273
239
|
const srcOutEdges = this._outEdgeMap.get(src);
|
|
274
240
|
if (srcOutEdges) {
|
|
@@ -276,7 +242,6 @@ export class DirectedGraph<
|
|
|
276
242
|
}
|
|
277
243
|
}
|
|
278
244
|
}
|
|
279
|
-
|
|
280
245
|
return edgeMap[0] || undefined;
|
|
281
246
|
}
|
|
282
247
|
|
|
@@ -294,12 +259,10 @@ export class DirectedGraph<
|
|
|
294
259
|
if (!src || !dest) {
|
|
295
260
|
return undefined;
|
|
296
261
|
}
|
|
297
|
-
|
|
298
262
|
const srcOutEdges = this._outEdgeMap.get(src);
|
|
299
263
|
if (srcOutEdges) {
|
|
300
264
|
arrayRemove<EO>(srcOutEdges, (edge: EO) => edge.dest === dest.key);
|
|
301
265
|
}
|
|
302
|
-
|
|
303
266
|
const destInEdges = this._inEdgeMap.get(dest);
|
|
304
267
|
if (destInEdges) {
|
|
305
268
|
removed = arrayRemove<EO>(destInEdges, (edge: EO) => edge.src === src.key)[0] || undefined;
|
|
@@ -313,70 +276,31 @@ export class DirectedGraph<
|
|
|
313
276
|
* @param destVertexKey - Optional destination vertex/key when deleting by pair.
|
|
314
277
|
* @returns Removed edge or `undefined`.
|
|
315
278
|
* @remarks Time O(1) avg, Space O(1)
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
* @example
|
|
356
|
-
* // DirectedGraph deleteEdge and vertex operations
|
|
357
|
-
* const graph = new DirectedGraph<string>();
|
|
358
|
-
*
|
|
359
|
-
* // Build a small graph
|
|
360
|
-
* graph.addVertex('X');
|
|
361
|
-
* graph.addVertex('Y');
|
|
362
|
-
* graph.addVertex('Z');
|
|
363
|
-
* graph.addEdge('X', 'Y', 1);
|
|
364
|
-
* graph.addEdge('Y', 'Z', 2);
|
|
365
|
-
*
|
|
366
|
-
* // Delete an edge
|
|
367
|
-
* graph.deleteEdgeSrcToDest('X', 'Y');
|
|
368
|
-
* console.log(graph.hasEdge('X', 'Y')); // false;
|
|
369
|
-
*
|
|
370
|
-
* // Edge in other direction should not exist
|
|
371
|
-
* console.log(graph.hasEdge('Y', 'X')); // false;
|
|
372
|
-
*
|
|
373
|
-
* // Other edges should remain
|
|
374
|
-
* console.log(graph.hasEdge('Y', 'Z')); // true;
|
|
375
|
-
*
|
|
376
|
-
* // Delete a vertex
|
|
377
|
-
* graph.deleteVertex('Y');
|
|
378
|
-
* console.log(graph.hasVertex('Y')); // false;
|
|
379
|
-
* console.log(graph.size); // 2;
|
|
279
|
+
* @example
|
|
280
|
+
* // DirectedGraph deleteEdge and vertex operations
|
|
281
|
+
* const graph = new DirectedGraph<string>();
|
|
282
|
+
*
|
|
283
|
+
* // Build a small graph
|
|
284
|
+
* graph.addVertex('X');
|
|
285
|
+
* graph.addVertex('Y');
|
|
286
|
+
* graph.addVertex('Z');
|
|
287
|
+
* graph.addEdge('X', 'Y', 1);
|
|
288
|
+
* graph.addEdge('Y', 'Z', 2);
|
|
289
|
+
*
|
|
290
|
+
* // Delete an edge
|
|
291
|
+
* graph.deleteEdgeSrcToDest('X', 'Y');
|
|
292
|
+
* console.log(graph.hasEdge('X', 'Y')); // false;
|
|
293
|
+
*
|
|
294
|
+
* // Edge in other direction should not exist
|
|
295
|
+
* console.log(graph.hasEdge('Y', 'X')); // false;
|
|
296
|
+
*
|
|
297
|
+
* // Other edges should remain
|
|
298
|
+
* console.log(graph.hasEdge('Y', 'Z')); // true;
|
|
299
|
+
*
|
|
300
|
+
* // Delete a vertex
|
|
301
|
+
* graph.deleteVertex('Y');
|
|
302
|
+
* console.log(graph.hasVertex('Y')); // false;
|
|
303
|
+
* console.log(graph.size); // 2;
|
|
380
304
|
*/
|
|
381
305
|
deleteEdge(edgeOrSrcVertexKey: EO | VertexKey, destVertexKey?: VertexKey): EO | undefined {
|
|
382
306
|
let removed: EO | undefined = undefined;
|
|
@@ -392,69 +316,30 @@ export class DirectedGraph<
|
|
|
392
316
|
src = this._getVertex(edgeOrSrcVertexKey.src);
|
|
393
317
|
dest = this._getVertex(edgeOrSrcVertexKey.dest);
|
|
394
318
|
}
|
|
395
|
-
|
|
396
319
|
if (src && dest) {
|
|
397
320
|
const srcOutEdges = this._outEdgeMap.get(src);
|
|
398
321
|
if (srcOutEdges && srcOutEdges.length > 0) {
|
|
399
322
|
arrayRemove(srcOutEdges, (edge: EO) => edge.src === src!.key && edge.dest === dest?.key);
|
|
400
323
|
}
|
|
401
|
-
|
|
402
324
|
const destInEdges = this._inEdgeMap.get(dest);
|
|
403
325
|
if (destInEdges && destInEdges.length > 0) {
|
|
404
326
|
removed = arrayRemove(destInEdges, (edge: EO) => edge.src === src!.key && edge.dest === dest!.key)[0];
|
|
405
327
|
}
|
|
406
328
|
}
|
|
407
|
-
|
|
408
329
|
return removed;
|
|
409
330
|
}
|
|
410
331
|
|
|
411
|
-
|
|
332
|
+
/**
|
|
412
333
|
* Remove a vertex
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
* @example
|
|
450
|
-
* // Remove a vertex
|
|
451
|
-
* const g = new DirectedGraph();
|
|
452
|
-
* g.addVertex('A');
|
|
453
|
-
* g.addVertex('B');
|
|
454
|
-
* g.addEdge('A', 'B');
|
|
455
|
-
* g.deleteVertex('A');
|
|
456
|
-
* console.log(g.hasVertex('A')); // false;
|
|
457
|
-
* console.log(g.hasEdge('A', 'B')); // false;
|
|
334
|
+
* @example
|
|
335
|
+
* // Remove a vertex
|
|
336
|
+
* const g = new DirectedGraph();
|
|
337
|
+
* g.addVertex('A');
|
|
338
|
+
* g.addVertex('B');
|
|
339
|
+
* g.addEdge('A', 'B');
|
|
340
|
+
* g.deleteVertex('A');
|
|
341
|
+
* console.log(g.hasVertex('A')); // false;
|
|
342
|
+
* console.log(g.hasEdge('A', 'B')); // false;
|
|
458
343
|
*/
|
|
459
344
|
deleteVertex(vertexOrKey: VO | VertexKey): boolean {
|
|
460
345
|
let vertexKey: VertexKey;
|
|
@@ -466,7 +351,6 @@ export class DirectedGraph<
|
|
|
466
351
|
vertex = vertexOrKey;
|
|
467
352
|
vertexKey = this._getVertexKey(vertexOrKey);
|
|
468
353
|
}
|
|
469
|
-
|
|
470
354
|
if (vertex) {
|
|
471
355
|
/**
|
|
472
356
|
* One-step neighbors following outgoing edges.
|
|
@@ -481,21 +365,17 @@ export class DirectedGraph<
|
|
|
481
365
|
this._outEdgeMap.delete(vertex);
|
|
482
366
|
this._inEdgeMap.delete(vertex);
|
|
483
367
|
}
|
|
484
|
-
|
|
485
368
|
return this._vertexMap.delete(vertexKey);
|
|
486
369
|
}
|
|
487
370
|
|
|
488
371
|
deleteEdgesBetween(v1: VertexKey | VO, v2: VertexKey | VO): EO[] {
|
|
489
372
|
const removed: EO[] = [];
|
|
490
|
-
|
|
491
373
|
if (v1 && v2) {
|
|
492
374
|
const v1ToV2 = this.deleteEdgeSrcToDest(v1, v2);
|
|
493
375
|
const v2ToV1 = this.deleteEdgeSrcToDest(v2, v1);
|
|
494
|
-
|
|
495
376
|
if (v1ToV2) removed.push(v1ToV2);
|
|
496
377
|
if (v2ToV1) removed.push(v2ToV1);
|
|
497
378
|
}
|
|
498
|
-
|
|
499
379
|
return removed;
|
|
500
380
|
}
|
|
501
381
|
|
|
@@ -504,51 +384,15 @@ export class DirectedGraph<
|
|
|
504
384
|
* @param vertexOrKey - Vertex or key.
|
|
505
385
|
* @returns Array of incoming edges.
|
|
506
386
|
* @remarks Time O(deg_in), Space O(deg_in)
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
* @example
|
|
544
|
-
* // Get incoming edges
|
|
545
|
-
* const g = new DirectedGraph();
|
|
546
|
-
* g.addVertex('A');
|
|
547
|
-
* g.addVertex('B');
|
|
548
|
-
* g.addVertex('C');
|
|
549
|
-
* g.addEdge('A', 'C');
|
|
550
|
-
* g.addEdge('B', 'C');
|
|
551
|
-
* console.log(g.incomingEdgesOf('C').length); // 2;
|
|
387
|
+
* @example
|
|
388
|
+
* // Get incoming edges
|
|
389
|
+
* const g = new DirectedGraph();
|
|
390
|
+
* g.addVertex('A');
|
|
391
|
+
* g.addVertex('B');
|
|
392
|
+
* g.addVertex('C');
|
|
393
|
+
* g.addEdge('A', 'C');
|
|
394
|
+
* g.addEdge('B', 'C');
|
|
395
|
+
* console.log(g.incomingEdgesOf('C').length); // 2;
|
|
552
396
|
*/
|
|
553
397
|
incomingEdgesOf(vertexOrKey: VO | VertexKey): EO[] {
|
|
554
398
|
const target = this._getVertex(vertexOrKey);
|
|
@@ -563,51 +407,15 @@ export class DirectedGraph<
|
|
|
563
407
|
* @param vertexOrKey - Vertex or key.
|
|
564
408
|
* @returns Array of outgoing edges.
|
|
565
409
|
* @remarks Time O(deg_out), Space O(deg_out)
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
* @example
|
|
603
|
-
* // Get outgoing edges
|
|
604
|
-
* const g = new DirectedGraph();
|
|
605
|
-
* g.addVertex('A');
|
|
606
|
-
* g.addVertex('B');
|
|
607
|
-
* g.addVertex('C');
|
|
608
|
-
* g.addEdge('A', 'B');
|
|
609
|
-
* g.addEdge('A', 'C');
|
|
610
|
-
* console.log(g.outgoingEdgesOf('A').length); // 2;
|
|
410
|
+
* @example
|
|
411
|
+
* // Get outgoing edges
|
|
412
|
+
* const g = new DirectedGraph();
|
|
413
|
+
* g.addVertex('A');
|
|
414
|
+
* g.addVertex('B');
|
|
415
|
+
* g.addVertex('C');
|
|
416
|
+
* g.addEdge('A', 'B');
|
|
417
|
+
* g.addEdge('A', 'C');
|
|
418
|
+
* console.log(g.outgoingEdgesOf('A').length); // 2;
|
|
611
419
|
*/
|
|
612
420
|
outgoingEdgesOf(vertexOrKey: VO | VertexKey): EO[] {
|
|
613
421
|
const target = this._getVertex(vertexOrKey);
|
|
@@ -691,76 +499,35 @@ export class DirectedGraph<
|
|
|
691
499
|
* @param propertyName - `'key'` to map to keys; `'vertex'` to keep instances.
|
|
692
500
|
* @returns Array of keys/vertices, or `undefined` when cycle is found.
|
|
693
501
|
* @remarks Time O(V + E), Space O(V)
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
* @example
|
|
734
|
-
* // DirectedGraph topologicalSort for task scheduling
|
|
735
|
-
* const graph = new DirectedGraph<string>();
|
|
736
|
-
*
|
|
737
|
-
* // Build a DAG (Directed Acyclic Graph) for task dependencies
|
|
738
|
-
* graph.addVertex('Design');
|
|
739
|
-
* graph.addVertex('Implement');
|
|
740
|
-
* graph.addVertex('Test');
|
|
741
|
-
* graph.addVertex('Deploy');
|
|
742
|
-
*
|
|
743
|
-
* // Add dependency edges
|
|
744
|
-
* graph.addEdge('Design', 'Implement', 1); // Design must come before Implement
|
|
745
|
-
* graph.addEdge('Implement', 'Test', 1); // Implement must come before Test
|
|
746
|
-
* graph.addEdge('Test', 'Deploy', 1); // Test must come before Deploy
|
|
747
|
-
*
|
|
748
|
-
* // Topological sort gives valid execution order
|
|
749
|
-
* const executionOrder = graph.topologicalSort();
|
|
750
|
-
* console.log(executionOrder); // defined;
|
|
751
|
-
* console.log(executionOrder); // ['Design', 'Implement', 'Test', 'Deploy'];
|
|
752
|
-
*
|
|
753
|
-
* // All vertices should be included
|
|
754
|
-
* console.log(executionOrder?.length); // 4;
|
|
502
|
+
* @example
|
|
503
|
+
* // DirectedGraph topologicalSort for task scheduling
|
|
504
|
+
* const graph = new DirectedGraph<string>();
|
|
505
|
+
*
|
|
506
|
+
* // Build a DAG (Directed Acyclic Graph) for task dependencies
|
|
507
|
+
* graph.addVertex('Design');
|
|
508
|
+
* graph.addVertex('Implement');
|
|
509
|
+
* graph.addVertex('Test');
|
|
510
|
+
* graph.addVertex('Deploy');
|
|
511
|
+
*
|
|
512
|
+
* // Add dependency edges
|
|
513
|
+
* graph.addEdge('Design', 'Implement', 1); // Design must come before Implement
|
|
514
|
+
* graph.addEdge('Implement', 'Test', 1); // Implement must come before Test
|
|
515
|
+
* graph.addEdge('Test', 'Deploy', 1); // Test must come before Deploy
|
|
516
|
+
*
|
|
517
|
+
* // Topological sort gives valid execution order
|
|
518
|
+
* const executionOrder = graph.topologicalSort();
|
|
519
|
+
* console.log(executionOrder); // defined;
|
|
520
|
+
* console.log(executionOrder); // ['Design', 'Implement', 'Test', 'Deploy'];
|
|
521
|
+
*
|
|
522
|
+
* // All vertices should be included
|
|
523
|
+
* console.log(executionOrder?.length); // 4;
|
|
755
524
|
*/
|
|
756
525
|
topologicalSort(propertyName?: 'vertex' | 'key'): Array<VO | VertexKey> | undefined {
|
|
757
526
|
propertyName = propertyName ?? 'key';
|
|
758
|
-
|
|
759
527
|
const statusMap: Map<VO | VertexKey, TopologicalStatus> = new Map<VO | VertexKey, TopologicalStatus>();
|
|
760
528
|
for (const entry of this.vertexMap) {
|
|
761
529
|
statusMap.set(entry[1], 0);
|
|
762
530
|
}
|
|
763
|
-
|
|
764
531
|
let sorted: (VO | VertexKey)[] = [];
|
|
765
532
|
let hasCycle = false;
|
|
766
533
|
const dfs = (cur: VO | VertexKey) => {
|
|
@@ -777,64 +544,25 @@ export class DirectedGraph<
|
|
|
777
544
|
statusMap.set(cur, 2);
|
|
778
545
|
sorted.push(cur);
|
|
779
546
|
};
|
|
780
|
-
|
|
781
547
|
for (const entry of this.vertexMap) {
|
|
782
548
|
if (statusMap.get(entry[1]) === 0) {
|
|
783
549
|
dfs(entry[1]);
|
|
784
550
|
}
|
|
785
551
|
}
|
|
786
|
-
|
|
787
552
|
if (hasCycle) return undefined;
|
|
788
|
-
|
|
789
553
|
if (propertyName === 'key') sorted = sorted.map(vertex => (vertex instanceof DirectedVertex ? vertex.key : vertex));
|
|
790
554
|
return sorted.reverse();
|
|
791
555
|
}
|
|
792
556
|
|
|
793
|
-
|
|
557
|
+
/**
|
|
794
558
|
* Get all edges
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
* @example
|
|
832
|
-
* // Get all edges
|
|
833
|
-
* const g = new DirectedGraph();
|
|
834
|
-
* g.addVertex('A');
|
|
835
|
-
* g.addVertex('B');
|
|
836
|
-
* g.addEdge('A', 'B', 3);
|
|
837
|
-
* console.log(g.edgeSet().length); // 1;
|
|
559
|
+
* @example
|
|
560
|
+
* // Get all edges
|
|
561
|
+
* const g = new DirectedGraph();
|
|
562
|
+
* g.addVertex('A');
|
|
563
|
+
* g.addVertex('B');
|
|
564
|
+
* g.addEdge('A', 'B', 3);
|
|
565
|
+
* console.log(g.edgeSet().length); // 1;
|
|
838
566
|
*/
|
|
839
567
|
edgeSet(): EO[] {
|
|
840
568
|
let edgeMap: EO[] = [];
|
|
@@ -844,55 +572,18 @@ export class DirectedGraph<
|
|
|
844
572
|
return edgeMap;
|
|
845
573
|
}
|
|
846
574
|
|
|
847
|
-
|
|
575
|
+
/**
|
|
848
576
|
* Get outgoing neighbors
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
* @example
|
|
887
|
-
* // Get outgoing neighbors
|
|
888
|
-
* const g = new DirectedGraph();
|
|
889
|
-
* g.addVertex('A');
|
|
890
|
-
* g.addVertex('B');
|
|
891
|
-
* g.addVertex('C');
|
|
892
|
-
* g.addEdge('A', 'B');
|
|
893
|
-
* g.addEdge('A', 'C');
|
|
894
|
-
* const neighbors = g.getNeighbors('A');
|
|
895
|
-
* console.log(neighbors.map(v => v.key).sort()); // ['B', 'C'];
|
|
577
|
+
* @example
|
|
578
|
+
* // Get outgoing neighbors
|
|
579
|
+
* const g = new DirectedGraph();
|
|
580
|
+
* g.addVertex('A');
|
|
581
|
+
* g.addVertex('B');
|
|
582
|
+
* g.addVertex('C');
|
|
583
|
+
* g.addEdge('A', 'B');
|
|
584
|
+
* g.addEdge('A', 'C');
|
|
585
|
+
* const neighbors = g.getNeighbors('A');
|
|
586
|
+
* console.log(neighbors.map(v => v.key).sort()); // ['B', 'C'];
|
|
896
587
|
*/
|
|
897
588
|
getNeighbors(vertexOrKey: VO | VertexKey): VO[] {
|
|
898
589
|
const neighbors: VO[] = [];
|
|
@@ -901,7 +592,6 @@ export class DirectedGraph<
|
|
|
901
592
|
const outEdges = this.outgoingEdgesOf(vertex);
|
|
902
593
|
for (const outEdge of outEdges) {
|
|
903
594
|
const neighbor = this._getVertex(outEdge.dest);
|
|
904
|
-
|
|
905
595
|
if (neighbor) {
|
|
906
596
|
neighbors.push(neighbor);
|
|
907
597
|
}
|
|
@@ -960,74 +650,33 @@ export class DirectedGraph<
|
|
|
960
650
|
* Tarjan's algorithm for strongly connected components.
|
|
961
651
|
* @returns `{ dfnMap, lowMap, SCCs }`.
|
|
962
652
|
* @remarks Time O(V + E), Space O(V + E)
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
* @example
|
|
1000
|
-
* // Find strongly connected components
|
|
1001
|
-
* const g = new DirectedGraph();
|
|
1002
|
-
* g.addVertex('A');
|
|
1003
|
-
* g.addVertex('B');
|
|
1004
|
-
* g.addVertex('C');
|
|
1005
|
-
* g.addEdge('A', 'B');
|
|
1006
|
-
* g.addEdge('B', 'C');
|
|
1007
|
-
* g.addEdge('C', 'A');
|
|
1008
|
-
* const { SCCs } = g.tarjan();
|
|
1009
|
-
* // A→B→C→A forms one SCC with 3 members
|
|
1010
|
-
* const sccArrays = [...SCCs.values()];
|
|
1011
|
-
* console.log(sccArrays.some(scc => scc.length === 3)); // true;
|
|
653
|
+
* @example
|
|
654
|
+
* // Find strongly connected components
|
|
655
|
+
* const g = new DirectedGraph();
|
|
656
|
+
* g.addVertex('A');
|
|
657
|
+
* g.addVertex('B');
|
|
658
|
+
* g.addVertex('C');
|
|
659
|
+
* g.addEdge('A', 'B');
|
|
660
|
+
* g.addEdge('B', 'C');
|
|
661
|
+
* g.addEdge('C', 'A');
|
|
662
|
+
* const { SCCs } = g.tarjan();
|
|
663
|
+
* // A→B→C→A forms one SCC with 3 members
|
|
664
|
+
* const sccArrays = [...SCCs.values()];
|
|
665
|
+
* console.log(sccArrays.some(scc => scc.length === 3)); // true;
|
|
1012
666
|
*/
|
|
1013
667
|
tarjan(): { dfnMap: Map<VO, number>; lowMap: Map<VO, number>; SCCs: Map<number, VO[]> } {
|
|
1014
668
|
const dfnMap = new Map<VO, number>();
|
|
1015
669
|
const lowMap = new Map<VO, number>();
|
|
1016
670
|
const SCCs = new Map<number, VO[]>();
|
|
1017
|
-
|
|
1018
671
|
let time = 0;
|
|
1019
|
-
|
|
1020
672
|
const stack: VO[] = [];
|
|
1021
673
|
const inStack: Set<VO> = new Set();
|
|
1022
|
-
|
|
1023
674
|
const dfs = (vertex: VO) => {
|
|
1024
675
|
dfnMap.set(vertex, time);
|
|
1025
676
|
lowMap.set(vertex, time);
|
|
1026
677
|
time++;
|
|
1027
|
-
|
|
1028
678
|
stack.push(vertex);
|
|
1029
679
|
inStack.add(vertex);
|
|
1030
|
-
|
|
1031
680
|
const neighbors = this.getNeighbors(vertex);
|
|
1032
681
|
for (const neighbor of neighbors) {
|
|
1033
682
|
if (!dfnMap.has(neighbor)) {
|
|
@@ -1037,27 +686,22 @@ export class DirectedGraph<
|
|
|
1037
686
|
lowMap.set(vertex, Math.min(lowMap.get(vertex)!, dfnMap.get(neighbor)!));
|
|
1038
687
|
}
|
|
1039
688
|
}
|
|
1040
|
-
|
|
1041
689
|
if (dfnMap.get(vertex) === lowMap.get(vertex)) {
|
|
1042
690
|
const SCC: VO[] = [];
|
|
1043
691
|
let poppedVertex: VO | undefined;
|
|
1044
|
-
|
|
1045
692
|
do {
|
|
1046
693
|
poppedVertex = stack.pop();
|
|
1047
694
|
inStack.delete(poppedVertex!);
|
|
1048
695
|
SCC.push(poppedVertex!);
|
|
1049
696
|
} while (poppedVertex !== vertex);
|
|
1050
|
-
|
|
1051
697
|
SCCs.set(SCCs.size, SCC);
|
|
1052
698
|
}
|
|
1053
699
|
};
|
|
1054
|
-
|
|
1055
700
|
for (const vertex of this.vertexMap.values()) {
|
|
1056
701
|
if (!dfnMap.has(vertex)) {
|
|
1057
702
|
dfs(vertex);
|
|
1058
703
|
}
|
|
1059
704
|
}
|
|
1060
|
-
|
|
1061
705
|
return { dfnMap, lowMap, SCCs };
|
|
1062
706
|
}
|
|
1063
707
|
|
|
@@ -1083,53 +727,17 @@ export class DirectedGraph<
|
|
|
1083
727
|
* Strongly connected components computed by `tarjan()`.
|
|
1084
728
|
* @returns Map from SCC id to vertices.
|
|
1085
729
|
* @remarks Time O(#SCC + V), Space O(V)
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
* @example
|
|
1123
|
-
* // Get strongly connected components
|
|
1124
|
-
* const g = new DirectedGraph();
|
|
1125
|
-
* g.addVertex(1);
|
|
1126
|
-
* g.addVertex(2);
|
|
1127
|
-
* g.addVertex(3);
|
|
1128
|
-
* g.addEdge(1, 2);
|
|
1129
|
-
* g.addEdge(2, 3);
|
|
1130
|
-
* g.addEdge(3, 1);
|
|
1131
|
-
* const sccs = g.getSCCs(); // Map<number, VO[]>
|
|
1132
|
-
* console.log(sccs.size); // >= 1;
|
|
730
|
+
* @example
|
|
731
|
+
* // Get strongly connected components
|
|
732
|
+
* const g = new DirectedGraph();
|
|
733
|
+
* g.addVertex(1);
|
|
734
|
+
* g.addVertex(2);
|
|
735
|
+
* g.addVertex(3);
|
|
736
|
+
* g.addEdge(1, 2);
|
|
737
|
+
* g.addEdge(2, 3);
|
|
738
|
+
* g.addEdge(3, 1);
|
|
739
|
+
* const sccs = g.getSCCs(); // Map<number, VO[]>
|
|
740
|
+
* console.log(sccs.size); // >= 1;
|
|
1133
741
|
*/
|
|
1134
742
|
getSCCs(): Map<number, VO[]> {
|
|
1135
743
|
return this.tarjan().SCCs;
|
|
@@ -1145,10 +753,8 @@ export class DirectedGraph<
|
|
|
1145
753
|
if (!(this.hasVertex(edge.src) && this.hasVertex(edge.dest))) {
|
|
1146
754
|
return false;
|
|
1147
755
|
}
|
|
1148
|
-
|
|
1149
756
|
const srcVertex = this._getVertex(edge.src);
|
|
1150
757
|
const destVertex = this._getVertex(edge.dest);
|
|
1151
|
-
|
|
1152
758
|
if (srcVertex && destVertex) {
|
|
1153
759
|
const srcOutEdges = this._outEdgeMap.get(srcVertex);
|
|
1154
760
|
if (srcOutEdges) {
|
|
@@ -1156,7 +762,6 @@ export class DirectedGraph<
|
|
|
1156
762
|
} else {
|
|
1157
763
|
this._outEdgeMap.set(srcVertex, [edge]);
|
|
1158
764
|
}
|
|
1159
|
-
|
|
1160
765
|
const destInEdges = this._inEdgeMap.get(destVertex);
|
|
1161
766
|
if (destInEdges) {
|
|
1162
767
|
destInEdges.push(edge);
|