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, 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,62 +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
|
-
* @example
|
|
266
|
-
* // Get edge between vertices
|
|
267
|
-
* const g = new UndirectedGraph();
|
|
268
|
-
* g.addVertex('A');
|
|
269
|
-
* g.addVertex('B');
|
|
270
|
-
* g.addEdge('A', 'B', 7);
|
|
271
|
-
* 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;
|
|
272
240
|
*/
|
|
273
241
|
getEdge(v1: VO | VertexKey | undefined, v2: VO | VertexKey | undefined): EO | undefined {
|
|
274
242
|
let edgeMap: EO[] | undefined = [];
|
|
275
|
-
|
|
276
243
|
if (v1 !== undefined && v2 !== undefined) {
|
|
277
244
|
const vertex1: VO | undefined = this._getVertex(v1);
|
|
278
245
|
const vertex2: VO | undefined = this._getVertex(v2);
|
|
279
|
-
|
|
280
246
|
if (vertex1 && vertex2) {
|
|
281
247
|
edgeMap = this._edgeMap.get(vertex1)?.filter(e => e.endpoints.includes(vertex2.key));
|
|
282
248
|
}
|
|
283
249
|
}
|
|
284
|
-
|
|
285
250
|
return edgeMap ? edgeMap[0] || undefined : undefined;
|
|
286
251
|
}
|
|
287
252
|
|
|
@@ -295,11 +260,9 @@ export class UndirectedGraph<
|
|
|
295
260
|
deleteEdgeBetween(v1: VO | VertexKey, v2: VO | VertexKey): EO | undefined {
|
|
296
261
|
const vertex1: VO | undefined = this._getVertex(v1);
|
|
297
262
|
const vertex2: VO | undefined = this._getVertex(v2);
|
|
298
|
-
|
|
299
263
|
if (!vertex1 || !vertex2) {
|
|
300
264
|
return undefined;
|
|
301
265
|
}
|
|
302
|
-
|
|
303
266
|
const v1Edges = this._edgeMap.get(vertex1);
|
|
304
267
|
let removed: EO | undefined = undefined;
|
|
305
268
|
if (v1Edges) {
|
|
@@ -318,72 +281,33 @@ export class UndirectedGraph<
|
|
|
318
281
|
* @param otherSideVertexKey - Required second endpoint when deleting by pair.
|
|
319
282
|
* @returns Removed edge or `undefined`.
|
|
320
283
|
* @remarks Time O(1) avg, Space O(1)
|
|
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
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
* @example
|
|
361
|
-
* // UndirectedGraph deleteEdge and vertex operations
|
|
362
|
-
* const graph = new UndirectedGraph<string>();
|
|
363
|
-
*
|
|
364
|
-
* // Build a simple undirected graph
|
|
365
|
-
* graph.addVertex('X');
|
|
366
|
-
* graph.addVertex('Y');
|
|
367
|
-
* graph.addVertex('Z');
|
|
368
|
-
* graph.addEdge('X', 'Y', 1);
|
|
369
|
-
* graph.addEdge('Y', 'Z', 2);
|
|
370
|
-
* graph.addEdge('X', 'Z', 3);
|
|
371
|
-
*
|
|
372
|
-
* // Delete an edge
|
|
373
|
-
* graph.deleteEdge('X', 'Y');
|
|
374
|
-
* console.log(graph.hasEdge('X', 'Y')); // false;
|
|
375
|
-
*
|
|
376
|
-
* // Bidirectional deletion confirmed
|
|
377
|
-
* console.log(graph.hasEdge('Y', 'X')); // false;
|
|
378
|
-
*
|
|
379
|
-
* // Other edges should remain
|
|
380
|
-
* console.log(graph.hasEdge('Y', 'Z')); // true;
|
|
381
|
-
* console.log(graph.hasEdge('Z', 'Y')); // true;
|
|
382
|
-
*
|
|
383
|
-
* // Delete a vertex
|
|
384
|
-
* graph.deleteVertex('Y');
|
|
385
|
-
* console.log(graph.hasVertex('Y')); // false;
|
|
386
|
-
* 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;
|
|
387
311
|
*/
|
|
388
312
|
deleteEdge(edgeOrOneSideVertexKey: EO | VertexKey, otherSideVertexKey?: VertexKey): EO | undefined {
|
|
389
313
|
let oneSide: VO | undefined, otherSide: VO | undefined;
|
|
@@ -398,7 +322,6 @@ export class UndirectedGraph<
|
|
|
398
322
|
oneSide = this._getVertex(edgeOrOneSideVertexKey.endpoints[0]);
|
|
399
323
|
otherSide = this._getVertex(edgeOrOneSideVertexKey.endpoints[1]);
|
|
400
324
|
}
|
|
401
|
-
|
|
402
325
|
if (oneSide && otherSide) {
|
|
403
326
|
return this.deleteEdgeBetween(oneSide, otherSide);
|
|
404
327
|
} else {
|
|
@@ -411,50 +334,14 @@ export class UndirectedGraph<
|
|
|
411
334
|
* @param vertexOrKey - Vertex or key.
|
|
412
335
|
* @returns `true` if removed; otherwise `false`.
|
|
413
336
|
* @remarks Time O(deg), Space O(1)
|
|
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
|
-
|
|
450
|
-
* @example
|
|
451
|
-
* // Remove vertex and edges
|
|
452
|
-
* const g = new UndirectedGraph();
|
|
453
|
-
* g.addVertex('A');
|
|
454
|
-
* g.addVertex('B');
|
|
455
|
-
* g.addEdge('A', 'B');
|
|
456
|
-
* g.deleteVertex('A');
|
|
457
|
-
* 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;
|
|
458
345
|
*/
|
|
459
346
|
deleteVertex(vertexOrKey: VO | VertexKey): boolean {
|
|
460
347
|
let vertexKey: VertexKey;
|
|
@@ -474,7 +361,6 @@ export class UndirectedGraph<
|
|
|
474
361
|
* @remarks Time O(deg), Space O(deg)
|
|
475
362
|
*/
|
|
476
363
|
const neighbors = this.getNeighbors(vertexOrKey);
|
|
477
|
-
|
|
478
364
|
if (vertex) {
|
|
479
365
|
neighbors.forEach(neighbor => {
|
|
480
366
|
const neighborEdges = this._edgeMap.get(neighbor);
|
|
@@ -487,7 +373,6 @@ export class UndirectedGraph<
|
|
|
487
373
|
});
|
|
488
374
|
this._edgeMap.delete(vertex);
|
|
489
375
|
}
|
|
490
|
-
|
|
491
376
|
return this._vertexMap.delete(vertexKey);
|
|
492
377
|
}
|
|
493
378
|
|
|
@@ -525,49 +410,13 @@ export class UndirectedGraph<
|
|
|
525
410
|
* Unique set of undirected edges across endpoints.
|
|
526
411
|
* @returns Array of edges.
|
|
527
412
|
* @remarks Time O(E), Space O(E)
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
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
|
-
* @example
|
|
565
|
-
* // Get all edges
|
|
566
|
-
* const g = new UndirectedGraph();
|
|
567
|
-
* g.addVertex('A');
|
|
568
|
-
* g.addVertex('B');
|
|
569
|
-
* g.addEdge('A', 'B');
|
|
570
|
-
* 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;
|
|
571
420
|
*/
|
|
572
421
|
edgeSet(): EO[] {
|
|
573
422
|
const edgeSet: Set<EO> = new Set();
|
|
@@ -579,79 +428,40 @@ export class UndirectedGraph<
|
|
|
579
428
|
return [...edgeSet];
|
|
580
429
|
}
|
|
581
430
|
|
|
582
|
-
|
|
431
|
+
/**
|
|
583
432
|
* UndirectedGraph connectivity and neighbors
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
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
|
-
* @example
|
|
624
|
-
* // UndirectedGraph connectivity and neighbors
|
|
625
|
-
* const graph = new UndirectedGraph<string>();
|
|
626
|
-
*
|
|
627
|
-
* // Build a friendship network
|
|
628
|
-
* const people = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'];
|
|
629
|
-
* for (const person of people) {
|
|
630
|
-
* graph.addVertex(person);
|
|
631
|
-
* }
|
|
632
|
-
*
|
|
633
|
-
* // Add friendships (undirected edges)
|
|
634
|
-
* graph.addEdge('Alice', 'Bob', 1);
|
|
635
|
-
* graph.addEdge('Alice', 'Charlie', 1);
|
|
636
|
-
* graph.addEdge('Bob', 'Diana', 1);
|
|
637
|
-
* graph.addEdge('Charlie', 'Eve', 1);
|
|
638
|
-
* graph.addEdge('Diana', 'Eve', 1);
|
|
639
|
-
*
|
|
640
|
-
* // Get friends of each person
|
|
641
|
-
* const aliceFriends = graph.getNeighbors('Alice');
|
|
642
|
-
* console.log(aliceFriends[0].key); // 'Bob';
|
|
643
|
-
* console.log(aliceFriends[1].key); // 'Charlie';
|
|
644
|
-
* console.log(aliceFriends.length); // 2;
|
|
645
|
-
*
|
|
646
|
-
* const dianaFriends = graph.getNeighbors('Diana');
|
|
647
|
-
* console.log(dianaFriends[0].key); // 'Bob';
|
|
648
|
-
* console.log(dianaFriends[1].key); // 'Eve';
|
|
649
|
-
* console.log(dianaFriends.length); // 2;
|
|
650
|
-
*
|
|
651
|
-
* // Verify bidirectional friendship
|
|
652
|
-
* const bobFriends = graph.getNeighbors('Bob');
|
|
653
|
-
* console.log(bobFriends[0].key); // 'Alice'; // Alice -> Bob -> Alice ✓
|
|
654
|
-
* 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';
|
|
655
465
|
*/
|
|
656
466
|
getNeighbors(vertexOrKey: VO | VertexKey): VO[] {
|
|
657
467
|
const neighbors: VO[] = [];
|
|
@@ -717,75 +527,34 @@ export class UndirectedGraph<
|
|
|
717
527
|
* Tarjan-based bridge and articulation point detection.
|
|
718
528
|
* @returns `{ dfnMap, lowMap, bridges, cutVertices }`.
|
|
719
529
|
* @remarks Time O(V + E), Space O(V + E)
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
* @example
|
|
757
|
-
* // Find articulation points and bridges
|
|
758
|
-
* const g = new UndirectedGraph();
|
|
759
|
-
* g.addVertex('A');
|
|
760
|
-
* g.addVertex('B');
|
|
761
|
-
* g.addVertex('C');
|
|
762
|
-
* g.addEdge('A', 'B');
|
|
763
|
-
* g.addEdge('B', 'C');
|
|
764
|
-
* const result = g.tarjan();
|
|
765
|
-
* 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;
|
|
766
540
|
*/
|
|
767
541
|
tarjan(): { dfnMap: Map<VO, number>; lowMap: Map<VO, number>; bridges: EO[]; cutVertices: VO[] } {
|
|
768
542
|
const dfnMap = new Map<VO, number>();
|
|
769
543
|
const lowMap = new Map<VO, number>();
|
|
770
544
|
const bridges: EO[] = [];
|
|
771
545
|
const cutVertices: VO[] = [];
|
|
772
|
-
|
|
773
546
|
let time = 0;
|
|
774
|
-
|
|
775
547
|
const dfs = (vertex: VO, parent: VO | undefined) => {
|
|
776
548
|
dfnMap.set(vertex, time);
|
|
777
549
|
lowMap.set(vertex, time);
|
|
778
550
|
time++;
|
|
779
|
-
|
|
780
551
|
const neighbors = this.getNeighbors(vertex);
|
|
781
552
|
let childCount = 0;
|
|
782
|
-
|
|
783
553
|
for (const neighbor of neighbors) {
|
|
784
554
|
if (!dfnMap.has(neighbor)) {
|
|
785
555
|
childCount++;
|
|
786
556
|
dfs(neighbor, vertex);
|
|
787
557
|
lowMap.set(vertex, Math.min(lowMap.get(vertex)!, lowMap.get(neighbor)!));
|
|
788
|
-
|
|
789
558
|
if (lowMap.get(neighbor)! > dfnMap.get(vertex)!) {
|
|
790
559
|
// Found a bridge
|
|
791
560
|
const edge = this.getEdge(vertex, neighbor);
|
|
@@ -793,7 +562,6 @@ export class UndirectedGraph<
|
|
|
793
562
|
bridges.push(edge);
|
|
794
563
|
}
|
|
795
564
|
}
|
|
796
|
-
|
|
797
565
|
if (parent !== undefined && lowMap.get(neighbor)! >= dfnMap.get(vertex)!) {
|
|
798
566
|
// Found an articulation point
|
|
799
567
|
cutVertices.push(vertex);
|
|
@@ -802,19 +570,16 @@ export class UndirectedGraph<
|
|
|
802
570
|
lowMap.set(vertex, Math.min(lowMap.get(vertex)!, dfnMap.get(neighbor)!));
|
|
803
571
|
}
|
|
804
572
|
}
|
|
805
|
-
|
|
806
573
|
if (parent === undefined && childCount > 1) {
|
|
807
574
|
// Special case for root in DFS tree
|
|
808
575
|
cutVertices.push(vertex);
|
|
809
576
|
}
|
|
810
577
|
};
|
|
811
|
-
|
|
812
578
|
for (const vertex of this.vertexMap.values()) {
|
|
813
579
|
if (!dfnMap.has(vertex)) {
|
|
814
580
|
dfs(vertex, undefined);
|
|
815
581
|
}
|
|
816
582
|
}
|
|
817
|
-
|
|
818
583
|
return {
|
|
819
584
|
dfnMap,
|
|
820
585
|
lowMap,
|
|
@@ -835,25 +600,20 @@ export class UndirectedGraph<
|
|
|
835
600
|
const edgeStack: EO[] = [];
|
|
836
601
|
const components: EO[][] = [];
|
|
837
602
|
let time = 0;
|
|
838
|
-
|
|
839
603
|
const dfs = (vertex: VO, parent: VO | undefined) => {
|
|
840
604
|
dfn.set(vertex, time);
|
|
841
605
|
low.set(vertex, time);
|
|
842
606
|
time++;
|
|
843
|
-
|
|
844
607
|
const neighbors = this.getNeighbors(vertex);
|
|
845
608
|
let childCount = 0;
|
|
846
|
-
|
|
847
609
|
for (const neighbor of neighbors) {
|
|
848
610
|
const edge = this.getEdge(vertex, neighbor);
|
|
849
611
|
if (!edge) continue;
|
|
850
|
-
|
|
851
612
|
if (!dfn.has(neighbor)) {
|
|
852
613
|
childCount++;
|
|
853
614
|
edgeStack.push(edge);
|
|
854
615
|
dfs(neighbor, vertex);
|
|
855
616
|
low.set(vertex, Math.min(low.get(vertex)!, low.get(neighbor)!));
|
|
856
|
-
|
|
857
617
|
// Articulation point found — pop edges to form a component
|
|
858
618
|
if (
|
|
859
619
|
(parent === undefined && childCount > 1) ||
|
|
@@ -874,7 +634,6 @@ export class UndirectedGraph<
|
|
|
874
634
|
}
|
|
875
635
|
}
|
|
876
636
|
};
|
|
877
|
-
|
|
878
637
|
for (const vertex of this.vertexMap.values()) {
|
|
879
638
|
if (!dfn.has(vertex)) {
|
|
880
639
|
dfs(vertex, undefined);
|
|
@@ -885,7 +644,6 @@ export class UndirectedGraph<
|
|
|
885
644
|
}
|
|
886
645
|
}
|
|
887
646
|
}
|
|
888
|
-
|
|
889
647
|
return components;
|
|
890
648
|
}
|
|
891
649
|
|
|
@@ -894,57 +652,20 @@ export class UndirectedGraph<
|
|
|
894
652
|
* Uses DFS with parent tracking.
|
|
895
653
|
* @returns `true` if a cycle exists, `false` otherwise.
|
|
896
654
|
* @remarks Time O(V + E), Space O(V)
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
* @example
|
|
934
|
-
* // Detect cycle
|
|
935
|
-
* const g = new UndirectedGraph();
|
|
936
|
-
* g.addVertex('A');
|
|
937
|
-
* g.addVertex('B');
|
|
938
|
-
* g.addVertex('C');
|
|
939
|
-
* g.addEdge('A', 'B');
|
|
940
|
-
* g.addEdge('B', 'C');
|
|
941
|
-
* console.log(g.hasCycle()); // false;
|
|
942
|
-
* g.addEdge('C', 'A');
|
|
943
|
-
* 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;
|
|
944
666
|
*/
|
|
945
667
|
hasCycle(): boolean {
|
|
946
668
|
const visited = new Set<VO>();
|
|
947
|
-
|
|
948
669
|
const dfs = (vertex: VO, parent: VO | undefined): boolean => {
|
|
949
670
|
visited.add(vertex);
|
|
950
671
|
for (const neighbor of this.getNeighbors(vertex)) {
|
|
@@ -956,7 +677,6 @@ export class UndirectedGraph<
|
|
|
956
677
|
}
|
|
957
678
|
return false;
|
|
958
679
|
};
|
|
959
|
-
|
|
960
680
|
for (const vertex of this.vertexMap.values()) {
|
|
961
681
|
if (!visited.has(vertex)) {
|
|
962
682
|
if (dfs(vertex, undefined)) return true;
|
|
@@ -969,52 +689,16 @@ export class UndirectedGraph<
|
|
|
969
689
|
* Get bridges discovered by `tarjan()`.
|
|
970
690
|
* @returns Array of edges that are bridges.
|
|
971
691
|
* @remarks Time O(B), Space O(1)
|
|
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
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
* @example
|
|
1009
|
-
* // Find bridge edges
|
|
1010
|
-
* const g = new UndirectedGraph();
|
|
1011
|
-
* g.addVertex('A');
|
|
1012
|
-
* g.addVertex('B');
|
|
1013
|
-
* g.addVertex('C');
|
|
1014
|
-
* g.addEdge('A', 'B');
|
|
1015
|
-
* g.addEdge('B', 'C');
|
|
1016
|
-
* const bridges = g.getBridges();
|
|
1017
|
-
* 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;
|
|
1018
702
|
*/
|
|
1019
703
|
getBridges() {
|
|
1020
704
|
return this.tarjan().bridges;
|
|
@@ -1024,53 +708,17 @@ export class UndirectedGraph<
|
|
|
1024
708
|
* Get articulation points discovered by `tarjan()`.
|
|
1025
709
|
* @returns Array of cut vertices.
|
|
1026
710
|
* @remarks Time O(C), Space O(1)
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
* @example
|
|
1064
|
-
* // Find articulation points
|
|
1065
|
-
* const g = new UndirectedGraph();
|
|
1066
|
-
* g.addVertex('A');
|
|
1067
|
-
* g.addVertex('B');
|
|
1068
|
-
* g.addVertex('C');
|
|
1069
|
-
* g.addEdge('A', 'B');
|
|
1070
|
-
* g.addEdge('B', 'C');
|
|
1071
|
-
* const cuts = g.getCutVertices();
|
|
1072
|
-
* console.log(cuts.length); // 1;
|
|
1073
|
-
* 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';
|
|
1074
722
|
*/
|
|
1075
723
|
getCutVertices() {
|
|
1076
724
|
return this.tarjan().cutVertices;
|