data-structure-typed 2.4.4 → 2.5.0
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/CHANGELOG.md +22 -1
- package/README.md +34 -1
- package/dist/cjs/index.cjs +10639 -2151
- package/dist/cjs-legacy/index.cjs +10694 -2195
- package/dist/esm/index.mjs +10639 -2150
- package/dist/esm-legacy/index.mjs +10694 -2194
- package/dist/types/common/error.d.ts +23 -0
- package/dist/types/common/index.d.ts +1 -0
- package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +128 -51
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +210 -164
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +439 -78
- package/dist/types/data-structures/binary-tree/bst.d.ts +311 -28
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +217 -31
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +218 -152
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +1281 -5
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1087 -201
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +858 -65
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +1133 -5
- package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
- package/dist/types/data-structures/graph/directed-graph.d.ts +220 -47
- package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +218 -59
- package/dist/types/data-structures/hash/hash-map.d.ts +230 -77
- package/dist/types/data-structures/heap/heap.d.ts +287 -99
- package/dist/types/data-structures/heap/max-heap.d.ts +46 -0
- package/dist/types/data-structures/heap/min-heap.d.ts +59 -0
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +286 -44
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +278 -65
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +415 -12
- package/dist/types/data-structures/matrix/matrix.d.ts +331 -0
- package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +57 -0
- package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +60 -0
- package/dist/types/data-structures/priority-queue/priority-queue.d.ts +60 -0
- package/dist/types/data-structures/queue/deque.d.ts +313 -66
- package/dist/types/data-structures/queue/queue.d.ts +211 -42
- package/dist/types/data-structures/stack/stack.d.ts +174 -32
- package/dist/types/data-structures/trie/trie.d.ts +213 -43
- package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
- package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
- package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
- package/dist/umd/data-structure-typed.js +10725 -2221
- package/dist/umd/data-structure-typed.min.js +4 -2
- package/package.json +5 -4
- package/src/common/error.ts +60 -0
- package/src/common/index.ts +2 -0
- package/src/data-structures/base/iterable-element-base.ts +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +146 -51
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +317 -247
- package/src/data-structures/binary-tree/binary-tree.ts +567 -121
- package/src/data-structures/binary-tree/bst.ts +370 -37
- package/src/data-structures/binary-tree/red-black-tree.ts +328 -96
- package/src/data-structures/binary-tree/segment-tree.ts +378 -248
- package/src/data-structures/binary-tree/tree-map.ts +1411 -13
- package/src/data-structures/binary-tree/tree-multi-map.ts +1218 -215
- package/src/data-structures/binary-tree/tree-multi-set.ts +959 -69
- package/src/data-structures/binary-tree/tree-set.ts +1257 -15
- package/src/data-structures/graph/abstract-graph.ts +106 -1
- package/src/data-structures/graph/directed-graph.ts +233 -47
- package/src/data-structures/graph/map-graph.ts +59 -1
- package/src/data-structures/graph/undirected-graph.ts +308 -59
- package/src/data-structures/hash/hash-map.ts +254 -79
- package/src/data-structures/heap/heap.ts +305 -102
- package/src/data-structures/heap/max-heap.ts +48 -3
- package/src/data-structures/heap/min-heap.ts +59 -0
- package/src/data-structures/linked-list/doubly-linked-list.ts +303 -44
- package/src/data-structures/linked-list/singly-linked-list.ts +293 -65
- package/src/data-structures/linked-list/skip-linked-list.ts +707 -90
- package/src/data-structures/matrix/matrix.ts +433 -22
- package/src/data-structures/priority-queue/max-priority-queue.ts +59 -3
- package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
- package/src/data-structures/priority-queue/priority-queue.ts +60 -0
- package/src/data-structures/queue/deque.ts +358 -68
- package/src/data-structures/queue/queue.ts +223 -42
- package/src/data-structures/stack/stack.ts +184 -32
- package/src/data-structures/trie/trie.ts +227 -44
- package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
- package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
- package/src/types/data-structures/queue/deque.ts +7 -0
- package/src/utils/utils.ts +4 -2
|
@@ -77,65 +77,6 @@ export class UndirectedEdge<E = number> extends AbstractEdge<E> {
|
|
|
77
77
|
* console.log(neighborsA[0].key); // 'B';
|
|
78
78
|
* console.log(neighborsA[1].key); // 'C';
|
|
79
79
|
* @example
|
|
80
|
-
* // UndirectedGraph deleteEdge and vertex operations
|
|
81
|
-
* const graph = new UndirectedGraph<string>();
|
|
82
|
-
*
|
|
83
|
-
* // Build a simple undirected graph
|
|
84
|
-
* graph.addVertex('X');
|
|
85
|
-
* graph.addVertex('Y');
|
|
86
|
-
* graph.addVertex('Z');
|
|
87
|
-
* graph.addEdge('X', 'Y', 1);
|
|
88
|
-
* graph.addEdge('Y', 'Z', 2);
|
|
89
|
-
* graph.addEdge('X', 'Z', 3);
|
|
90
|
-
*
|
|
91
|
-
* // Delete an edge
|
|
92
|
-
* graph.deleteEdge('X', 'Y');
|
|
93
|
-
* console.log(graph.hasEdge('X', 'Y')); // false;
|
|
94
|
-
*
|
|
95
|
-
* // Bidirectional deletion confirmed
|
|
96
|
-
* console.log(graph.hasEdge('Y', 'X')); // false;
|
|
97
|
-
*
|
|
98
|
-
* // Other edges should remain
|
|
99
|
-
* console.log(graph.hasEdge('Y', 'Z')); // true;
|
|
100
|
-
* console.log(graph.hasEdge('Z', 'Y')); // true;
|
|
101
|
-
*
|
|
102
|
-
* // Delete a vertex
|
|
103
|
-
* graph.deleteVertex('Y');
|
|
104
|
-
* console.log(graph.hasVertex('Y')); // false;
|
|
105
|
-
* console.log(graph.size); // 2;
|
|
106
|
-
* @example
|
|
107
|
-
* // UndirectedGraph connectivity and neighbors
|
|
108
|
-
* const graph = new UndirectedGraph<string>();
|
|
109
|
-
*
|
|
110
|
-
* // Build a friendship network
|
|
111
|
-
* const people = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'];
|
|
112
|
-
* for (const person of people) {
|
|
113
|
-
* graph.addVertex(person);
|
|
114
|
-
* }
|
|
115
|
-
*
|
|
116
|
-
* // Add friendships (undirected edges)
|
|
117
|
-
* graph.addEdge('Alice', 'Bob', 1);
|
|
118
|
-
* graph.addEdge('Alice', 'Charlie', 1);
|
|
119
|
-
* graph.addEdge('Bob', 'Diana', 1);
|
|
120
|
-
* graph.addEdge('Charlie', 'Eve', 1);
|
|
121
|
-
* graph.addEdge('Diana', 'Eve', 1);
|
|
122
|
-
*
|
|
123
|
-
* // Get friends of each person
|
|
124
|
-
* const aliceFriends = graph.getNeighbors('Alice');
|
|
125
|
-
* console.log(aliceFriends[0].key); // 'Bob';
|
|
126
|
-
* console.log(aliceFriends[1].key); // 'Charlie';
|
|
127
|
-
* console.log(aliceFriends.length); // 2;
|
|
128
|
-
*
|
|
129
|
-
* const dianaFriends = graph.getNeighbors('Diana');
|
|
130
|
-
* console.log(dianaFriends[0].key); // 'Bob';
|
|
131
|
-
* console.log(dianaFriends[1].key); // 'Eve';
|
|
132
|
-
* console.log(dianaFriends.length); // 2;
|
|
133
|
-
*
|
|
134
|
-
* // Verify bidirectional friendship
|
|
135
|
-
* const bobFriends = graph.getNeighbors('Bob');
|
|
136
|
-
* console.log(bobFriends[0].key); // 'Alice'; // Alice -> Bob -> Alice ✓
|
|
137
|
-
* console.log(bobFriends[1].key); // 'Diana';
|
|
138
|
-
* @example
|
|
139
80
|
* // UndirectedGraph for social network connectivity analysis
|
|
140
81
|
* interface Person {
|
|
141
82
|
* id: number;
|
|
@@ -285,6 +226,22 @@ export class UndirectedGraph<
|
|
|
285
226
|
* @param v2 - The other vertex or key.
|
|
286
227
|
* @returns Edge instance or `undefined`.
|
|
287
228
|
* @remarks Time O(1) avg, Space O(1)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
* @example
|
|
239
|
+
* // Get edge between vertices
|
|
240
|
+
* const g = new UndirectedGraph();
|
|
241
|
+
* g.addVertex('A');
|
|
242
|
+
* g.addVertex('B');
|
|
243
|
+
* g.addEdge('A', 'B', 7);
|
|
244
|
+
* console.log(g.getEdge('A', 'B')?.weight); // 7;
|
|
288
245
|
*/
|
|
289
246
|
getEdge(v1: VO | VertexKey | undefined, v2: VO | VertexKey | undefined): EO | undefined {
|
|
290
247
|
let edgeMap: EO[] | undefined = [];
|
|
@@ -334,6 +291,45 @@ export class UndirectedGraph<
|
|
|
334
291
|
* @param otherSideVertexKey - Required second endpoint when deleting by pair.
|
|
335
292
|
* @returns Removed edge or `undefined`.
|
|
336
293
|
* @remarks Time O(1) avg, Space O(1)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
* @example
|
|
307
|
+
* // UndirectedGraph deleteEdge and vertex operations
|
|
308
|
+
* const graph = new UndirectedGraph<string>();
|
|
309
|
+
*
|
|
310
|
+
* // Build a simple undirected graph
|
|
311
|
+
* graph.addVertex('X');
|
|
312
|
+
* graph.addVertex('Y');
|
|
313
|
+
* graph.addVertex('Z');
|
|
314
|
+
* graph.addEdge('X', 'Y', 1);
|
|
315
|
+
* graph.addEdge('Y', 'Z', 2);
|
|
316
|
+
* graph.addEdge('X', 'Z', 3);
|
|
317
|
+
*
|
|
318
|
+
* // Delete an edge
|
|
319
|
+
* graph.deleteEdge('X', 'Y');
|
|
320
|
+
* console.log(graph.hasEdge('X', 'Y')); // false;
|
|
321
|
+
*
|
|
322
|
+
* // Bidirectional deletion confirmed
|
|
323
|
+
* console.log(graph.hasEdge('Y', 'X')); // false;
|
|
324
|
+
*
|
|
325
|
+
* // Other edges should remain
|
|
326
|
+
* console.log(graph.hasEdge('Y', 'Z')); // true;
|
|
327
|
+
* console.log(graph.hasEdge('Z', 'Y')); // true;
|
|
328
|
+
*
|
|
329
|
+
* // Delete a vertex
|
|
330
|
+
* graph.deleteVertex('Y');
|
|
331
|
+
* console.log(graph.hasVertex('Y')); // false;
|
|
332
|
+
* console.log(graph.size); // 2;
|
|
337
333
|
*/
|
|
338
334
|
deleteEdge(edgeOrOneSideVertexKey: EO | VertexKey, otherSideVertexKey?: VertexKey): EO | undefined {
|
|
339
335
|
let oneSide: VO | undefined, otherSide: VO | undefined;
|
|
@@ -361,6 +357,23 @@ export class UndirectedGraph<
|
|
|
361
357
|
* @param vertexOrKey - Vertex or key.
|
|
362
358
|
* @returns `true` if removed; otherwise `false`.
|
|
363
359
|
* @remarks Time O(deg), Space O(1)
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
* @example
|
|
370
|
+
* // Remove vertex and edges
|
|
371
|
+
* const g = new UndirectedGraph();
|
|
372
|
+
* g.addVertex('A');
|
|
373
|
+
* g.addVertex('B');
|
|
374
|
+
* g.addEdge('A', 'B');
|
|
375
|
+
* g.deleteVertex('A');
|
|
376
|
+
* console.log(g.hasVertex('A')); // false;
|
|
364
377
|
*/
|
|
365
378
|
deleteVertex(vertexOrKey: VO | VertexKey): boolean {
|
|
366
379
|
let vertexKey: VertexKey;
|
|
@@ -431,6 +444,22 @@ export class UndirectedGraph<
|
|
|
431
444
|
* Unique set of undirected edges across endpoints.
|
|
432
445
|
* @returns Array of edges.
|
|
433
446
|
* @remarks Time O(E), Space O(E)
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
* @example
|
|
457
|
+
* // Get all edges
|
|
458
|
+
* const g = new UndirectedGraph();
|
|
459
|
+
* g.addVertex('A');
|
|
460
|
+
* g.addVertex('B');
|
|
461
|
+
* g.addEdge('A', 'B');
|
|
462
|
+
* console.log(g.edgeSet().length); // 1;
|
|
434
463
|
*/
|
|
435
464
|
edgeSet(): EO[] {
|
|
436
465
|
const edgeSet: Set<EO> = new Set();
|
|
@@ -442,6 +471,53 @@ export class UndirectedGraph<
|
|
|
442
471
|
return [...edgeSet];
|
|
443
472
|
}
|
|
444
473
|
|
|
474
|
+
/**
|
|
475
|
+
* UndirectedGraph connectivity and neighbors
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
* @example
|
|
489
|
+
* // UndirectedGraph connectivity and neighbors
|
|
490
|
+
* const graph = new UndirectedGraph<string>();
|
|
491
|
+
*
|
|
492
|
+
* // Build a friendship network
|
|
493
|
+
* const people = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'];
|
|
494
|
+
* for (const person of people) {
|
|
495
|
+
* graph.addVertex(person);
|
|
496
|
+
* }
|
|
497
|
+
*
|
|
498
|
+
* // Add friendships (undirected edges)
|
|
499
|
+
* graph.addEdge('Alice', 'Bob', 1);
|
|
500
|
+
* graph.addEdge('Alice', 'Charlie', 1);
|
|
501
|
+
* graph.addEdge('Bob', 'Diana', 1);
|
|
502
|
+
* graph.addEdge('Charlie', 'Eve', 1);
|
|
503
|
+
* graph.addEdge('Diana', 'Eve', 1);
|
|
504
|
+
*
|
|
505
|
+
* // Get friends of each person
|
|
506
|
+
* const aliceFriends = graph.getNeighbors('Alice');
|
|
507
|
+
* console.log(aliceFriends[0].key); // 'Bob';
|
|
508
|
+
* console.log(aliceFriends[1].key); // 'Charlie';
|
|
509
|
+
* console.log(aliceFriends.length); // 2;
|
|
510
|
+
*
|
|
511
|
+
* const dianaFriends = graph.getNeighbors('Diana');
|
|
512
|
+
* console.log(dianaFriends[0].key); // 'Bob';
|
|
513
|
+
* console.log(dianaFriends[1].key); // 'Eve';
|
|
514
|
+
* console.log(dianaFriends.length); // 2;
|
|
515
|
+
*
|
|
516
|
+
* // Verify bidirectional friendship
|
|
517
|
+
* const bobFriends = graph.getNeighbors('Bob');
|
|
518
|
+
* console.log(bobFriends[0].key); // 'Alice'; // Alice -> Bob -> Alice ✓
|
|
519
|
+
* console.log(bobFriends[1].key); // 'Diana';
|
|
520
|
+
*/
|
|
445
521
|
getNeighbors(vertexOrKey: VO | VertexKey): VO[] {
|
|
446
522
|
const neighbors: VO[] = [];
|
|
447
523
|
const vertex = this._getVertex(vertexOrKey);
|
|
@@ -506,6 +582,25 @@ export class UndirectedGraph<
|
|
|
506
582
|
* Tarjan-based bridge and articulation point detection.
|
|
507
583
|
* @returns `{ dfnMap, lowMap, bridges, cutVertices }`.
|
|
508
584
|
* @remarks Time O(V + E), Space O(V + E)
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
* @example
|
|
595
|
+
* // Find articulation points and bridges
|
|
596
|
+
* const g = new UndirectedGraph();
|
|
597
|
+
* g.addVertex('A');
|
|
598
|
+
* g.addVertex('B');
|
|
599
|
+
* g.addVertex('C');
|
|
600
|
+
* g.addEdge('A', 'B');
|
|
601
|
+
* g.addEdge('B', 'C');
|
|
602
|
+
* const result = g.tarjan();
|
|
603
|
+
* console.log(result); // defined;
|
|
509
604
|
*/
|
|
510
605
|
tarjan(): { dfnMap: Map<VO, number>; lowMap: Map<VO, number>; bridges: EO[]; cutVertices: VO[] } {
|
|
511
606
|
const dfnMap = new Map<VO, number>();
|
|
@@ -566,10 +661,144 @@ export class UndirectedGraph<
|
|
|
566
661
|
};
|
|
567
662
|
}
|
|
568
663
|
|
|
664
|
+
/**
|
|
665
|
+
* Find biconnected components using edge-stack Tarjan variant.
|
|
666
|
+
* A biconnected component is a maximal biconnected subgraph.
|
|
667
|
+
* @returns Array of edge arrays, each representing a biconnected component.
|
|
668
|
+
* @remarks Time O(V + E), Space O(V + E)
|
|
669
|
+
*/
|
|
670
|
+
getBiconnectedComponents(): EO[][] {
|
|
671
|
+
const dfn = new Map<VO, number>();
|
|
672
|
+
const low = new Map<VO, number>();
|
|
673
|
+
const edgeStack: EO[] = [];
|
|
674
|
+
const components: EO[][] = [];
|
|
675
|
+
let time = 0;
|
|
676
|
+
|
|
677
|
+
const dfs = (vertex: VO, parent: VO | undefined) => {
|
|
678
|
+
dfn.set(vertex, time);
|
|
679
|
+
low.set(vertex, time);
|
|
680
|
+
time++;
|
|
681
|
+
|
|
682
|
+
const neighbors = this.getNeighbors(vertex);
|
|
683
|
+
let childCount = 0;
|
|
684
|
+
|
|
685
|
+
for (const neighbor of neighbors) {
|
|
686
|
+
const edge = this.getEdge(vertex, neighbor);
|
|
687
|
+
if (!edge) continue;
|
|
688
|
+
|
|
689
|
+
if (!dfn.has(neighbor)) {
|
|
690
|
+
childCount++;
|
|
691
|
+
edgeStack.push(edge);
|
|
692
|
+
dfs(neighbor, vertex);
|
|
693
|
+
low.set(vertex, Math.min(low.get(vertex)!, low.get(neighbor)!));
|
|
694
|
+
|
|
695
|
+
// Articulation point found — pop edges to form a component
|
|
696
|
+
if (
|
|
697
|
+
(parent === undefined && childCount > 1) ||
|
|
698
|
+
(parent !== undefined && low.get(neighbor)! >= dfn.get(vertex)!)
|
|
699
|
+
) {
|
|
700
|
+
const component: EO[] = [];
|
|
701
|
+
let e: EO | undefined;
|
|
702
|
+
do {
|
|
703
|
+
e = edgeStack.pop();
|
|
704
|
+
if (e) component.push(e);
|
|
705
|
+
} while (e && e !== edge);
|
|
706
|
+
if (component.length > 0) components.push(component);
|
|
707
|
+
}
|
|
708
|
+
} else if (neighbor !== parent && dfn.get(neighbor)! < dfn.get(vertex)!) {
|
|
709
|
+
// Back edge (only push once per undirected edge)
|
|
710
|
+
edgeStack.push(edge);
|
|
711
|
+
low.set(vertex, Math.min(low.get(vertex)!, dfn.get(neighbor)!));
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
};
|
|
715
|
+
|
|
716
|
+
for (const vertex of this.vertexMap.values()) {
|
|
717
|
+
if (!dfn.has(vertex)) {
|
|
718
|
+
dfs(vertex, undefined);
|
|
719
|
+
// Remaining edges form a component
|
|
720
|
+
if (edgeStack.length > 0) {
|
|
721
|
+
components.push([...edgeStack]);
|
|
722
|
+
edgeStack.length = 0;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
return components;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* Detect whether the graph contains a cycle.
|
|
732
|
+
* Uses DFS with parent tracking.
|
|
733
|
+
* @returns `true` if a cycle exists, `false` otherwise.
|
|
734
|
+
* @remarks Time O(V + E), Space O(V)
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
* @example
|
|
745
|
+
* // Detect cycle
|
|
746
|
+
* const g = new UndirectedGraph();
|
|
747
|
+
* g.addVertex('A');
|
|
748
|
+
* g.addVertex('B');
|
|
749
|
+
* g.addVertex('C');
|
|
750
|
+
* g.addEdge('A', 'B');
|
|
751
|
+
* g.addEdge('B', 'C');
|
|
752
|
+
* console.log(g.hasCycle()); // false;
|
|
753
|
+
* g.addEdge('C', 'A');
|
|
754
|
+
* console.log(g.hasCycle()); // true;
|
|
755
|
+
*/
|
|
756
|
+
hasCycle(): boolean {
|
|
757
|
+
const visited = new Set<VO>();
|
|
758
|
+
|
|
759
|
+
const dfs = (vertex: VO, parent: VO | undefined): boolean => {
|
|
760
|
+
visited.add(vertex);
|
|
761
|
+
for (const neighbor of this.getNeighbors(vertex)) {
|
|
762
|
+
if (!visited.has(neighbor)) {
|
|
763
|
+
if (dfs(neighbor, vertex)) return true;
|
|
764
|
+
} else if (neighbor !== parent) {
|
|
765
|
+
return true; // back edge = cycle
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
return false;
|
|
769
|
+
};
|
|
770
|
+
|
|
771
|
+
for (const vertex of this.vertexMap.values()) {
|
|
772
|
+
if (!visited.has(vertex)) {
|
|
773
|
+
if (dfs(vertex, undefined)) return true;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
return false;
|
|
777
|
+
}
|
|
778
|
+
|
|
569
779
|
/**
|
|
570
780
|
* Get bridges discovered by `tarjan()`.
|
|
571
781
|
* @returns Array of edges that are bridges.
|
|
572
782
|
* @remarks Time O(B), Space O(1)
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
|
|
789
|
+
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
* @example
|
|
793
|
+
* // Find bridge edges
|
|
794
|
+
* const g = new UndirectedGraph();
|
|
795
|
+
* g.addVertex('A');
|
|
796
|
+
* g.addVertex('B');
|
|
797
|
+
* g.addVertex('C');
|
|
798
|
+
* g.addEdge('A', 'B');
|
|
799
|
+
* g.addEdge('B', 'C');
|
|
800
|
+
* const bridges = g.getBridges();
|
|
801
|
+
* console.log(bridges.length); // 2;
|
|
573
802
|
*/
|
|
574
803
|
getBridges() {
|
|
575
804
|
return this.tarjan().bridges;
|
|
@@ -579,6 +808,26 @@ export class UndirectedGraph<
|
|
|
579
808
|
* Get articulation points discovered by `tarjan()`.
|
|
580
809
|
* @returns Array of cut vertices.
|
|
581
810
|
* @remarks Time O(C), Space O(1)
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
|
|
814
|
+
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
|
|
818
|
+
|
|
819
|
+
|
|
820
|
+
* @example
|
|
821
|
+
* // Find articulation points
|
|
822
|
+
* const g = new UndirectedGraph();
|
|
823
|
+
* g.addVertex('A');
|
|
824
|
+
* g.addVertex('B');
|
|
825
|
+
* g.addVertex('C');
|
|
826
|
+
* g.addEdge('A', 'B');
|
|
827
|
+
* g.addEdge('B', 'C');
|
|
828
|
+
* const cuts = g.getCutVertices();
|
|
829
|
+
* console.log(cuts.length); // 1;
|
|
830
|
+
* console.log(cuts[0].key); // 'B';
|
|
582
831
|
*/
|
|
583
832
|
getCutVertices() {
|
|
584
833
|
return this.tarjan().cutVertices;
|