data-structure-typed 2.6.0 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/.github/workflows/ci.yml +7 -2
  2. package/.github/workflows/release-package.yml +9 -2
  3. package/docs-site-docusaurus/docs/api/classes/AVLTree.md +108 -108
  4. package/docs-site-docusaurus/docs/api/classes/BST.md +101 -101
  5. package/docs-site-docusaurus/docs/api/classes/BinaryIndexedTree.md +13 -13
  6. package/docs-site-docusaurus/docs/api/classes/BinaryTree.md +66 -66
  7. package/docs-site-docusaurus/docs/api/classes/Deque.md +235 -51
  8. package/docs-site-docusaurus/docs/api/classes/DirectedGraph.md +21 -21
  9. package/docs-site-docusaurus/docs/api/classes/DoublyLinkedList.md +231 -67
  10. package/docs-site-docusaurus/docs/api/classes/FibonacciHeap.md +9 -9
  11. package/docs-site-docusaurus/docs/api/classes/FibonacciHeapNode.md +1 -1
  12. package/docs-site-docusaurus/docs/api/classes/HashMap.md +14 -14
  13. package/docs-site-docusaurus/docs/api/classes/Heap.md +117 -34
  14. package/docs-site-docusaurus/docs/api/classes/IterableElementBase.md +83 -13
  15. package/docs-site-docusaurus/docs/api/classes/LinearBase.md +124 -20
  16. package/docs-site-docusaurus/docs/api/classes/LinearLinkedBase.md +140 -32
  17. package/docs-site-docusaurus/docs/api/classes/LinkedHashMap.md +23 -23
  18. package/docs-site-docusaurus/docs/api/classes/LinkedListQueue.md +159 -51
  19. package/docs-site-docusaurus/docs/api/classes/MapGraph.md +20 -20
  20. package/docs-site-docusaurus/docs/api/classes/Matrix.md +23 -23
  21. package/docs-site-docusaurus/docs/api/classes/MaxHeap.md +117 -34
  22. package/docs-site-docusaurus/docs/api/classes/MaxPriorityQueue.md +117 -34
  23. package/docs-site-docusaurus/docs/api/classes/MinHeap.md +117 -34
  24. package/docs-site-docusaurus/docs/api/classes/MinPriorityQueue.md +117 -34
  25. package/docs-site-docusaurus/docs/api/classes/PriorityQueue.md +117 -34
  26. package/docs-site-docusaurus/docs/api/classes/Queue.md +142 -34
  27. package/docs-site-docusaurus/docs/api/classes/RedBlackTree.md +117 -117
  28. package/docs-site-docusaurus/docs/api/classes/SegmentTree.md +8 -8
  29. package/docs-site-docusaurus/docs/api/classes/SinglyLinkedList.md +158 -50
  30. package/docs-site-docusaurus/docs/api/classes/SkipList.md +21 -21
  31. package/docs-site-docusaurus/docs/api/classes/Stack.md +108 -26
  32. package/docs-site-docusaurus/docs/api/classes/TreeMap.md +33 -33
  33. package/docs-site-docusaurus/docs/api/classes/TreeMultiMap.md +75 -39
  34. package/docs-site-docusaurus/docs/api/classes/TreeSet.md +301 -39
  35. package/docs-site-docusaurus/docs/api/classes/Trie.md +110 -28
  36. package/docs-site-docusaurus/docs/api/classes/UndirectedGraph.md +20 -20
  37. package/package.json +45 -46
  38. package/src/common/error.ts +15 -32
  39. package/src/common/index.ts +0 -3
  40. package/src/data-structures/base/iterable-element-base.ts +0 -3
  41. package/src/data-structures/base/linear-base.ts +2 -36
  42. package/src/data-structures/binary-tree/avl-tree.ts +31 -529
  43. package/src/data-structures/binary-tree/binary-indexed-tree.ts +47 -572
  44. package/src/data-structures/binary-tree/binary-tree.ts +326 -1311
  45. package/src/data-structures/binary-tree/bst.ts +158 -1082
  46. package/src/data-structures/binary-tree/red-black-tree.ts +451 -1290
  47. package/src/data-structures/binary-tree/segment-tree.ts +73 -351
  48. package/src/data-structures/binary-tree/tree-map.ts +462 -5124
  49. package/src/data-structures/binary-tree/tree-multi-map.ts +302 -4914
  50. package/src/data-structures/binary-tree/tree-multi-set.ts +284 -3972
  51. package/src/data-structures/binary-tree/tree-set.ts +338 -4836
  52. package/src/data-structures/graph/abstract-graph.ts +98 -167
  53. package/src/data-structures/graph/directed-graph.ts +137 -562
  54. package/src/data-structures/graph/map-graph.ts +0 -3
  55. package/src/data-structures/graph/undirected-graph.ts +132 -511
  56. package/src/data-structures/hash/hash-map.ts +154 -582
  57. package/src/data-structures/heap/heap.ts +200 -795
  58. package/src/data-structures/linked-list/doubly-linked-list.ts +121 -865
  59. package/src/data-structures/linked-list/singly-linked-list.ts +122 -794
  60. package/src/data-structures/linked-list/skip-linked-list.ts +211 -918
  61. package/src/data-structures/matrix/matrix.ts +179 -518
  62. package/src/data-structures/matrix/navigator.ts +0 -1
  63. package/src/data-structures/priority-queue/max-priority-queue.ts +1 -6
  64. package/src/data-structures/priority-queue/min-priority-queue.ts +6 -11
  65. package/src/data-structures/priority-queue/priority-queue.ts +1 -2
  66. package/src/data-structures/queue/deque.ts +214 -882
  67. package/src/data-structures/queue/queue.ts +102 -625
  68. package/src/data-structures/stack/stack.ts +76 -505
  69. package/src/data-structures/trie/trie.ts +98 -628
  70. package/src/types/common.ts +0 -10
  71. package/src/types/data-structures/binary-tree/bst.ts +0 -7
  72. package/src/types/data-structures/binary-tree/red-black-tree.ts +0 -1
  73. package/src/types/data-structures/graph/abstract-graph.ts +0 -2
  74. package/src/types/data-structures/hash/hash-map.ts +0 -3
  75. package/src/types/data-structures/hash/index.ts +0 -1
  76. package/src/types/data-structures/matrix/navigator.ts +0 -2
  77. package/src/types/utils/utils.ts +0 -7
  78. package/src/types/utils/validate-type.ts +0 -7
  79. package/src/utils/number.ts +0 -2
  80. package/src/utils/utils.ts +0 -5
