data-structure-typed 2.6.0 → 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/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 +23 -23
- 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/package.json +45 -46
- package/src/common/error.ts +15 -32
- package/src/common/index.ts +0 -3
- package/src/data-structures/base/iterable-element-base.ts +0 -3
- package/src/data-structures/base/linear-base.ts +2 -36
- package/src/data-structures/binary-tree/avl-tree.ts +31 -529
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +47 -572
- package/src/data-structures/binary-tree/binary-tree.ts +326 -1311
- package/src/data-structures/binary-tree/bst.ts +158 -1082
- package/src/data-structures/binary-tree/red-black-tree.ts +451 -1290
- package/src/data-structures/binary-tree/segment-tree.ts +73 -351
- package/src/data-structures/binary-tree/tree-map.ts +462 -5124
- package/src/data-structures/binary-tree/tree-multi-map.ts +302 -4914
- package/src/data-structures/binary-tree/tree-multi-set.ts +284 -3972
- package/src/data-structures/binary-tree/tree-set.ts +338 -4836
- package/src/data-structures/graph/abstract-graph.ts +98 -167
- package/src/data-structures/graph/directed-graph.ts +137 -562
- package/src/data-structures/graph/map-graph.ts +0 -3
- package/src/data-structures/graph/undirected-graph.ts +132 -511
- package/src/data-structures/hash/hash-map.ts +154 -582
- package/src/data-structures/heap/heap.ts +200 -795
- package/src/data-structures/linked-list/doubly-linked-list.ts +121 -865
- package/src/data-structures/linked-list/singly-linked-list.ts +122 -794
- package/src/data-structures/linked-list/skip-linked-list.ts +211 -918
- package/src/data-structures/matrix/matrix.ts +179 -518
- 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 +214 -882
- package/src/data-structures/queue/queue.ts +102 -625
- package/src/data-structures/stack/stack.ts +76 -505
- package/src/data-structures/trie/trie.ts +98 -628
- 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, VertexKey } from '../../types';
|
|
10
9
|
import { IGraph } from '../../interfaces';
|
|
11
10
|
import { AbstractEdge, AbstractGraph, AbstractVertex } from './abstract-graph';
|
|
@@ -155,7 +154,6 @@ export class UndirectedGraph<
|
|
|
155
154
|
}
|
|
156
155
|
|
|
157
156
|
protected _edgeMap: Map<VO, EO[]>;
|
|
158
|
-
|
|
159
157
|
get edgeMap(): Map<VO, EO[]> {
|
|
160
158
|
return this._edgeMap;
|
|
161
159
|
}
|
|
@@ -174,7 +172,10 @@ export class UndirectedGraph<
|
|
|
174
172
|
static fromKeys<K extends VertexKey>(
|
|
175
173
|
keys: Iterable<K>
|
|
176
174
|
): UndirectedGraph<K, undefined, UndirectedVertex<K>, UndirectedEdge<undefined>> {
|
|
177
|
-
const g: UndirectedGraph<K, undefined, UndirectedVertex<K>, UndirectedEdge<undefined>> = new UndirectedGraph<
|
|
175
|
+
const g: UndirectedGraph<K, undefined, UndirectedVertex<K>, UndirectedEdge<undefined>> = new UndirectedGraph<
|
|
176
|
+
K,
|
|
177
|
+
undefined
|
|
178
|
+
>({
|
|
178
179
|
vertexValueInitializer: (k: VertexKey) => k as K
|
|
179
180
|
});
|
|
180
181
|
for (const k of keys) g.addVertex(k);
|
|
@@ -191,7 +192,10 @@ export class UndirectedGraph<
|
|
|
191
192
|
static fromEntries<V>(
|
|
192
193
|
entries: Iterable<[VertexKey, V]>
|
|
193
194
|
): UndirectedGraph<V, undefined, UndirectedVertex<V>, UndirectedEdge<undefined>> {
|
|
194
|
-
const g: UndirectedGraph<V, undefined, UndirectedVertex<V>, UndirectedEdge<undefined>> = new UndirectedGraph<
|
|
195
|
+
const g: UndirectedGraph<V, undefined, UndirectedVertex<V>, UndirectedEdge<undefined>> = new UndirectedGraph<
|
|
196
|
+
V,
|
|
197
|
+
undefined
|
|
198
|
+
>();
|
|
195
199
|
for (const [k, v] of entries) g.addVertex(k, v);
|
|
196
200
|
return g;
|
|
197
201
|
}
|
|
@@ -226,65 +230,23 @@ export class UndirectedGraph<
|
|
|
226
230
|
* @param v2 - The other vertex or key.
|
|
227
231
|
* @returns Edge instance or `undefined`.
|
|
228
232
|
* @remarks Time O(1) avg, Space O(1)
|
|
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
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
* @example
|
|
269
|
-
* // Get edge between vertices
|
|
270
|
-
* const g = new UndirectedGraph();
|
|
271
|
-
* g.addVertex('A');
|
|
272
|
-
* g.addVertex('B');
|
|
273
|
-
* g.addEdge('A', 'B', 7);
|
|
274
|
-
* console.log(g.getEdge('A', 'B')?.weight); // 7;
|
|
233
|
+
* @example
|
|
234
|
+
* // Get edge between vertices
|
|
235
|
+
* const g = new UndirectedGraph();
|
|
236
|
+
* g.addVertex('A');
|
|
237
|
+
* g.addVertex('B');
|
|
238
|
+
* g.addEdge('A', 'B', 7);
|
|
239
|
+
* console.log(g.getEdge('A', 'B')?.weight); // 7;
|
|
275
240
|
*/
|
|
276
241
|
getEdge(v1: VO | VertexKey | undefined, v2: VO | VertexKey | undefined): EO | undefined {
|
|
277
242
|
let edgeMap: EO[] | undefined = [];
|
|
278
|
-
|
|
279
243
|
if (v1 !== undefined && v2 !== undefined) {
|
|
280
244
|
const vertex1: VO | undefined = this._getVertex(v1);
|
|
281
245
|
const vertex2: VO | undefined = this._getVertex(v2);
|
|
282
|
-
|
|
283
246
|
if (vertex1 && vertex2) {
|
|
284
247
|
edgeMap = this._edgeMap.get(vertex1)?.filter(e => e.endpoints.includes(vertex2.key));
|
|
285
248
|
}
|
|
286
249
|
}
|
|
287
|
-
|
|
288
250
|
return edgeMap ? edgeMap[0] || undefined : undefined;
|
|
289
251
|
}
|
|
290
252
|
|
|
@@ -298,11 +260,9 @@ export class UndirectedGraph<
|
|
|
298
260
|
deleteEdgeBetween(v1: VO | VertexKey, v2: VO | VertexKey): EO | undefined {
|
|
299
261
|
const vertex1: VO | undefined = this._getVertex(v1);
|
|
300
262
|
const vertex2: VO | undefined = this._getVertex(v2);
|
|
301
|
-
|
|
302
263
|
if (!vertex1 || !vertex2) {
|
|
303
264
|
return undefined;
|
|
304
265
|
}
|
|
305
|
-
|
|
306
266
|
const v1Edges = this._edgeMap.get(vertex1);
|
|
307
267
|
let removed: EO | undefined = undefined;
|
|
308
268
|
if (v1Edges) {
|
|
@@ -321,75 +281,33 @@ export class UndirectedGraph<
|
|
|
321
281
|
* @param otherSideVertexKey - Required second endpoint when deleting by pair.
|
|
322
282
|
* @returns Removed edge or `undefined`.
|
|
323
283
|
* @remarks Time O(1) avg, Space O(1)
|
|
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
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
* @example
|
|
367
|
-
* // UndirectedGraph deleteEdge and vertex operations
|
|
368
|
-
* const graph = new UndirectedGraph<string>();
|
|
369
|
-
*
|
|
370
|
-
* // Build a simple undirected graph
|
|
371
|
-
* graph.addVertex('X');
|
|
372
|
-
* graph.addVertex('Y');
|
|
373
|
-
* graph.addVertex('Z');
|
|
374
|
-
* graph.addEdge('X', 'Y', 1);
|
|
375
|
-
* graph.addEdge('Y', 'Z', 2);
|
|
376
|
-
* graph.addEdge('X', 'Z', 3);
|
|
377
|
-
*
|
|
378
|
-
* // Delete an edge
|
|
379
|
-
* graph.deleteEdge('X', 'Y');
|
|
380
|
-
* console.log(graph.hasEdge('X', 'Y')); // false;
|
|
381
|
-
*
|
|
382
|
-
* // Bidirectional deletion confirmed
|
|
383
|
-
* console.log(graph.hasEdge('Y', 'X')); // false;
|
|
384
|
-
*
|
|
385
|
-
* // Other edges should remain
|
|
386
|
-
* console.log(graph.hasEdge('Y', 'Z')); // true;
|
|
387
|
-
* console.log(graph.hasEdge('Z', 'Y')); // true;
|
|
388
|
-
*
|
|
389
|
-
* // Delete a vertex
|
|
390
|
-
* graph.deleteVertex('Y');
|
|
391
|
-
* console.log(graph.hasVertex('Y')); // false;
|
|
392
|
-
* console.log(graph.size); // 2;
|
|
284
|
+
* @example
|
|
285
|
+
* // UndirectedGraph deleteEdge and vertex operations
|
|
286
|
+
* const graph = new UndirectedGraph<string>();
|
|
287
|
+
*
|
|
288
|
+
* // Build a simple undirected graph
|
|
289
|
+
* graph.addVertex('X');
|
|
290
|
+
* graph.addVertex('Y');
|
|
291
|
+
* graph.addVertex('Z');
|
|
292
|
+
* graph.addEdge('X', 'Y', 1);
|
|
293
|
+
* graph.addEdge('Y', 'Z', 2);
|
|
294
|
+
* graph.addEdge('X', 'Z', 3);
|
|
295
|
+
*
|
|
296
|
+
* // Delete an edge
|
|
297
|
+
* graph.deleteEdge('X', 'Y');
|
|
298
|
+
* console.log(graph.hasEdge('X', 'Y')); // false;
|
|
299
|
+
*
|
|
300
|
+
* // Bidirectional deletion confirmed
|
|
301
|
+
* console.log(graph.hasEdge('Y', 'X')); // false;
|
|
302
|
+
*
|
|
303
|
+
* // Other edges should remain
|
|
304
|
+
* console.log(graph.hasEdge('Y', 'Z')); // true;
|
|
305
|
+
* console.log(graph.hasEdge('Z', 'Y')); // true;
|
|
306
|
+
*
|
|
307
|
+
* // Delete a vertex
|
|
308
|
+
* graph.deleteVertex('Y');
|
|
309
|
+
* console.log(graph.hasVertex('Y')); // false;
|
|
310
|
+
* console.log(graph.size); // 2;
|
|
393
311
|
*/
|
|
394
312
|
deleteEdge(edgeOrOneSideVertexKey: EO | VertexKey, otherSideVertexKey?: VertexKey): EO | undefined {
|
|
395
313
|
let oneSide: VO | undefined, otherSide: VO | undefined;
|
|
@@ -404,7 +322,6 @@ export class UndirectedGraph<
|
|
|
404
322
|
oneSide = this._getVertex(edgeOrOneSideVertexKey.endpoints[0]);
|
|
405
323
|
otherSide = this._getVertex(edgeOrOneSideVertexKey.endpoints[1]);
|
|
406
324
|
}
|
|
407
|
-
|
|
408
325
|
if (oneSide && otherSide) {
|
|
409
326
|
return this.deleteEdgeBetween(oneSide, otherSide);
|
|
410
327
|
} else {
|
|
@@ -417,53 +334,14 @@ export class UndirectedGraph<
|
|
|
417
334
|
* @param vertexOrKey - Vertex or key.
|
|
418
335
|
* @returns `true` if removed; otherwise `false`.
|
|
419
336
|
* @remarks Time O(deg), Space O(1)
|
|
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
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
* @example
|
|
460
|
-
* // Remove vertex and edges
|
|
461
|
-
* const g = new UndirectedGraph();
|
|
462
|
-
* g.addVertex('A');
|
|
463
|
-
* g.addVertex('B');
|
|
464
|
-
* g.addEdge('A', 'B');
|
|
465
|
-
* g.deleteVertex('A');
|
|
466
|
-
* console.log(g.hasVertex('A')); // false;
|
|
337
|
+
* @example
|
|
338
|
+
* // Remove vertex and edges
|
|
339
|
+
* const g = new UndirectedGraph();
|
|
340
|
+
* g.addVertex('A');
|
|
341
|
+
* g.addVertex('B');
|
|
342
|
+
* g.addEdge('A', 'B');
|
|
343
|
+
* g.deleteVertex('A');
|
|
344
|
+
* console.log(g.hasVertex('A')); // false;
|
|
467
345
|
*/
|
|
468
346
|
deleteVertex(vertexOrKey: VO | VertexKey): boolean {
|
|
469
347
|
let vertexKey: VertexKey;
|
|
@@ -483,7 +361,6 @@ export class UndirectedGraph<
|
|
|
483
361
|
* @remarks Time O(deg), Space O(deg)
|
|
484
362
|
*/
|
|
485
363
|
const neighbors = this.getNeighbors(vertexOrKey);
|
|
486
|
-
|
|
487
364
|
if (vertex) {
|
|
488
365
|
neighbors.forEach(neighbor => {
|
|
489
366
|
const neighborEdges = this._edgeMap.get(neighbor);
|
|
@@ -496,7 +373,6 @@ export class UndirectedGraph<
|
|
|
496
373
|
});
|
|
497
374
|
this._edgeMap.delete(vertex);
|
|
498
375
|
}
|
|
499
|
-
|
|
500
376
|
return this._vertexMap.delete(vertexKey);
|
|
501
377
|
}
|
|
502
378
|
|
|
@@ -534,52 +410,13 @@ export class UndirectedGraph<
|
|
|
534
410
|
* Unique set of undirected edges across endpoints.
|
|
535
411
|
* @returns Array of edges.
|
|
536
412
|
* @remarks Time O(E), Space O(E)
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
* @example
|
|
577
|
-
* // Get all edges
|
|
578
|
-
* const g = new UndirectedGraph();
|
|
579
|
-
* g.addVertex('A');
|
|
580
|
-
* g.addVertex('B');
|
|
581
|
-
* g.addEdge('A', 'B');
|
|
582
|
-
* console.log(g.edgeSet().length); // 1;
|
|
413
|
+
* @example
|
|
414
|
+
* // Get all edges
|
|
415
|
+
* const g = new UndirectedGraph();
|
|
416
|
+
* g.addVertex('A');
|
|
417
|
+
* g.addVertex('B');
|
|
418
|
+
* g.addEdge('A', 'B');
|
|
419
|
+
* console.log(g.edgeSet().length); // 1;
|
|
583
420
|
*/
|
|
584
421
|
edgeSet(): EO[] {
|
|
585
422
|
const edgeSet: Set<EO> = new Set();
|
|
@@ -591,82 +428,40 @@ export class UndirectedGraph<
|
|
|
591
428
|
return [...edgeSet];
|
|
592
429
|
}
|
|
593
430
|
|
|
594
|
-
|
|
431
|
+
/**
|
|
595
432
|
* UndirectedGraph connectivity and neighbors
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
* @example
|
|
639
|
-
* // UndirectedGraph connectivity and neighbors
|
|
640
|
-
* const graph = new UndirectedGraph<string>();
|
|
641
|
-
*
|
|
642
|
-
* // Build a friendship network
|
|
643
|
-
* const people = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'];
|
|
644
|
-
* for (const person of people) {
|
|
645
|
-
* graph.addVertex(person);
|
|
646
|
-
* }
|
|
647
|
-
*
|
|
648
|
-
* // Add friendships (undirected edges)
|
|
649
|
-
* graph.addEdge('Alice', 'Bob', 1);
|
|
650
|
-
* graph.addEdge('Alice', 'Charlie', 1);
|
|
651
|
-
* graph.addEdge('Bob', 'Diana', 1);
|
|
652
|
-
* graph.addEdge('Charlie', 'Eve', 1);
|
|
653
|
-
* graph.addEdge('Diana', 'Eve', 1);
|
|
654
|
-
*
|
|
655
|
-
* // Get friends of each person
|
|
656
|
-
* const aliceFriends = graph.getNeighbors('Alice');
|
|
657
|
-
* console.log(aliceFriends[0].key); // 'Bob';
|
|
658
|
-
* console.log(aliceFriends[1].key); // 'Charlie';
|
|
659
|
-
* console.log(aliceFriends.length); // 2;
|
|
660
|
-
*
|
|
661
|
-
* const dianaFriends = graph.getNeighbors('Diana');
|
|
662
|
-
* console.log(dianaFriends[0].key); // 'Bob';
|
|
663
|
-
* console.log(dianaFriends[1].key); // 'Eve';
|
|
664
|
-
* console.log(dianaFriends.length); // 2;
|
|
665
|
-
*
|
|
666
|
-
* // Verify bidirectional friendship
|
|
667
|
-
* const bobFriends = graph.getNeighbors('Bob');
|
|
668
|
-
* console.log(bobFriends[0].key); // 'Alice'; // Alice -> Bob -> Alice ✓
|
|
669
|
-
* console.log(bobFriends[1].key); // 'Diana';
|
|
433
|
+
* @example
|
|
434
|
+
* // UndirectedGraph connectivity and neighbors
|
|
435
|
+
* const graph = new UndirectedGraph<string>();
|
|
436
|
+
*
|
|
437
|
+
* // Build a friendship network
|
|
438
|
+
* const people = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'];
|
|
439
|
+
* for (const person of people) {
|
|
440
|
+
* graph.addVertex(person);
|
|
441
|
+
* }
|
|
442
|
+
*
|
|
443
|
+
* // Add friendships (undirected edges)
|
|
444
|
+
* graph.addEdge('Alice', 'Bob', 1);
|
|
445
|
+
* graph.addEdge('Alice', 'Charlie', 1);
|
|
446
|
+
* graph.addEdge('Bob', 'Diana', 1);
|
|
447
|
+
* graph.addEdge('Charlie', 'Eve', 1);
|
|
448
|
+
* graph.addEdge('Diana', 'Eve', 1);
|
|
449
|
+
*
|
|
450
|
+
* // Get friends of each person
|
|
451
|
+
* const aliceFriends = graph.getNeighbors('Alice');
|
|
452
|
+
* console.log(aliceFriends[0].key); // 'Bob';
|
|
453
|
+
* console.log(aliceFriends[1].key); // 'Charlie';
|
|
454
|
+
* console.log(aliceFriends.length); // 2;
|
|
455
|
+
*
|
|
456
|
+
* const dianaFriends = graph.getNeighbors('Diana');
|
|
457
|
+
* console.log(dianaFriends[0].key); // 'Bob';
|
|
458
|
+
* console.log(dianaFriends[1].key); // 'Eve';
|
|
459
|
+
* console.log(dianaFriends.length); // 2;
|
|
460
|
+
*
|
|
461
|
+
* // Verify bidirectional friendship
|
|
462
|
+
* const bobFriends = graph.getNeighbors('Bob');
|
|
463
|
+
* console.log(bobFriends[0].key); // 'Alice'; // Alice -> Bob -> Alice ✓
|
|
464
|
+
* console.log(bobFriends[1].key); // 'Diana';
|
|
670
465
|
*/
|
|
671
466
|
getNeighbors(vertexOrKey: VO | VertexKey): VO[] {
|
|
672
467
|
const neighbors: VO[] = [];
|
|
@@ -732,78 +527,34 @@ export class UndirectedGraph<
|
|
|
732
527
|
* Tarjan-based bridge and articulation point detection.
|
|
733
528
|
* @returns `{ dfnMap, lowMap, bridges, cutVertices }`.
|
|
734
529
|
* @remarks Time O(V + E), Space O(V + E)
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
* @example
|
|
775
|
-
* // Find articulation points and bridges
|
|
776
|
-
* const g = new UndirectedGraph();
|
|
777
|
-
* g.addVertex('A');
|
|
778
|
-
* g.addVertex('B');
|
|
779
|
-
* g.addVertex('C');
|
|
780
|
-
* g.addEdge('A', 'B');
|
|
781
|
-
* g.addEdge('B', 'C');
|
|
782
|
-
* const result = g.tarjan();
|
|
783
|
-
* console.log(result); // defined;
|
|
530
|
+
* @example
|
|
531
|
+
* // Find articulation points and bridges
|
|
532
|
+
* const g = new UndirectedGraph();
|
|
533
|
+
* g.addVertex('A');
|
|
534
|
+
* g.addVertex('B');
|
|
535
|
+
* g.addVertex('C');
|
|
536
|
+
* g.addEdge('A', 'B');
|
|
537
|
+
* g.addEdge('B', 'C');
|
|
538
|
+
* const result = g.tarjan();
|
|
539
|
+
* console.log(result); // defined;
|
|
784
540
|
*/
|
|
785
541
|
tarjan(): { dfnMap: Map<VO, number>; lowMap: Map<VO, number>; bridges: EO[]; cutVertices: VO[] } {
|
|
786
542
|
const dfnMap = new Map<VO, number>();
|
|
787
543
|
const lowMap = new Map<VO, number>();
|
|
788
544
|
const bridges: EO[] = [];
|
|
789
545
|
const cutVertices: VO[] = [];
|
|
790
|
-
|
|
791
546
|
let time = 0;
|
|
792
|
-
|
|
793
547
|
const dfs = (vertex: VO, parent: VO | undefined) => {
|
|
794
548
|
dfnMap.set(vertex, time);
|
|
795
549
|
lowMap.set(vertex, time);
|
|
796
550
|
time++;
|
|
797
|
-
|
|
798
551
|
const neighbors = this.getNeighbors(vertex);
|
|
799
552
|
let childCount = 0;
|
|
800
|
-
|
|
801
553
|
for (const neighbor of neighbors) {
|
|
802
554
|
if (!dfnMap.has(neighbor)) {
|
|
803
555
|
childCount++;
|
|
804
556
|
dfs(neighbor, vertex);
|
|
805
557
|
lowMap.set(vertex, Math.min(lowMap.get(vertex)!, lowMap.get(neighbor)!));
|
|
806
|
-
|
|
807
558
|
if (lowMap.get(neighbor)! > dfnMap.get(vertex)!) {
|
|
808
559
|
// Found a bridge
|
|
809
560
|
const edge = this.getEdge(vertex, neighbor);
|
|
@@ -811,7 +562,6 @@ export class UndirectedGraph<
|
|
|
811
562
|
bridges.push(edge);
|
|
812
563
|
}
|
|
813
564
|
}
|
|
814
|
-
|
|
815
565
|
if (parent !== undefined && lowMap.get(neighbor)! >= dfnMap.get(vertex)!) {
|
|
816
566
|
// Found an articulation point
|
|
817
567
|
cutVertices.push(vertex);
|
|
@@ -820,19 +570,16 @@ export class UndirectedGraph<
|
|
|
820
570
|
lowMap.set(vertex, Math.min(lowMap.get(vertex)!, dfnMap.get(neighbor)!));
|
|
821
571
|
}
|
|
822
572
|
}
|
|
823
|
-
|
|
824
573
|
if (parent === undefined && childCount > 1) {
|
|
825
574
|
// Special case for root in DFS tree
|
|
826
575
|
cutVertices.push(vertex);
|
|
827
576
|
}
|
|
828
577
|
};
|
|
829
|
-
|
|
830
578
|
for (const vertex of this.vertexMap.values()) {
|
|
831
579
|
if (!dfnMap.has(vertex)) {
|
|
832
580
|
dfs(vertex, undefined);
|
|
833
581
|
}
|
|
834
582
|
}
|
|
835
|
-
|
|
836
583
|
return {
|
|
837
584
|
dfnMap,
|
|
838
585
|
lowMap,
|
|
@@ -853,25 +600,20 @@ export class UndirectedGraph<
|
|
|
853
600
|
const edgeStack: EO[] = [];
|
|
854
601
|
const components: EO[][] = [];
|
|
855
602
|
let time = 0;
|
|
856
|
-
|
|
857
603
|
const dfs = (vertex: VO, parent: VO | undefined) => {
|
|
858
604
|
dfn.set(vertex, time);
|
|
859
605
|
low.set(vertex, time);
|
|
860
606
|
time++;
|
|
861
|
-
|
|
862
607
|
const neighbors = this.getNeighbors(vertex);
|
|
863
608
|
let childCount = 0;
|
|
864
|
-
|
|
865
609
|
for (const neighbor of neighbors) {
|
|
866
610
|
const edge = this.getEdge(vertex, neighbor);
|
|
867
611
|
if (!edge) continue;
|
|
868
|
-
|
|
869
612
|
if (!dfn.has(neighbor)) {
|
|
870
613
|
childCount++;
|
|
871
614
|
edgeStack.push(edge);
|
|
872
615
|
dfs(neighbor, vertex);
|
|
873
616
|
low.set(vertex, Math.min(low.get(vertex)!, low.get(neighbor)!));
|
|
874
|
-
|
|
875
617
|
// Articulation point found — pop edges to form a component
|
|
876
618
|
if (
|
|
877
619
|
(parent === undefined && childCount > 1) ||
|
|
@@ -892,7 +634,6 @@ export class UndirectedGraph<
|
|
|
892
634
|
}
|
|
893
635
|
}
|
|
894
636
|
};
|
|
895
|
-
|
|
896
637
|
for (const vertex of this.vertexMap.values()) {
|
|
897
638
|
if (!dfn.has(vertex)) {
|
|
898
639
|
dfs(vertex, undefined);
|
|
@@ -903,7 +644,6 @@ export class UndirectedGraph<
|
|
|
903
644
|
}
|
|
904
645
|
}
|
|
905
646
|
}
|
|
906
|
-
|
|
907
647
|
return components;
|
|
908
648
|
}
|
|
909
649
|
|
|
@@ -912,60 +652,20 @@ export class UndirectedGraph<
|
|
|
912
652
|
* Uses DFS with parent tracking.
|
|
913
653
|
* @returns `true` if a cycle exists, `false` otherwise.
|
|
914
654
|
* @remarks Time O(V + E), Space O(V)
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
* @example
|
|
955
|
-
* // Detect cycle
|
|
956
|
-
* const g = new UndirectedGraph();
|
|
957
|
-
* g.addVertex('A');
|
|
958
|
-
* g.addVertex('B');
|
|
959
|
-
* g.addVertex('C');
|
|
960
|
-
* g.addEdge('A', 'B');
|
|
961
|
-
* g.addEdge('B', 'C');
|
|
962
|
-
* console.log(g.hasCycle()); // false;
|
|
963
|
-
* g.addEdge('C', 'A');
|
|
964
|
-
* console.log(g.hasCycle()); // true;
|
|
655
|
+
* @example
|
|
656
|
+
* // Detect cycle
|
|
657
|
+
* const g = new UndirectedGraph();
|
|
658
|
+
* g.addVertex('A');
|
|
659
|
+
* g.addVertex('B');
|
|
660
|
+
* g.addVertex('C');
|
|
661
|
+
* g.addEdge('A', 'B');
|
|
662
|
+
* g.addEdge('B', 'C');
|
|
663
|
+
* console.log(g.hasCycle()); // false;
|
|
664
|
+
* g.addEdge('C', 'A');
|
|
665
|
+
* console.log(g.hasCycle()); // true;
|
|
965
666
|
*/
|
|
966
667
|
hasCycle(): boolean {
|
|
967
668
|
const visited = new Set<VO>();
|
|
968
|
-
|
|
969
669
|
const dfs = (vertex: VO, parent: VO | undefined): boolean => {
|
|
970
670
|
visited.add(vertex);
|
|
971
671
|
for (const neighbor of this.getNeighbors(vertex)) {
|
|
@@ -977,7 +677,6 @@ export class UndirectedGraph<
|
|
|
977
677
|
}
|
|
978
678
|
return false;
|
|
979
679
|
};
|
|
980
|
-
|
|
981
680
|
for (const vertex of this.vertexMap.values()) {
|
|
982
681
|
if (!visited.has(vertex)) {
|
|
983
682
|
if (dfs(vertex, undefined)) return true;
|
|
@@ -990,55 +689,16 @@ export class UndirectedGraph<
|
|
|
990
689
|
* Get bridges discovered by `tarjan()`.
|
|
991
690
|
* @returns Array of edges that are bridges.
|
|
992
691
|
* @remarks Time O(B), Space O(1)
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
* @example
|
|
1033
|
-
* // Find bridge edges
|
|
1034
|
-
* const g = new UndirectedGraph();
|
|
1035
|
-
* g.addVertex('A');
|
|
1036
|
-
* g.addVertex('B');
|
|
1037
|
-
* g.addVertex('C');
|
|
1038
|
-
* g.addEdge('A', 'B');
|
|
1039
|
-
* g.addEdge('B', 'C');
|
|
1040
|
-
* const bridges = g.getBridges();
|
|
1041
|
-
* console.log(bridges.length); // 2;
|
|
692
|
+
* @example
|
|
693
|
+
* // Find bridge edges
|
|
694
|
+
* const g = new UndirectedGraph();
|
|
695
|
+
* g.addVertex('A');
|
|
696
|
+
* g.addVertex('B');
|
|
697
|
+
* g.addVertex('C');
|
|
698
|
+
* g.addEdge('A', 'B');
|
|
699
|
+
* g.addEdge('B', 'C');
|
|
700
|
+
* const bridges = g.getBridges();
|
|
701
|
+
* console.log(bridges.length); // 2;
|
|
1042
702
|
*/
|
|
1043
703
|
getBridges() {
|
|
1044
704
|
return this.tarjan().bridges;
|
|
@@ -1048,56 +708,17 @@ export class UndirectedGraph<
|
|
|
1048
708
|
* Get articulation points discovered by `tarjan()`.
|
|
1049
709
|
* @returns Array of cut vertices.
|
|
1050
710
|
* @remarks Time O(C), Space O(1)
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
* @example
|
|
1091
|
-
* // Find articulation points
|
|
1092
|
-
* const g = new UndirectedGraph();
|
|
1093
|
-
* g.addVertex('A');
|
|
1094
|
-
* g.addVertex('B');
|
|
1095
|
-
* g.addVertex('C');
|
|
1096
|
-
* g.addEdge('A', 'B');
|
|
1097
|
-
* g.addEdge('B', 'C');
|
|
1098
|
-
* const cuts = g.getCutVertices();
|
|
1099
|
-
* console.log(cuts.length); // 1;
|
|
1100
|
-
* console.log(cuts[0].key); // 'B';
|
|
711
|
+
* @example
|
|
712
|
+
* // Find articulation points
|
|
713
|
+
* const g = new UndirectedGraph();
|
|
714
|
+
* g.addVertex('A');
|
|
715
|
+
* g.addVertex('B');
|
|
716
|
+
* g.addVertex('C');
|
|
717
|
+
* g.addEdge('A', 'B');
|
|
718
|
+
* g.addEdge('B', 'C');
|
|
719
|
+
* const cuts = g.getCutVertices();
|
|
720
|
+
* console.log(cuts.length); // 1;
|
|
721
|
+
* console.log(cuts[0].key); // 'B';
|
|
1101
722
|
*/
|
|
1102
723
|
getCutVertices() {
|
|
1103
724
|
return this.tarjan().cutVertices;
|