binary-tree-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/README.md +0 -84
- package/dist/cjs/index.cjs +965 -420
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +962 -417
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +965 -421
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +962 -418
- package/dist/esm-legacy/index.mjs.map +1 -1
- 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/binary-tree-typed.js +959 -414
- package/dist/umd/binary-tree-typed.js.map +1 -1
- package/dist/umd/binary-tree-typed.min.js +3 -3
- package/dist/umd/binary-tree-typed.min.js.map +1 -1
- package/package.json +2 -2
- 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 +134 -51
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +303 -247
- package/src/data-structures/binary-tree/binary-tree.ts +542 -121
- package/src/data-structures/binary-tree/bst.ts +346 -37
- package/src/data-structures/binary-tree/red-black-tree.ts +309 -96
- package/src/data-structures/binary-tree/segment-tree.ts +372 -248
- package/src/data-structures/binary-tree/tree-map.ts +1292 -13
- package/src/data-structures/binary-tree/tree-multi-map.ts +1098 -215
- package/src/data-structures/binary-tree/tree-multi-set.ts +863 -69
- package/src/data-structures/binary-tree/tree-set.ts +1143 -15
- package/src/data-structures/graph/abstract-graph.ts +106 -1
- package/src/data-structures/graph/directed-graph.ts +223 -47
- package/src/data-structures/graph/map-graph.ts +59 -1
- package/src/data-structures/graph/undirected-graph.ts +299 -59
- package/src/data-structures/hash/hash-map.ts +243 -79
- package/src/data-structures/heap/heap.ts +291 -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 +286 -44
- package/src/data-structures/linked-list/singly-linked-list.ts +278 -65
- package/src/data-structures/linked-list/skip-linked-list.ts +689 -90
- package/src/data-structures/matrix/matrix.ts +425 -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 +343 -68
- package/src/data-structures/queue/queue.ts +211 -42
- package/src/data-structures/stack/stack.ts +174 -32
- package/src/data-structures/trie/trie.ts +215 -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,21 @@ 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
|
+
* @example
|
|
238
|
+
* // Get edge between vertices
|
|
239
|
+
* const g = new UndirectedGraph();
|
|
240
|
+
* g.addVertex('A');
|
|
241
|
+
* g.addVertex('B');
|
|
242
|
+
* g.addEdge('A', 'B', 7);
|
|
243
|
+
* console.log(g.getEdge('A', 'B')?.weight); // 7;
|
|
288
244
|
*/
|
|
289
245
|
getEdge(v1: VO | VertexKey | undefined, v2: VO | VertexKey | undefined): EO | undefined {
|
|
290
246
|
let edgeMap: EO[] | undefined = [];
|
|
@@ -334,6 +290,44 @@ export class UndirectedGraph<
|
|
|
334
290
|
* @param otherSideVertexKey - Required second endpoint when deleting by pair.
|
|
335
291
|
* @returns Removed edge or `undefined`.
|
|
336
292
|
* @remarks Time O(1) avg, Space O(1)
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
* @example
|
|
305
|
+
* // UndirectedGraph deleteEdge and vertex operations
|
|
306
|
+
* const graph = new UndirectedGraph<string>();
|
|
307
|
+
*
|
|
308
|
+
* // Build a simple undirected graph
|
|
309
|
+
* graph.addVertex('X');
|
|
310
|
+
* graph.addVertex('Y');
|
|
311
|
+
* graph.addVertex('Z');
|
|
312
|
+
* graph.addEdge('X', 'Y', 1);
|
|
313
|
+
* graph.addEdge('Y', 'Z', 2);
|
|
314
|
+
* graph.addEdge('X', 'Z', 3);
|
|
315
|
+
*
|
|
316
|
+
* // Delete an edge
|
|
317
|
+
* graph.deleteEdge('X', 'Y');
|
|
318
|
+
* console.log(graph.hasEdge('X', 'Y')); // false;
|
|
319
|
+
*
|
|
320
|
+
* // Bidirectional deletion confirmed
|
|
321
|
+
* console.log(graph.hasEdge('Y', 'X')); // false;
|
|
322
|
+
*
|
|
323
|
+
* // Other edges should remain
|
|
324
|
+
* console.log(graph.hasEdge('Y', 'Z')); // true;
|
|
325
|
+
* console.log(graph.hasEdge('Z', 'Y')); // true;
|
|
326
|
+
*
|
|
327
|
+
* // Delete a vertex
|
|
328
|
+
* graph.deleteVertex('Y');
|
|
329
|
+
* console.log(graph.hasVertex('Y')); // false;
|
|
330
|
+
* console.log(graph.size); // 2;
|
|
337
331
|
*/
|
|
338
332
|
deleteEdge(edgeOrOneSideVertexKey: EO | VertexKey, otherSideVertexKey?: VertexKey): EO | undefined {
|
|
339
333
|
let oneSide: VO | undefined, otherSide: VO | undefined;
|
|
@@ -361,6 +355,22 @@ export class UndirectedGraph<
|
|
|
361
355
|
* @param vertexOrKey - Vertex or key.
|
|
362
356
|
* @returns `true` if removed; otherwise `false`.
|
|
363
357
|
* @remarks Time O(deg), Space O(1)
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
* @example
|
|
367
|
+
* // Remove vertex and edges
|
|
368
|
+
* const g = new UndirectedGraph();
|
|
369
|
+
* g.addVertex('A');
|
|
370
|
+
* g.addVertex('B');
|
|
371
|
+
* g.addEdge('A', 'B');
|
|
372
|
+
* g.deleteVertex('A');
|
|
373
|
+
* console.log(g.hasVertex('A')); // false;
|
|
364
374
|
*/
|
|
365
375
|
deleteVertex(vertexOrKey: VO | VertexKey): boolean {
|
|
366
376
|
let vertexKey: VertexKey;
|
|
@@ -431,6 +441,21 @@ export class UndirectedGraph<
|
|
|
431
441
|
* Unique set of undirected edges across endpoints.
|
|
432
442
|
* @returns Array of edges.
|
|
433
443
|
* @remarks Time O(E), Space O(E)
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
* @example
|
|
453
|
+
* // Get all edges
|
|
454
|
+
* const g = new UndirectedGraph();
|
|
455
|
+
* g.addVertex('A');
|
|
456
|
+
* g.addVertex('B');
|
|
457
|
+
* g.addEdge('A', 'B');
|
|
458
|
+
* console.log(g.edgeSet().length); // 1;
|
|
434
459
|
*/
|
|
435
460
|
edgeSet(): EO[] {
|
|
436
461
|
const edgeSet: Set<EO> = new Set();
|
|
@@ -442,6 +467,52 @@ export class UndirectedGraph<
|
|
|
442
467
|
return [...edgeSet];
|
|
443
468
|
}
|
|
444
469
|
|
|
470
|
+
/**
|
|
471
|
+
* UndirectedGraph connectivity and neighbors
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
* @example
|
|
484
|
+
* // UndirectedGraph connectivity and neighbors
|
|
485
|
+
* const graph = new UndirectedGraph<string>();
|
|
486
|
+
*
|
|
487
|
+
* // Build a friendship network
|
|
488
|
+
* const people = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'];
|
|
489
|
+
* for (const person of people) {
|
|
490
|
+
* graph.addVertex(person);
|
|
491
|
+
* }
|
|
492
|
+
*
|
|
493
|
+
* // Add friendships (undirected edges)
|
|
494
|
+
* graph.addEdge('Alice', 'Bob', 1);
|
|
495
|
+
* graph.addEdge('Alice', 'Charlie', 1);
|
|
496
|
+
* graph.addEdge('Bob', 'Diana', 1);
|
|
497
|
+
* graph.addEdge('Charlie', 'Eve', 1);
|
|
498
|
+
* graph.addEdge('Diana', 'Eve', 1);
|
|
499
|
+
*
|
|
500
|
+
* // Get friends of each person
|
|
501
|
+
* const aliceFriends = graph.getNeighbors('Alice');
|
|
502
|
+
* console.log(aliceFriends[0].key); // 'Bob';
|
|
503
|
+
* console.log(aliceFriends[1].key); // 'Charlie';
|
|
504
|
+
* console.log(aliceFriends.length); // 2;
|
|
505
|
+
*
|
|
506
|
+
* const dianaFriends = graph.getNeighbors('Diana');
|
|
507
|
+
* console.log(dianaFriends[0].key); // 'Bob';
|
|
508
|
+
* console.log(dianaFriends[1].key); // 'Eve';
|
|
509
|
+
* console.log(dianaFriends.length); // 2;
|
|
510
|
+
*
|
|
511
|
+
* // Verify bidirectional friendship
|
|
512
|
+
* const bobFriends = graph.getNeighbors('Bob');
|
|
513
|
+
* console.log(bobFriends[0].key); // 'Alice'; // Alice -> Bob -> Alice ✓
|
|
514
|
+
* console.log(bobFriends[1].key); // 'Diana';
|
|
515
|
+
*/
|
|
445
516
|
getNeighbors(vertexOrKey: VO | VertexKey): VO[] {
|
|
446
517
|
const neighbors: VO[] = [];
|
|
447
518
|
const vertex = this._getVertex(vertexOrKey);
|
|
@@ -506,6 +577,24 @@ export class UndirectedGraph<
|
|
|
506
577
|
* Tarjan-based bridge and articulation point detection.
|
|
507
578
|
* @returns `{ dfnMap, lowMap, bridges, cutVertices }`.
|
|
508
579
|
* @remarks Time O(V + E), Space O(V + E)
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
* @example
|
|
589
|
+
* // Find articulation points and bridges
|
|
590
|
+
* const g = new UndirectedGraph();
|
|
591
|
+
* g.addVertex('A');
|
|
592
|
+
* g.addVertex('B');
|
|
593
|
+
* g.addVertex('C');
|
|
594
|
+
* g.addEdge('A', 'B');
|
|
595
|
+
* g.addEdge('B', 'C');
|
|
596
|
+
* const result = g.tarjan();
|
|
597
|
+
* console.log(result); // defined;
|
|
509
598
|
*/
|
|
510
599
|
tarjan(): { dfnMap: Map<VO, number>; lowMap: Map<VO, number>; bridges: EO[]; cutVertices: VO[] } {
|
|
511
600
|
const dfnMap = new Map<VO, number>();
|
|
@@ -566,10 +655,142 @@ export class UndirectedGraph<
|
|
|
566
655
|
};
|
|
567
656
|
}
|
|
568
657
|
|
|
658
|
+
/**
|
|
659
|
+
* Find biconnected components using edge-stack Tarjan variant.
|
|
660
|
+
* A biconnected component is a maximal biconnected subgraph.
|
|
661
|
+
* @returns Array of edge arrays, each representing a biconnected component.
|
|
662
|
+
* @remarks Time O(V + E), Space O(V + E)
|
|
663
|
+
*/
|
|
664
|
+
getBiconnectedComponents(): EO[][] {
|
|
665
|
+
const dfn = new Map<VO, number>();
|
|
666
|
+
const low = new Map<VO, number>();
|
|
667
|
+
const edgeStack: EO[] = [];
|
|
668
|
+
const components: EO[][] = [];
|
|
669
|
+
let time = 0;
|
|
670
|
+
|
|
671
|
+
const dfs = (vertex: VO, parent: VO | undefined) => {
|
|
672
|
+
dfn.set(vertex, time);
|
|
673
|
+
low.set(vertex, time);
|
|
674
|
+
time++;
|
|
675
|
+
|
|
676
|
+
const neighbors = this.getNeighbors(vertex);
|
|
677
|
+
let childCount = 0;
|
|
678
|
+
|
|
679
|
+
for (const neighbor of neighbors) {
|
|
680
|
+
const edge = this.getEdge(vertex, neighbor);
|
|
681
|
+
if (!edge) continue;
|
|
682
|
+
|
|
683
|
+
if (!dfn.has(neighbor)) {
|
|
684
|
+
childCount++;
|
|
685
|
+
edgeStack.push(edge);
|
|
686
|
+
dfs(neighbor, vertex);
|
|
687
|
+
low.set(vertex, Math.min(low.get(vertex)!, low.get(neighbor)!));
|
|
688
|
+
|
|
689
|
+
// Articulation point found — pop edges to form a component
|
|
690
|
+
if (
|
|
691
|
+
(parent === undefined && childCount > 1) ||
|
|
692
|
+
(parent !== undefined && low.get(neighbor)! >= dfn.get(vertex)!)
|
|
693
|
+
) {
|
|
694
|
+
const component: EO[] = [];
|
|
695
|
+
let e: EO | undefined;
|
|
696
|
+
do {
|
|
697
|
+
e = edgeStack.pop();
|
|
698
|
+
if (e) component.push(e);
|
|
699
|
+
} while (e && e !== edge);
|
|
700
|
+
if (component.length > 0) components.push(component);
|
|
701
|
+
}
|
|
702
|
+
} else if (neighbor !== parent && dfn.get(neighbor)! < dfn.get(vertex)!) {
|
|
703
|
+
// Back edge (only push once per undirected edge)
|
|
704
|
+
edgeStack.push(edge);
|
|
705
|
+
low.set(vertex, Math.min(low.get(vertex)!, dfn.get(neighbor)!));
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
};
|
|
709
|
+
|
|
710
|
+
for (const vertex of this.vertexMap.values()) {
|
|
711
|
+
if (!dfn.has(vertex)) {
|
|
712
|
+
dfs(vertex, undefined);
|
|
713
|
+
// Remaining edges form a component
|
|
714
|
+
if (edgeStack.length > 0) {
|
|
715
|
+
components.push([...edgeStack]);
|
|
716
|
+
edgeStack.length = 0;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
return components;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Detect whether the graph contains a cycle.
|
|
726
|
+
* Uses DFS with parent tracking.
|
|
727
|
+
* @returns `true` if a cycle exists, `false` otherwise.
|
|
728
|
+
* @remarks Time O(V + E), Space O(V)
|
|
729
|
+
|
|
730
|
+
|
|
731
|
+
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
* @example
|
|
738
|
+
* // Detect cycle
|
|
739
|
+
* const g = new UndirectedGraph();
|
|
740
|
+
* g.addVertex('A');
|
|
741
|
+
* g.addVertex('B');
|
|
742
|
+
* g.addVertex('C');
|
|
743
|
+
* g.addEdge('A', 'B');
|
|
744
|
+
* g.addEdge('B', 'C');
|
|
745
|
+
* console.log(g.hasCycle()); // false;
|
|
746
|
+
* g.addEdge('C', 'A');
|
|
747
|
+
* console.log(g.hasCycle()); // true;
|
|
748
|
+
*/
|
|
749
|
+
hasCycle(): boolean {
|
|
750
|
+
const visited = new Set<VO>();
|
|
751
|
+
|
|
752
|
+
const dfs = (vertex: VO, parent: VO | undefined): boolean => {
|
|
753
|
+
visited.add(vertex);
|
|
754
|
+
for (const neighbor of this.getNeighbors(vertex)) {
|
|
755
|
+
if (!visited.has(neighbor)) {
|
|
756
|
+
if (dfs(neighbor, vertex)) return true;
|
|
757
|
+
} else if (neighbor !== parent) {
|
|
758
|
+
return true; // back edge = cycle
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
return false;
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
for (const vertex of this.vertexMap.values()) {
|
|
765
|
+
if (!visited.has(vertex)) {
|
|
766
|
+
if (dfs(vertex, undefined)) return true;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
return false;
|
|
770
|
+
}
|
|
771
|
+
|
|
569
772
|
/**
|
|
570
773
|
* Get bridges discovered by `tarjan()`.
|
|
571
774
|
* @returns Array of edges that are bridges.
|
|
572
775
|
* @remarks Time O(B), Space O(1)
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
|
|
784
|
+
* @example
|
|
785
|
+
* // Find bridge edges
|
|
786
|
+
* const g = new UndirectedGraph();
|
|
787
|
+
* g.addVertex('A');
|
|
788
|
+
* g.addVertex('B');
|
|
789
|
+
* g.addVertex('C');
|
|
790
|
+
* g.addEdge('A', 'B');
|
|
791
|
+
* g.addEdge('B', 'C');
|
|
792
|
+
* const bridges = g.getBridges();
|
|
793
|
+
* console.log(bridges.length); // 2;
|
|
573
794
|
*/
|
|
574
795
|
getBridges() {
|
|
575
796
|
return this.tarjan().bridges;
|
|
@@ -579,6 +800,25 @@ export class UndirectedGraph<
|
|
|
579
800
|
* Get articulation points discovered by `tarjan()`.
|
|
580
801
|
* @returns Array of cut vertices.
|
|
581
802
|
* @remarks Time O(C), Space O(1)
|
|
803
|
+
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
|
|
809
|
+
|
|
810
|
+
|
|
811
|
+
* @example
|
|
812
|
+
* // Find articulation points
|
|
813
|
+
* const g = new UndirectedGraph();
|
|
814
|
+
* g.addVertex('A');
|
|
815
|
+
* g.addVertex('B');
|
|
816
|
+
* g.addVertex('C');
|
|
817
|
+
* g.addEdge('A', 'B');
|
|
818
|
+
* g.addEdge('B', 'C');
|
|
819
|
+
* const cuts = g.getCutVertices();
|
|
820
|
+
* console.log(cuts.length); // 1;
|
|
821
|
+
* console.log(cuts[0].key); // 'B';
|
|
582
822
|
*/
|
|
583
823
|
getCutVertices() {
|
|
584
824
|
return this.tarjan().cutVertices;
|