max-heap-typed 2.2.2 → 2.2.4
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/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree-counter.d.ts +2 -2
- package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +5 -5
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +98 -5
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +103 -7
- package/dist/types/data-structures/binary-tree/bst.d.ts +202 -39
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +86 -37
- package/dist/types/data-structures/binary-tree/tree-counter.d.ts +4 -5
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +7 -7
- package/dist/types/data-structures/graph/directed-graph.d.ts +126 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +160 -1
- package/dist/types/data-structures/hash/hash-map.d.ts +110 -27
- package/dist/types/data-structures/heap/heap.d.ts +107 -58
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +72 -404
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +121 -5
- package/dist/types/data-structures/queue/deque.d.ts +95 -67
- package/dist/types/data-structures/queue/queue.d.ts +90 -34
- package/dist/types/data-structures/stack/stack.d.ts +58 -40
- package/dist/types/data-structures/trie/trie.d.ts +109 -47
- package/dist/types/interfaces/binary-tree.d.ts +1 -0
- package/dist/types/types/data-structures/binary-tree/bst.d.ts +5 -5
- package/dist/umd/max-heap-typed.js.map +1 -1
- package/dist/umd/max-heap-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/data-structures/binary-tree/avl-tree-counter.ts +1 -2
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +7 -8
- package/src/data-structures/binary-tree/avl-tree.ts +100 -7
- package/src/data-structures/binary-tree/binary-tree.ts +117 -7
- package/src/data-structures/binary-tree/bst.ts +431 -93
- package/src/data-structures/binary-tree/red-black-tree.ts +85 -37
- package/src/data-structures/binary-tree/tree-counter.ts +5 -7
- package/src/data-structures/binary-tree/tree-multi-map.ts +9 -10
- package/src/data-structures/graph/directed-graph.ts +126 -1
- package/src/data-structures/graph/undirected-graph.ts +160 -1
- package/src/data-structures/hash/hash-map.ts +110 -27
- package/src/data-structures/heap/heap.ts +107 -58
- package/src/data-structures/linked-list/doubly-linked-list.ts +72 -404
- package/src/data-structures/linked-list/singly-linked-list.ts +121 -5
- package/src/data-structures/queue/deque.ts +95 -67
- package/src/data-structures/queue/queue.ts +90 -34
- package/src/data-structures/stack/stack.ts +58 -40
- package/src/data-structures/trie/trie.ts +109 -47
- package/src/interfaces/binary-tree.ts +2 -0
- package/src/types/data-structures/binary-tree/bst.ts +5 -5
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
import type {
|
|
10
10
|
BinaryTreeDeleteResult,
|
|
11
|
-
BinaryTreeOptions,
|
|
12
11
|
CRUD,
|
|
13
12
|
EntryCallback,
|
|
14
13
|
FamilyPosition,
|
|
@@ -188,48 +187,97 @@ export class RedBlackTreeNode<K = any, V = any> {
|
|
|
188
187
|
* 2. It is BST itself. Compared with Heap which is not completely ordered, RedBlackTree is completely ordered.
|
|
189
188
|
*
|
|
190
189
|
* @example
|
|
191
|
-
* //
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
190
|
+
* // basic Red-Black Tree with simple number keys
|
|
191
|
+
* // Create a simple Red-Black Tree with numeric keys
|
|
192
|
+
* const tree = new RedBlackTree([5, 2, 8, 1, 9]);
|
|
193
|
+
*
|
|
194
|
+
* tree.print();
|
|
195
|
+
* // _2___
|
|
196
|
+
* // / \
|
|
197
|
+
* // 1 _8_
|
|
198
|
+
* // / \
|
|
199
|
+
* // 5 9
|
|
200
|
+
*
|
|
201
|
+
* // Verify the tree maintains sorted order
|
|
202
|
+
* console.log([...tree.keys()]); // [1, 2, 5, 8, 9];
|
|
203
|
+
*
|
|
204
|
+
* // Check size
|
|
205
|
+
* console.log(tree.size); // 5;
|
|
206
|
+
* @example
|
|
207
|
+
* // Red-Black Tree with key-value pairs for lookups
|
|
208
|
+
* interface Employee {
|
|
209
|
+
* id: number;
|
|
210
|
+
* name: string;
|
|
197
211
|
* }
|
|
198
212
|
*
|
|
199
|
-
* //
|
|
200
|
-
* const
|
|
201
|
-
* {
|
|
202
|
-
* {
|
|
203
|
-
* {
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
213
|
+
* // Create tree with employee data
|
|
214
|
+
* const employees = new RedBlackTree<number, Employee>([
|
|
215
|
+
* [1, { id: 1, name: 'Alice' }],
|
|
216
|
+
* [3, { id: 3, name: 'Charlie' }],
|
|
217
|
+
* [2, { id: 2, name: 'Bob' }]
|
|
218
|
+
* ]);
|
|
219
|
+
*
|
|
220
|
+
* // Retrieve employee by ID
|
|
221
|
+
* const alice = employees.get(1);
|
|
222
|
+
* console.log(alice?.name); // 'Alice';
|
|
223
|
+
*
|
|
224
|
+
* // Verify sorted order by ID
|
|
225
|
+
* console.log([...employees.keys()]); // [1, 2, 3];
|
|
226
|
+
* @example
|
|
227
|
+
* // Red-Black Tree range search for filtering
|
|
228
|
+
* interface Product {
|
|
229
|
+
* name: string;
|
|
230
|
+
* price: number;
|
|
231
|
+
* }
|
|
207
232
|
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
233
|
+
* const products = new RedBlackTree<number, Product>([
|
|
234
|
+
* [10, { name: 'Item A', price: 10 }],
|
|
235
|
+
* [25, { name: 'Item B', price: 25 }],
|
|
236
|
+
* [40, { name: 'Item C', price: 40 }],
|
|
237
|
+
* [50, { name: 'Item D', price: 50 }]
|
|
238
|
+
* ]);
|
|
210
239
|
*
|
|
211
|
-
* //
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
* toEntryFn: stockRecord => [
|
|
215
|
-
* stockRecord.price, // Use stock price as the key
|
|
216
|
-
* {
|
|
217
|
-
* ...stockRecord,
|
|
218
|
-
* lastUpdated: new Date() // Add a timestamp for when the record was indexed
|
|
219
|
-
* }
|
|
220
|
-
* ]
|
|
240
|
+
* // Find products in price range [20, 45]
|
|
241
|
+
* const pricesInRange = products.rangeSearch([20, 45], node => {
|
|
242
|
+
* return products.get(node)?.name;
|
|
221
243
|
* });
|
|
222
244
|
*
|
|
223
|
-
* //
|
|
224
|
-
*
|
|
225
|
-
*
|
|
245
|
+
* console.log(pricesInRange); // ['Item B', 'Item C'];
|
|
246
|
+
* @example
|
|
247
|
+
* // Red-Black Tree as database index for stock market data
|
|
248
|
+
* interface StockPrice {
|
|
249
|
+
* symbol: string;
|
|
250
|
+
* volume: number;
|
|
251
|
+
* timestamp: Date;
|
|
252
|
+
* }
|
|
253
|
+
*
|
|
254
|
+
* // Simulate real-time stock price index
|
|
255
|
+
* const priceIndex = new RedBlackTree<number, StockPrice>([
|
|
256
|
+
* [142.5, { symbol: 'AAPL', volume: 1000000, timestamp: new Date() }],
|
|
257
|
+
* [335.2, { symbol: 'MSFT', volume: 800000, timestamp: new Date() }],
|
|
258
|
+
* [3285.04, { symbol: 'AMZN', volume: 500000, timestamp: new Date() }],
|
|
259
|
+
* [267.98, { symbol: 'META', volume: 750000, timestamp: new Date() }],
|
|
260
|
+
* [234.57, { symbol: 'GOOGL', volume: 900000, timestamp: new Date() }]
|
|
261
|
+
* ]);
|
|
262
|
+
*
|
|
263
|
+
* // Find highest-priced stock
|
|
264
|
+
* const maxPrice = priceIndex.getRightMost();
|
|
265
|
+
* console.log(priceIndex.get(maxPrice)?.symbol); // 'AMZN';
|
|
266
|
+
*
|
|
267
|
+
* // Find stocks in price range [200, 400] for portfolio balancing
|
|
268
|
+
* const stocksInRange = priceIndex.rangeSearch([200, 400], node => {
|
|
269
|
+
* const stock = priceIndex.get(node);
|
|
270
|
+
* return {
|
|
271
|
+
* symbol: stock?.symbol,
|
|
272
|
+
* price: node,
|
|
273
|
+
* volume: stock?.volume
|
|
274
|
+
* };
|
|
275
|
+
* });
|
|
226
276
|
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
* );
|
|
232
|
-
* console.log(stocksInRange); // ['GOOGL', 'META', 'MSFT']
|
|
277
|
+
* console.log(stocksInRange.length); // 3;
|
|
278
|
+
* console.log(stocksInRange.some((s: any) => s.symbol === 'GOOGL')); // true;
|
|
279
|
+
* console.log(stocksInRange.some((s: any) => s.symbol === 'META')); // true;
|
|
280
|
+
* console.log(stocksInRange.some((s: any) => s.symbol === 'MSFT')); // true;
|
|
233
281
|
*/
|
|
234
282
|
|
|
235
283
|
export class RedBlackTree<K = any, V = any, R = any> extends BST<K, V, R> implements IBinaryTree<K, V, R> {
|
|
@@ -414,7 +462,7 @@ export class RedBlackTree<K = any, V = any, R = any> extends BST<K, V, R> implem
|
|
|
414
462
|
|
|
415
463
|
override map<MK = K, MV = V, MR = any>(
|
|
416
464
|
callback: EntryCallback<K, V | undefined, [MK, MV]>,
|
|
417
|
-
options?: Partial<
|
|
465
|
+
options?: Partial<RedBlackTreeOptions<MK, MV, MR>>,
|
|
418
466
|
thisArg?: unknown
|
|
419
467
|
): RedBlackTree<MK, MV, MR> {
|
|
420
468
|
const out = this._createLike<MK, MV, MR>([], options);
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
import type {
|
|
10
10
|
BinaryTreeDeleteResult,
|
|
11
|
-
BinaryTreeOptions,
|
|
12
11
|
BSTNOptKeyOrNode,
|
|
13
12
|
EntryCallback,
|
|
14
13
|
FamilyPosition,
|
|
@@ -17,7 +16,6 @@ import type {
|
|
|
17
16
|
RBTNColor,
|
|
18
17
|
TreeCounterOptions
|
|
19
18
|
} from '../../types';
|
|
20
|
-
import { BSTOptions } from '../../types';
|
|
21
19
|
import { BSTNode } from './bst';
|
|
22
20
|
import { IBinaryTree } from '../../interfaces';
|
|
23
21
|
import { RedBlackTree } from './red-black-tree';
|
|
@@ -432,7 +430,7 @@ export class TreeCounter<K = any, V = any, R = any> extends RedBlackTree<K, V, R
|
|
|
432
430
|
*/
|
|
433
431
|
override map<MK = K, MV = V, MR = any>(
|
|
434
432
|
callback: EntryCallback<K, V | undefined, [MK, MV]>,
|
|
435
|
-
options?: Partial<
|
|
433
|
+
options?: Partial<TreeCounterOptions<MK, MV, MR>>,
|
|
436
434
|
thisArg?: unknown
|
|
437
435
|
): TreeCounter<MK, MV, MR> {
|
|
438
436
|
const out = this._createLike<MK, MV, MR>([], options);
|
|
@@ -465,10 +463,10 @@ export class TreeCounter<K = any, V = any, R = any> extends RedBlackTree<K, V, R
|
|
|
465
463
|
* @param [options] - Optional constructor options for the like-kind instance.
|
|
466
464
|
* @returns An empty like-kind instance.
|
|
467
465
|
*/
|
|
468
|
-
protected override _createInstance<TK = K, TV = V, TR = R>(options?: Partial<
|
|
466
|
+
protected override _createInstance<TK = K, TV = V, TR = R>(options?: Partial<TreeCounterOptions<TK, TV, TR>>): this {
|
|
469
467
|
const Ctor = this.constructor as unknown as new (
|
|
470
468
|
iter?: Iterable<TK | BSTNode<TK, TV> | [TK | null | undefined, TV | undefined] | null | undefined | TR>,
|
|
471
|
-
opts?:
|
|
469
|
+
opts?: TreeCounterOptions<TK, TV, TR>
|
|
472
470
|
) => this;
|
|
473
471
|
return new Ctor([], { ...this._snapshotOptions<TK, TV, TR>(), ...(options ?? {}) }) as unknown as this;
|
|
474
472
|
}
|
|
@@ -485,11 +483,11 @@ export class TreeCounter<K = any, V = any, R = any> extends RedBlackTree<K, V, R
|
|
|
485
483
|
*/
|
|
486
484
|
protected override _createLike<TK = K, TV = V, TR = R>(
|
|
487
485
|
iter: Iterable<TK | BSTNode<TK, TV> | [TK | null | undefined, TV | undefined] | null | undefined | TR> = [],
|
|
488
|
-
options?: Partial<
|
|
486
|
+
options?: Partial<TreeCounterOptions<TK, TV, TR>>
|
|
489
487
|
): TreeCounter<TK, TV, TR> {
|
|
490
488
|
const Ctor = this.constructor as unknown as new (
|
|
491
489
|
iter?: Iterable<TK | BSTNode<TK, TV> | [TK | null | undefined, TV | undefined] | null | undefined | TR>,
|
|
492
|
-
opts?:
|
|
490
|
+
opts?: TreeCounterOptions<TK, TV, TR>
|
|
493
491
|
) => TreeCounter<TK, TV, TR>;
|
|
494
492
|
return new Ctor(iter as unknown as Iterable<TK | any>, {
|
|
495
493
|
...this._snapshotOptions<TK, TV, TR>(),
|
|
@@ -12,7 +12,6 @@ import type {
|
|
|
12
12
|
EntryCallback,
|
|
13
13
|
FamilyPosition,
|
|
14
14
|
RBTNColor,
|
|
15
|
-
RedBlackTreeOptions,
|
|
16
15
|
TreeMultiMapOptions
|
|
17
16
|
} from '../../types';
|
|
18
17
|
import { RedBlackTree, RedBlackTreeNode } from './red-black-tree';
|
|
@@ -186,7 +185,7 @@ export class TreeMultiMapNode<K = any, V = any> {
|
|
|
186
185
|
*
|
|
187
186
|
* @example
|
|
188
187
|
* // players ranked by score with their equipment
|
|
189
|
-
*
|
|
188
|
+
* type Equipment = {
|
|
190
189
|
* name: string; // Equipment name
|
|
191
190
|
* quality: 'legendary' | 'epic' | 'rare' | 'common';
|
|
192
191
|
* level: number;
|
|
@@ -347,7 +346,7 @@ export class TreeMultiMapNode<K = any, V = any> {
|
|
|
347
346
|
* // },
|
|
348
347
|
* // { name: 'Level 3 Backpack', quality: 'epic', level: 80 }
|
|
349
348
|
* // ]
|
|
350
|
-
* // ]
|
|
349
|
+
* // ];
|
|
351
350
|
*/
|
|
352
351
|
export class TreeMultiMap<K = any, V = any, R = any> extends RedBlackTree<K, V[], R> implements IBinaryTree<K, V[], R> {
|
|
353
352
|
/**
|
|
@@ -476,13 +475,13 @@ export class TreeMultiMap<K = any, V = any, R = any> extends RedBlackTree<K, V[]
|
|
|
476
475
|
|
|
477
476
|
override map<MK = K, MVArr extends unknown[] = V[], MR = any>(
|
|
478
477
|
callback: EntryCallback<K, V[] | undefined, [MK, MVArr]>,
|
|
479
|
-
options?: Partial<
|
|
478
|
+
options?: Partial<TreeMultiMapOptions<MK, MVArr, MR>>,
|
|
480
479
|
thisArg?: unknown
|
|
481
480
|
): TreeMultiMap<MK, ElemOf<MVArr>, MR>;
|
|
482
481
|
|
|
483
482
|
override map<MK = K, MV = V[], MR = any>(
|
|
484
483
|
callback: EntryCallback<K, V[] | undefined, [MK, MV]>,
|
|
485
|
-
options?: Partial<
|
|
484
|
+
options?: Partial<TreeMultiMapOptions<MK, MV, MR>>,
|
|
486
485
|
thisArg?: unknown
|
|
487
486
|
): RedBlackTree<MK, MV, MR>;
|
|
488
487
|
|
|
@@ -499,7 +498,7 @@ export class TreeMultiMap<K = any, V = any, R = any> extends RedBlackTree<K, V[]
|
|
|
499
498
|
*/
|
|
500
499
|
override map<MK, MV, MR extends object>(
|
|
501
500
|
callback: EntryCallback<K, V[] | undefined, [MK, MV]>,
|
|
502
|
-
options?: Partial<
|
|
501
|
+
options?: Partial<TreeMultiMapOptions<MK, MV, MR>>,
|
|
503
502
|
thisArg?: unknown
|
|
504
503
|
): RedBlackTree<MK, MV, MR> {
|
|
505
504
|
const out = this._createLike<MK, MV, MR>([], options);
|
|
@@ -517,10 +516,10 @@ export class TreeMultiMap<K = any, V = any, R = any> extends RedBlackTree<K, V[]
|
|
|
517
516
|
* @param [options] - Optional constructor options for the like-kind instance.
|
|
518
517
|
* @returns An empty like-kind instance.
|
|
519
518
|
*/
|
|
520
|
-
protected override _createInstance<TK = K, TV = V, TR = R>(options?: Partial<
|
|
519
|
+
protected override _createInstance<TK = K, TV = V, TR = R>(options?: Partial<TreeMultiMapOptions<TK, TV, TR>>): this {
|
|
521
520
|
const Ctor = this.constructor as unknown as new (
|
|
522
521
|
iter?: Iterable<TK | RedBlackTreeNode<TK, TV> | [TK | null | undefined, TV | undefined] | null | undefined | TR>,
|
|
523
|
-
opts?:
|
|
522
|
+
opts?: TreeMultiMapOptions<TK, TV, TR>
|
|
524
523
|
) => RedBlackTree<TK, TV, TR>;
|
|
525
524
|
return new Ctor([], { ...(this._snapshotOptions?.<TK, TV, TR>() ?? {}), ...(options ?? {}) }) as unknown as this;
|
|
526
525
|
}
|
|
@@ -539,11 +538,11 @@ export class TreeMultiMap<K = any, V = any, R = any> extends RedBlackTree<K, V[]
|
|
|
539
538
|
iter: Iterable<
|
|
540
539
|
TK | RedBlackTreeNode<TK, TV> | [TK | null | undefined, TV | undefined] | null | undefined | TR
|
|
541
540
|
> = [],
|
|
542
|
-
options?: Partial<
|
|
541
|
+
options?: Partial<TreeMultiMapOptions<TK, TV, TR>>
|
|
543
542
|
): RedBlackTree<TK, TV, TR> {
|
|
544
543
|
const Ctor = this.constructor as unknown as new (
|
|
545
544
|
iter?: Iterable<TK | RedBlackTreeNode<TK, TV> | [TK | null | undefined, TV | undefined] | null | undefined | TR>,
|
|
546
|
-
opts?:
|
|
545
|
+
opts?: TreeMultiMapOptions<TK, TV, TR>
|
|
547
546
|
) => RedBlackTree<TK, TV, TR>;
|
|
548
547
|
return new Ctor(iter, { ...(this._snapshotOptions?.<TK, TV, TR>() ?? {}), ...(options ?? {}) });
|
|
549
548
|
}
|
|
@@ -35,7 +35,132 @@ export class DirectedEdge<E = any> extends AbstractEdge<E> {
|
|
|
35
35
|
* @template VO - Concrete vertex class (extends AbstractVertex<V>).
|
|
36
36
|
* @template EO - Concrete edge class (extends AbstractEdge<E>).
|
|
37
37
|
* @remarks Time O(1), Space O(1)
|
|
38
|
-
* @example
|
|
38
|
+
* @example
|
|
39
|
+
* // basic DirectedGraph vertex and edge creation
|
|
40
|
+
* // Create a simple directed graph
|
|
41
|
+
* const graph = new DirectedGraph<string>();
|
|
42
|
+
*
|
|
43
|
+
* // Add vertices
|
|
44
|
+
* graph.addVertex('A');
|
|
45
|
+
* graph.addVertex('B');
|
|
46
|
+
* graph.addVertex('C');
|
|
47
|
+
*
|
|
48
|
+
* // Verify vertices exist
|
|
49
|
+
* console.log(graph.hasVertex('A')); // true;
|
|
50
|
+
* console.log(graph.hasVertex('B')); // true;
|
|
51
|
+
* console.log(graph.hasVertex('C')); // true;
|
|
52
|
+
* console.log(graph.hasVertex('D')); // false;
|
|
53
|
+
*
|
|
54
|
+
* // Check vertex count
|
|
55
|
+
* console.log(graph.size); // 3;
|
|
56
|
+
* @example
|
|
57
|
+
* // DirectedGraph edge operations
|
|
58
|
+
* const graph = new DirectedGraph<string>();
|
|
59
|
+
*
|
|
60
|
+
* // Add vertices
|
|
61
|
+
* graph.addVertex('A');
|
|
62
|
+
* graph.addVertex('B');
|
|
63
|
+
* graph.addVertex('C');
|
|
64
|
+
*
|
|
65
|
+
* // Add directed edges
|
|
66
|
+
* graph.addEdge('A', 'B', 1);
|
|
67
|
+
* graph.addEdge('B', 'C', 2);
|
|
68
|
+
* graph.addEdge('A', 'C', 3);
|
|
69
|
+
*
|
|
70
|
+
* // Verify edges exist
|
|
71
|
+
* console.log(graph.hasEdge('A', 'B')); // true;
|
|
72
|
+
* console.log(graph.hasEdge('B', 'C')); // true;
|
|
73
|
+
* console.log(graph.hasEdge('C', 'B')); // false; // Graph is directed
|
|
74
|
+
*
|
|
75
|
+
* // Get neighbors of A
|
|
76
|
+
* const neighborsA = graph.getNeighbors('A');
|
|
77
|
+
* console.log(neighborsA[0].key); // 'B';
|
|
78
|
+
* console.log(neighborsA[1].key); // 'C';
|
|
79
|
+
* @example
|
|
80
|
+
* // DirectedGraph deleteEdge and vertex operations
|
|
81
|
+
* const graph = new DirectedGraph<string>();
|
|
82
|
+
*
|
|
83
|
+
* // Build a small 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
|
+
*
|
|
90
|
+
* // Delete an edge
|
|
91
|
+
* graph.deleteEdgeSrcToDest('X', 'Y');
|
|
92
|
+
* console.log(graph.hasEdge('X', 'Y')); // false;
|
|
93
|
+
*
|
|
94
|
+
* // Edge in other direction should not exist
|
|
95
|
+
* console.log(graph.hasEdge('Y', 'X')); // false;
|
|
96
|
+
*
|
|
97
|
+
* // Other edges should remain
|
|
98
|
+
* console.log(graph.hasEdge('Y', 'Z')); // true;
|
|
99
|
+
*
|
|
100
|
+
* // Delete a vertex
|
|
101
|
+
* graph.deleteVertex('Y');
|
|
102
|
+
* console.log(graph.hasVertex('Y')); // false;
|
|
103
|
+
* console.log(graph.size); // 2;
|
|
104
|
+
* @example
|
|
105
|
+
* // DirectedGraph topologicalSort for task scheduling
|
|
106
|
+
* const graph = new DirectedGraph<string>();
|
|
107
|
+
*
|
|
108
|
+
* // Build a DAG (Directed Acyclic Graph) for task dependencies
|
|
109
|
+
* graph.addVertex('Design');
|
|
110
|
+
* graph.addVertex('Implement');
|
|
111
|
+
* graph.addVertex('Test');
|
|
112
|
+
* graph.addVertex('Deploy');
|
|
113
|
+
*
|
|
114
|
+
* // Add dependency edges
|
|
115
|
+
* graph.addEdge('Design', 'Implement', 1); // Design must come before Implement
|
|
116
|
+
* graph.addEdge('Implement', 'Test', 1); // Implement must come before Test
|
|
117
|
+
* graph.addEdge('Test', 'Deploy', 1); // Test must come before Deploy
|
|
118
|
+
*
|
|
119
|
+
* // Topological sort gives valid execution order
|
|
120
|
+
* const executionOrder = graph.topologicalSort();
|
|
121
|
+
* console.log(executionOrder); // defined;
|
|
122
|
+
* console.log(executionOrder); // ['Design', 'Implement', 'Test', 'Deploy'];
|
|
123
|
+
*
|
|
124
|
+
* // All vertices should be included
|
|
125
|
+
* console.log(executionOrder?.length); // 4;
|
|
126
|
+
* @example
|
|
127
|
+
* // DirectedGraph dijkstra shortest path for network routing
|
|
128
|
+
* // Build a weighted directed graph representing network nodes and costs
|
|
129
|
+
* const network = new DirectedGraph<string>();
|
|
130
|
+
*
|
|
131
|
+
* // Add network nodes
|
|
132
|
+
* network.addVertex('Router-A');
|
|
133
|
+
* network.addVertex('Router-B');
|
|
134
|
+
* network.addVertex('Router-C');
|
|
135
|
+
* network.addVertex('Router-D');
|
|
136
|
+
* network.addVertex('Router-E');
|
|
137
|
+
*
|
|
138
|
+
* // Add weighted edges (network latency costs)
|
|
139
|
+
* network.addEdge('Router-A', 'Router-B', 5);
|
|
140
|
+
* network.addEdge('Router-A', 'Router-C', 10);
|
|
141
|
+
* network.addEdge('Router-B', 'Router-D', 3);
|
|
142
|
+
* network.addEdge('Router-C', 'Router-D', 2);
|
|
143
|
+
* network.addEdge('Router-D', 'Router-E', 4);
|
|
144
|
+
* network.addEdge('Router-B', 'Router-E', 12);
|
|
145
|
+
*
|
|
146
|
+
* // Find shortest path from Router-A to Router-E
|
|
147
|
+
* const { minDist, minPath } = network.dijkstra('Router-A', 'Router-E', true, true) || {
|
|
148
|
+
* minDist: undefined,
|
|
149
|
+
* minPath: undefined
|
|
150
|
+
* };
|
|
151
|
+
*
|
|
152
|
+
* // Verify shortest path is found
|
|
153
|
+
* console.log(minDist); // defined;
|
|
154
|
+
* console.log(minPath); // defined;
|
|
155
|
+
*
|
|
156
|
+
* // Shortest path should be A -> B -> D -> E with cost 5+3+4=12
|
|
157
|
+
* // Or A -> C -> D -> E with cost 10+2+4=16
|
|
158
|
+
* // So the minimum is 12
|
|
159
|
+
* console.log(minDist); // <= 16;
|
|
160
|
+
*
|
|
161
|
+
* // Verify path is valid (includes start and end)
|
|
162
|
+
* console.log(minPath?.[0].key); // 'Router-A';
|
|
163
|
+
* console.log(minPath?.[minPath.length - 1].key); // 'Router-E';
|
|
39
164
|
*/
|
|
40
165
|
export class DirectedGraph<
|
|
41
166
|
V = any,
|
|
@@ -33,7 +33,166 @@ export class UndirectedEdge<E = number> extends AbstractEdge<E> {
|
|
|
33
33
|
* @template VO - Concrete vertex class (extends AbstractVertex<V>).
|
|
34
34
|
* @template EO - Concrete edge class (extends AbstractEdge<E>).
|
|
35
35
|
* @remarks Time O(1), Space O(1)
|
|
36
|
-
* @example
|
|
36
|
+
* @example
|
|
37
|
+
* // basic UndirectedGraph vertex and edge creation
|
|
38
|
+
* // Create a simple undirected graph
|
|
39
|
+
* const graph = new UndirectedGraph<string>();
|
|
40
|
+
*
|
|
41
|
+
* // Add vertices
|
|
42
|
+
* graph.addVertex('A');
|
|
43
|
+
* graph.addVertex('B');
|
|
44
|
+
* graph.addVertex('C');
|
|
45
|
+
* graph.addVertex('D');
|
|
46
|
+
*
|
|
47
|
+
* // Verify vertices exist
|
|
48
|
+
* console.log(graph.hasVertex('A')); // true;
|
|
49
|
+
* console.log(graph.hasVertex('B')); // true;
|
|
50
|
+
* console.log(graph.hasVertex('E')); // false;
|
|
51
|
+
*
|
|
52
|
+
* // Check vertex count
|
|
53
|
+
* console.log(graph.size); // 4;
|
|
54
|
+
* @example
|
|
55
|
+
* // UndirectedGraph edge operations (bidirectional)
|
|
56
|
+
* const graph = new UndirectedGraph<string>();
|
|
57
|
+
*
|
|
58
|
+
* // Add vertices
|
|
59
|
+
* graph.addVertex('A');
|
|
60
|
+
* graph.addVertex('B');
|
|
61
|
+
* graph.addVertex('C');
|
|
62
|
+
*
|
|
63
|
+
* // Add undirected edges (both directions automatically)
|
|
64
|
+
* graph.addEdge('A', 'B', 1);
|
|
65
|
+
* graph.addEdge('B', 'C', 2);
|
|
66
|
+
* graph.addEdge('A', 'C', 3);
|
|
67
|
+
*
|
|
68
|
+
* // Verify edges exist in both directions
|
|
69
|
+
* console.log(graph.hasEdge('A', 'B')); // true;
|
|
70
|
+
* console.log(graph.hasEdge('B', 'A')); // true; // Bidirectional!
|
|
71
|
+
*
|
|
72
|
+
* console.log(graph.hasEdge('C', 'B')); // true;
|
|
73
|
+
* console.log(graph.hasEdge('B', 'C')); // true; // Bidirectional!
|
|
74
|
+
*
|
|
75
|
+
* // Get neighbors of A
|
|
76
|
+
* const neighborsA = graph.getNeighbors('A');
|
|
77
|
+
* console.log(neighborsA[0].key); // 'B';
|
|
78
|
+
* console.log(neighborsA[1].key); // 'C';
|
|
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
|
+
* // UndirectedGraph for social network connectivity analysis
|
|
140
|
+
* interface Person {
|
|
141
|
+
* id: number;
|
|
142
|
+
* name: string;
|
|
143
|
+
* location: string;
|
|
144
|
+
* }
|
|
145
|
+
*
|
|
146
|
+
* // UndirectedGraph is perfect for modeling symmetric relationships
|
|
147
|
+
* // (friendships, collaborations, partnerships)
|
|
148
|
+
* const socialNetwork = new UndirectedGraph<number, Person>();
|
|
149
|
+
*
|
|
150
|
+
* // Add people as vertices
|
|
151
|
+
* const people: [number, Person][] = [
|
|
152
|
+
* [1, { id: 1, name: 'Alice', location: 'New York' }],
|
|
153
|
+
* [2, { id: 2, name: 'Bob', location: 'San Francisco' }],
|
|
154
|
+
* [3, { id: 3, name: 'Charlie', location: 'Boston' }],
|
|
155
|
+
* [4, { id: 4, name: 'Diana', location: 'New York' }],
|
|
156
|
+
* [5, { id: 5, name: 'Eve', location: 'Seattle' }]
|
|
157
|
+
* ];
|
|
158
|
+
*
|
|
159
|
+
* for (const [id] of people) {
|
|
160
|
+
* socialNetwork.addVertex(id);
|
|
161
|
+
* }
|
|
162
|
+
*
|
|
163
|
+
* // Add friendships (automatically bidirectional)
|
|
164
|
+
* socialNetwork.addEdge(1, 2, 1); // Alice <-> Bob
|
|
165
|
+
* socialNetwork.addEdge(1, 3, 1); // Alice <-> Charlie
|
|
166
|
+
* socialNetwork.addEdge(2, 4, 1); // Bob <-> Diana
|
|
167
|
+
* socialNetwork.addEdge(3, 5, 1); // Charlie <-> Eve
|
|
168
|
+
* socialNetwork.addEdge(4, 5, 1); // Diana <-> Eve
|
|
169
|
+
*
|
|
170
|
+
* console.log(socialNetwork.size); // 5;
|
|
171
|
+
*
|
|
172
|
+
* // Find direct connections for Alice
|
|
173
|
+
* const aliceConnections = socialNetwork.getNeighbors(1);
|
|
174
|
+
* console.log(aliceConnections[0].key); // 2;
|
|
175
|
+
* console.log(aliceConnections[1].key); // 3;
|
|
176
|
+
* console.log(aliceConnections.length); // 2;
|
|
177
|
+
*
|
|
178
|
+
* // Verify bidirectional connections
|
|
179
|
+
* console.log(socialNetwork.hasEdge(1, 2)); // true;
|
|
180
|
+
* console.log(socialNetwork.hasEdge(2, 1)); // true; // Friendship works both ways!
|
|
181
|
+
*
|
|
182
|
+
* // Remove a person from network
|
|
183
|
+
* socialNetwork.deleteVertex(2); // Bob leaves
|
|
184
|
+
* console.log(socialNetwork.hasVertex(2)); // false;
|
|
185
|
+
* console.log(socialNetwork.size); // 4;
|
|
186
|
+
*
|
|
187
|
+
* // Alice loses Bob as a friend
|
|
188
|
+
* const updatedAliceConnections = socialNetwork.getNeighbors(1);
|
|
189
|
+
* console.log(updatedAliceConnections[0].key); // 3;
|
|
190
|
+
* console.log(updatedAliceConnections[1]); // undefined;
|
|
191
|
+
*
|
|
192
|
+
* // Diana loses Bob as a friend
|
|
193
|
+
* const dianaConnections = socialNetwork.getNeighbors(4);
|
|
194
|
+
* console.log(dianaConnections[0].key); // 5;
|
|
195
|
+
* console.log(dianaConnections[1]); // undefined;
|
|
37
196
|
*/
|
|
38
197
|
export class UndirectedGraph<
|
|
39
198
|
V = any,
|