@@ -4,7 +4,6 @@
4
4
  * @author Pablo Zeng
5
5
  * @license MIT License
6
6
  */
7
-
8
7
  export type SegmentTreeOptions<E> = {
9
8
  merger: (a: E, b: E) => E;
10
9
  identity: E;
@@ -30,27 +29,22 @@ export type SegmentTreeOptions<E> = {
30
29
  export class SegmentTree<E = number> implements Iterable<E> {
31
30
  protected readonly _merger: (a: E, b: E) => E;
32
31
  protected readonly _identity: E;
33
- protected _n: number; // number of leaf elements
34
- protected _tree: E[]; // flat array, 1-indexed, size 2*_size
35
- protected _treeSize: number; // internal tree size (next power of 2 >= _n)
36
-
32
+ protected _n: number; // number of leaf elements
33
+ protected _tree: E[]; // flat array, 1-indexed, size 2*_size
34
+ protected _treeSize: number; // internal tree size (next power of 2 >= _n)
37
35
  constructor(elements: E[], options: SegmentTreeOptions<E>) {
38
36
  this._merger = options.merger;
39
37
  this._identity = options.identity;
40
38
  this._n = elements.length;
41
-
42
39
  // Round up to next power of 2
43
40
  this._treeSize = 1;
44
41
  while (this._treeSize < this._n) this._treeSize <<= 1;
45
-
46
42
  // Allocate and fill with identity
47
43
  this._tree = new Array(2 * this._treeSize).fill(this._identity);
48
-
49
44
  // Place elements in leaves
50
45
  for (let i = 0; i < this._n; i++) {
51
46
  this._tree[this._treeSize + i] = elements[i];
52
47
  }
53
-
54
48
  // Build internal nodes bottom-up
55
49
  for (let i = this._treeSize - 1; i >= 1; i--) {
56
50
  this._tree[i] = this._merger(this._tree[2 * i], this._tree[2 * i + 1]);
@@ -59,6 +53,11 @@ export class SegmentTree<E = number> implements Iterable<E> {
59
53
 
60
54
  // ─── Convenience factories ─────────────────────────────────
61
55
 
56
+ // ─── Standard interface ────────────────────────────────────
57
+ get size(): number {
58
+ return this._n;
59
+ }
60
+
62
61
  /**
63
62
  * Create a sum segment tree.
64
63
  * @example
@@ -78,60 +77,18 @@ export class SegmentTree<E = number> implements Iterable<E> {
78
77
 
79
78
  /**
80
79
  * Create a min segment tree.
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
-
108
-
109
-
110
-
111
-
112
-
113
-
114
-
115
-
116
-
117
-
118
-
119
-
120
-
121
-
122
-
123
- * @example
124
- * // Temperature monitoring with range queries
125
- * // Hourly temperatures for a day (24 readings)
126
- * const temps = [18, 17, 16, 15, 16, 18, 21, 24, 27, 29, 31, 32, 33, 32, 31, 29, 27, 25, 23, 21, 20, 19, 18, 17];
127
- * const tree = SegmentTree.sum(temps);
128
- *
129
- * // Average temperature during work hours (9-17)
130
- * const workSum = tree.query(9, 17);
131
- * console.log(workSum / 9); // toBeCloseTo;
132
- *
133
- * // Sum of morning temps (6-11)
134
- * console.log(tree.query(6, 11)); // 164;
80
+ * @example
81
+ * // Temperature monitoring with range queries
82
+ * // Hourly temperatures for a day (24 readings)
83
+ * const temps = [18, 17, 16, 15, 16, 18, 21, 24, 27, 29, 31, 32, 33, 32, 31, 29, 27, 25, 23, 21, 20, 19, 18, 17];
84
+ * const tree = SegmentTree.sum(temps);
85
+ *
86
+ * // Average temperature during work hours (9-17)
87
+ * const workSum = tree.query(9, 17);
88
+ * console.log(workSum / 9); // toBeCloseTo;
89
+ *
90
+ * // Sum of morning temps (6-11)
91
+ * console.log(tree.query(6, 11)); // 164;
135
92
  */
136
93
  static min(elements: number[]): SegmentTree<number> {
137
94
  return new SegmentTree<number>(elements, {
@@ -140,6 +97,8 @@ export class SegmentTree<E = number> implements Iterable<E> {
140
97
  });
141
98
  }
142
99
 
100
+ // ─── Core operations ───────────────────────────────────────
101
+
143
102
  /**
144
103
  * Create a max segment tree.
145
104
  * @example
@@ -155,77 +114,31 @@ export class SegmentTree<E = number> implements Iterable<E> {
155
114
  });
156
115
  }
157
116
 
158
- // ─── Core operations ───────────────────────────────────────
159
-
160
117
  /**
161
118
  * Point update: set element at index to value.
162
119
  * Time: O(log n)
163
-
164
-
165
-
166
-
167
-
168
-
169
-
170
-
171
-
172
-
173
-
174
-
175
-
176
-
177
-
178
-
179
-
180
-
181
-
182
-
183
-
184
-
185
-
186
-
187
-
188
-
189
-
190
-
191
-
192
-
193
-
194
-
195
-
196
-
197
-
198
-
199
-
200
-
201
-
202
-
203
-
204
-
205
- * @example
206
- * // Dynamic range sum with updates
207
- * // Monthly revenue data (in thousands)
208
- * const revenue = [120, 95, 140, 110, 85, 130, 150, 100, 160, 125, 90, 175];
209
- * const tree = SegmentTree.sum(revenue);
210
- *
211
- * // Q1 revenue (Jan-Mar)
212
- * console.log(tree.query(0, 2)); // 355;
213
- *
214
- * // Update March revenue from 140 to 200
215
- * tree.update(2, 200);
216
- *
217
- * // Q1 revenue after update
218
- * console.log(tree.query(0, 2)); // 415;
219
- *
220
- * // H1 revenue (Jan-Jun)
221
- * console.log(tree.query(0, 5)); // 740;
120
+ * @example
121
+ * // Dynamic range sum with updates
122
+ * // Monthly revenue data (in thousands)
123
+ * const revenue = [120, 95, 140, 110, 85, 130, 150, 100, 160, 125, 90, 175];
124
+ * const tree = SegmentTree.sum(revenue);
125
+ *
126
+ * // Q1 revenue (Jan-Mar)
127
+ * console.log(tree.query(0, 2)); // 355;
128
+ *
129
+ * // Update March revenue from 140 to 200
130
+ * tree.update(2, 200);
131
+ *
132
+ * // Q1 revenue after update
133
+ * console.log(tree.query(0, 2)); // 415;
134
+ *
135
+ * // H1 revenue (Jan-Jun)
136
+ * console.log(tree.query(0, 5)); // 740;
222
137
  */
223
138
  update(index: number, value: E): void {
224
139
  if (index < 0 || index >= this._n) return;
225
-
226
140
  let pos = this._treeSize + index;
227
141
  this._tree[pos] = value;
228
-
229
142
  // Propagate up
230
143
  pos >>= 1;
231
144
  while (pos >= 1) {
@@ -237,71 +150,27 @@ export class SegmentTree<E = number> implements Iterable<E> {
237
150
  /**
238
151
  * Range query: returns merger result over [start, end] (inclusive).
239
152
  * Time: O(log n)
240
-
241
-
242
-
243
-
244
-
245
-
246
-
247
-
248
-
249
-
250
-
251
-
252
-
253
-
254
-
255
-
256
-
257
-
258
-
259
-
260
-
261
-
262
-
263
-
264
-
265
-
266
-
267
-
268
-
269
-
270
-
271
-
272
-
273
-
274
-
275
-
276
-
277
-
278
-
279
-
280
-
281
-
282
- * @example
283
- * // Range sum query on an array
284
- * const tree = SegmentTree.sum([1, 3, 5, 7, 9, 11]);
285
- *
286
- * // Query sum of range [1, 3] → 3 + 5 + 7 = 15
287
- * console.log(tree.query(1, 3)); // 15;
288
- *
289
- * // Query entire range
290
- * console.log(tree.query(0, 5)); // 36;
291
- *
292
- * // Query single element
293
- * console.log(tree.query(2, 2)); // 5;
153
+ * @example
154
+ * // Range sum query on an array
155
+ * const tree = SegmentTree.sum([1, 3, 5, 7, 9, 11]);
156
+ *
157
+ * // Query sum of range [1, 3] → 3 + 5 + 7 = 15
158
+ * console.log(tree.query(1, 3)); // 15;
159
+ *
160
+ * // Query entire range
161
+ * console.log(tree.query(0, 5)); // 36;
162
+ *
163
+ * // Query single element
164
+ * console.log(tree.query(2, 2)); // 5;
294
165
  */
295
166
  query(start: number, end: number): E {
296
167
  if (start < 0) start = 0;
297
168
  if (end >= this._n) end = this._n - 1;
298
169
  if (start > end) return this._identity;
299
-
300
170
  let resultLeft = this._identity;
301
171
  let resultRight = this._identity;
302
172
  let left = this._treeSize + start;
303
173
  let right = this._treeSize + end + 1; // exclusive
304
-
305
174
  while (left < right) {
306
175
  if (left & 1) {
307
176
  resultLeft = this._merger(resultLeft, this._tree[left]);
@@ -314,132 +183,44 @@ export class SegmentTree<E = number> implements Iterable<E> {
314
183
  left >>= 1;
315
184
  right >>= 1;
316
185
  }
317
-
318
186
  return this._merger(resultLeft, resultRight);
319
187
  }
320
188
 
189
+ // ─── Binary search on tree (ACL-style) ─────────────────────
190
+
321
191
  /**
322
192
  * Get element at index.
323
193
  * Time: O(1)
324
-
325
-
326
-
327
-
328
-
329
-
330
-
331
-
332
-
333
-
334
-
335
-
336
-
337
-
338
-
339
-
340
-
341
-
342
-
343
-
344
-
345
-
346
-
347
-
348
-
349
-
350
-
351
-
352
-
353
-
354
-
355
-
356
-
357
-
358
-
359
-
360
-
361
-
362
-
363
-
364
-
365
-
366
- * @example
367
- * // Point access on segment tree
368
- * const st = SegmentTree.sum([10, 20, 30, 40]);
369
- * console.log(st.get(0)); // 10;
370
- * console.log(st.get(2)); // 30;
194
+ * @example
195
+ * // Point access on segment tree
196
+ * const st = SegmentTree.sum([10, 20, 30, 40]);
197
+ * console.log(st.get(0)); // 10;
198
+ * console.log(st.get(2)); // 30;
371
199
  */
372
200
  get(index: number): E {
373
201
  if (index < 0 || index >= this._n) return this._identity;
374
202
  return this._tree[this._treeSize + index];
375
203
  }
376
204
 
377
- // ─── Binary search on tree (ACL-style) ─────────────────────
378
-
379
205
  /**
380
206
  * Find the largest r such that predicate(query(left, r)) is true.
381
207
  * Returns left-1 if predicate(identity) is false.
382
208
  * Returns n-1 if predicate holds for the entire range [left, n-1].
383
209
  * Time: O(log n)
384
-
385
-
386
-
387
-
388
-
389
-
390
-
391
-
392
-
393
-
394
-
395
-
396
-
397
-
398
-
399
-
400
-
401
-
402
-
403
-
404
-
405
-
406
-
407
-
408
-
409
-
410
-
411
-
412
-
413
-
414
-
415
-
416
-
417
-
418
-
419
-
420
-
421
-
422
-
423
-
424
-
425
-
426
- * @example
427
- * // Find rightmost position where predicate holds
428
- * // Prefix sums: find the rightmost index where prefix sum < 10
429
- * const st = SegmentTree.sum([3, 1, 4, 1, 5]);
430
- * // maxRight(0, sum => sum < 10) — prefix [3,4,8,9,14]
431
- * // sum < 10 holds through index 3 (prefix=9), fails at 4 (prefix=14)
432
- * const result = st.maxRight(0, sum => sum < 10);
433
- * console.log(result); // 3;
210
+ * @example
211
+ * // Find rightmost position where predicate holds
212
+ * // Prefix sums: find the rightmost index where prefix sum < 10
213
+ * const st = SegmentTree.sum([3, 1, 4, 1, 5]);
214
+ * // maxRight(0, sum => sum < 10) — prefix [3,4,8,9,14]
215
+ * // sum < 10 holds through index 3 (prefix=9), fails at 4 (prefix=14)
216
+ * const result = st.maxRight(0, sum => sum < 10);
217
+ * console.log(result); // 3;
434
218
  */
435
219
  maxRight(left: number, predicate: (segValue: E) => boolean): number {
436
220
  if (left >= this._n) return this._n - 1;
437
-
438
221
  let acc = this._identity;
439
222
  if (!predicate(acc)) return left - 1;
440
-
441
223
  let pos = this._treeSize + left;
442
-
443
224
  // Go up while we're a right child or predicate still holds
444
225
  while (true) {
445
226
  // Find the lowest relevant node
@@ -453,19 +234,16 @@ export class SegmentTree<E = number> implements Iterable<E> {
453
234
  pos = 2 * pos; // go left (dig deeper)
454
235
  }
455
236
  }
456
-
457
237
  // At leaf level
458
238
  const combined = this._merger(acc, this._tree[pos]);
459
239
  if (!predicate(combined)) {
460
240
  return pos - this._treeSize - 1;
461
241
  }
462
242
  acc = combined;
463
-
464
243
  // Move to next segment
465
244
  pos++;
466
245
  // Check if we've gone past the end
467
246
  if (pos - this._treeSize >= this._n) return this._n - 1;
468
-
469
247
  // Go up while we're a right child
470
248
  while (pos > 1 && (pos & 1) === 0) {
471
249
  pos >>= 1;
@@ -480,65 +258,20 @@ export class SegmentTree<E = number> implements Iterable<E> {
480
258
  * Returns right+1 if predicate(identity) is false.
481
259
  * Returns 0 if predicate holds for the entire range [0, right].
482
260
  * Time: O(log n)
483
-
484
-
485
-
486
-
487
-
488
-
489
-
490
-
491
-
492
-
493
-
494
-
495
-
496
-
497
-
498
-
499
-
500
-
501
-
502
-
503
-
504
-
505
-
506
-
507
-
508
-
509
-
510
-
511
-
512
-
513
-
514
-
515
-
516
-
517
-
518
-
519
-
520
-
521
-
522
-
523
-
524
-
525
- * @example
526
- * // Find leftmost position where predicate holds
527
- * const st = SegmentTree.sum([3, 1, 4, 1, 5]);
528
- * // minLeft(5, sum => sum < 7) — suffix sums from right
529
- * // From right: [5]=5 < 7, [1,5]=6 < 7, [4,1,5]=10 ≥ 7
530
- * const result = st.minLeft(5, sum => sum < 7);
531
- * console.log(result); // 3;
261
+ * @example
262
+ * // Find leftmost position where predicate holds
263
+ * const st = SegmentTree.sum([3, 1, 4, 1, 5]);
264
+ * // minLeft(5, sum => sum < 7) — suffix sums from right
265
+ * // From right: [5]=5 < 7, [1,5]=6 < 7, [4,1,5]=10 ≥ 7
266
+ * const result = st.minLeft(5, sum => sum < 7);
267
+ * console.log(result); // 3;
532
268
  */
533
269
  minLeft(right: number, predicate: (segValue: E) => boolean): number {
534
270
  if (right < 0) return 0;
535
271
  if (right >= this._n) right = this._n - 1;
536
-
537
272
  let acc = this._identity;
538
273
  if (!predicate(acc)) return right + 1;
539
-
540
274
  let pos = this._treeSize + right;
541
-
542
275
  while (true) {
543
276
  while (pos < this._treeSize) {
544
277
  const combined = this._merger(this._tree[2 * pos + 1], acc);
@@ -549,17 +282,14 @@ export class SegmentTree<E = number> implements Iterable<E> {
549
282
  pos = 2 * pos + 1; // go right (dig deeper)
550
283
  }
551
284
  }
552
-
553
285
  const combined = this._merger(this._tree[pos], acc);
554
286
  if (!predicate(combined)) {
555
287
  return pos - this._treeSize + 1;
556
288
  }
557
289
  acc = combined;
558
-
559
290
  // Move to previous segment
560
291
  if (pos === this._treeSize) return 0;
561
292
  pos--;
562
-
563
293
  // Go up while we're a left child
564
294
  while (pos > 1 && (pos & 1) === 1) {
565
295
  pos >>= 1;
@@ -569,12 +299,6 @@ export class SegmentTree<E = number> implements Iterable<E> {
569
299
  }
570
300
  }
571
301
 
572
- // ─── Standard interface ────────────────────────────────────
573
-
574
- get size(): number {
575
- return this._n;
576
- }
577
-
578
302
  isEmpty(): boolean {
579
303
  return this._n === 0;
580
304
  }
@@ -629,5 +353,3 @@ export class SegmentTree<E = number> implements Iterable<E> {
629
353
  console.log(this.toArray());
630
354
  }
631
355
  }
632
-
633
-