max-priority-queue-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.
Files changed (85) hide show
  1. package/README.md +63 -0
  2. package/dist/cjs/index.cjs +403 -98
  3. package/dist/cjs/index.cjs.map +1 -1
  4. package/dist/cjs-legacy/index.cjs +402 -97
  5. package/dist/cjs-legacy/index.cjs.map +1 -1
  6. package/dist/esm/index.mjs +403 -99
  7. package/dist/esm/index.mjs.map +1 -1
  8. package/dist/esm-legacy/index.mjs +402 -98
  9. package/dist/esm-legacy/index.mjs.map +1 -1
  10. package/dist/types/common/error.d.ts +23 -0
  11. package/dist/types/common/index.d.ts +1 -0
  12. package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
  13. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +128 -51
  14. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +210 -164
  15. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +439 -78
  16. package/dist/types/data-structures/binary-tree/bst.d.ts +311 -28
  17. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +217 -31
  18. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +218 -152
  19. package/dist/types/data-structures/binary-tree/tree-map.d.ts +1281 -5
  20. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1087 -201
  21. package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +858 -65
  22. package/dist/types/data-structures/binary-tree/tree-set.d.ts +1133 -5
  23. package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
  24. package/dist/types/data-structures/graph/directed-graph.d.ts +220 -47
  25. package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
  26. package/dist/types/data-structures/graph/undirected-graph.d.ts +218 -59
  27. package/dist/types/data-structures/hash/hash-map.d.ts +230 -77
  28. package/dist/types/data-structures/heap/heap.d.ts +287 -99
  29. package/dist/types/data-structures/heap/max-heap.d.ts +46 -0
  30. package/dist/types/data-structures/heap/min-heap.d.ts +59 -0
  31. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +286 -44
  32. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +278 -65
  33. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +415 -12
  34. package/dist/types/data-structures/matrix/matrix.d.ts +331 -0
  35. package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +57 -0
  36. package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +60 -0
  37. package/dist/types/data-structures/priority-queue/priority-queue.d.ts +60 -0
  38. package/dist/types/data-structures/queue/deque.d.ts +313 -66
  39. package/dist/types/data-structures/queue/queue.d.ts +211 -42
  40. package/dist/types/data-structures/stack/stack.d.ts +174 -32
  41. package/dist/types/data-structures/trie/trie.d.ts +213 -43
  42. package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
  43. package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
  44. package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
  45. package/dist/umd/max-priority-queue-typed.js +400 -95
  46. package/dist/umd/max-priority-queue-typed.js.map +1 -1
  47. package/dist/umd/max-priority-queue-typed.min.js +1 -1
  48. package/dist/umd/max-priority-queue-typed.min.js.map +1 -1
  49. package/package.json +2 -2
  50. package/src/common/error.ts +60 -0
  51. package/src/common/index.ts +2 -0
  52. package/src/data-structures/base/iterable-element-base.ts +2 -2
  53. package/src/data-structures/binary-tree/avl-tree.ts +134 -51
  54. package/src/data-structures/binary-tree/binary-indexed-tree.ts +303 -247
  55. package/src/data-structures/binary-tree/binary-tree.ts +542 -121
  56. package/src/data-structures/binary-tree/bst.ts +346 -37
  57. package/src/data-structures/binary-tree/red-black-tree.ts +309 -96
  58. package/src/data-structures/binary-tree/segment-tree.ts +372 -248
  59. package/src/data-structures/binary-tree/tree-map.ts +1292 -13
  60. package/src/data-structures/binary-tree/tree-multi-map.ts +1098 -215
  61. package/src/data-structures/binary-tree/tree-multi-set.ts +863 -69
  62. package/src/data-structures/binary-tree/tree-set.ts +1143 -15
  63. package/src/data-structures/graph/abstract-graph.ts +106 -1
  64. package/src/data-structures/graph/directed-graph.ts +223 -47
  65. package/src/data-structures/graph/map-graph.ts +59 -1
  66. package/src/data-structures/graph/undirected-graph.ts +299 -59
  67. package/src/data-structures/hash/hash-map.ts +243 -79
  68. package/src/data-structures/heap/heap.ts +291 -102
  69. package/src/data-structures/heap/max-heap.ts +48 -3
  70. package/src/data-structures/heap/min-heap.ts +59 -0
  71. package/src/data-structures/linked-list/doubly-linked-list.ts +286 -44
  72. package/src/data-structures/linked-list/singly-linked-list.ts +278 -65
  73. package/src/data-structures/linked-list/skip-linked-list.ts +689 -90
  74. package/src/data-structures/matrix/matrix.ts +425 -22
  75. package/src/data-structures/priority-queue/max-priority-queue.ts +59 -3
  76. package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
  77. package/src/data-structures/priority-queue/priority-queue.ts +60 -0
  78. package/src/data-structures/queue/deque.ts +343 -68
  79. package/src/data-structures/queue/queue.ts +211 -42
  80. package/src/data-structures/stack/stack.ts +174 -32
  81. package/src/data-structures/trie/trie.ts +215 -44
  82. package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
  83. package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
  84. package/src/types/data-structures/queue/deque.ts +7 -0
  85. package/src/utils/utils.ts +4 -2
@@ -11,6 +11,66 @@ import { Heap } from '../heap';
11
11
 
12
12
  /**
13
13
  * @example
14
+ * // Hospital emergency room triage
15
+ * interface Patient {
16
+ * name: string;
17
+ * severity: number; // 1 = critical, 5 = minor
18
+ * }
19
+ *
20
+ * const er = new PriorityQueue<Patient>([], {
21
+ * comparator: (a, b) => a.severity - b.severity
22
+ * });
23
+ *
24
+ * er.add({ name: 'Flu symptoms', severity: 4 });
25
+ * er.add({ name: 'Heart attack', severity: 1 });
26
+ * er.add({ name: 'Broken arm', severity: 3 });
27
+ * er.add({ name: 'Stroke', severity: 1 });
28
+ *
29
+ * // Most critical patients first
30
+ * console.log(er.poll()?.severity); // 1;
31
+ * console.log(er.poll()?.severity); // 1;
32
+ * console.log(er.poll()?.severity); // 3;
33
+ * console.log(er.poll()?.severity); // 4;
34
+ * @example
35
+ * // Task scheduler with deadlines
36
+ * interface Task {
37
+ * name: string;
38
+ * deadline: number; // hours until due
39
+ * }
40
+ *
41
+ * const scheduler = new PriorityQueue<Task>([], {
42
+ * comparator: (a, b) => a.deadline - b.deadline
43
+ * });
44
+ *
45
+ * scheduler.add({ name: 'Report', deadline: 24 });
46
+ * scheduler.add({ name: 'Email', deadline: 2 });
47
+ * scheduler.add({ name: 'Meeting prep', deadline: 4 });
48
+ * scheduler.add({ name: 'Code review', deadline: 8 });
49
+ *
50
+ * // Process most urgent first
51
+ * console.log(scheduler.peek()?.name); // 'Email';
52
+ * console.log(scheduler.size); // 4;
53
+ *
54
+ * const order = [];
55
+ * while (scheduler.size > 0) {
56
+ * order.push(scheduler.poll()!.name);
57
+ * }
58
+ * console.log(order); // ['Email', 'Meeting prep', 'Code review', 'Report'];
59
+ * @example
60
+ * // Bandwidth allocation with priorities
61
+ * const bandwidth = new PriorityQueue<[number, string]>([], {
62
+ * comparator: (a, b) => a[0] - b[0]
63
+ * });
64
+ *
65
+ * bandwidth.add([1, 'Video call']); // highest priority
66
+ * bandwidth.add([3, 'File download']);
67
+ * bandwidth.add([2, 'Web browsing']);
68
+ * bandwidth.add([1, 'Voice call']);
69
+ *
70
+ * // Allocate bandwidth to highest priority first
71
+ * console.log(bandwidth.poll()?.[1]); // 'Video call';
72
+ * console.log(bandwidth.poll()?.[1]); // 'Voice call';
73
+ * console.log(bandwidth.size); // 2;
14
74
  */
15
75
  export class PriorityQueue<E = any, R = any> extends Heap<E, R> {
16
76
  constructor(elements: Iterable<E> | Iterable<R> = [], options?: PriorityQueueOptions<E, R>) {
@@ -27,71 +27,6 @@ import { LinearBase } from '../base/linear-base';
27
27
  * 4. Efficiency: Adding and removing elements at both ends of a deque is usually very fast. However, when the dynamic array needs to expand, it may involve copying the entire array to a larger one, and this operation has a time complexity of O(n).
28
28
  * 5. Performance jitter: Deque may experience performance jitter, but DoublyLinkedList will not
29
29
  * @example
30
- * // basic Deque creation and push/pop operations
31
- * // Create a simple Deque with initial values
32
- * const deque = new Deque([1, 2, 3, 4, 5]);
33
- *
34
- * // Verify the deque maintains insertion order
35
- * console.log([...deque]); // [1, 2, 3, 4, 5];
36
- *
37
- * // Check length
38
- * console.log(deque.length); // 5;
39
- *
40
- * // Push to the end
41
- * deque.push(6);
42
- * console.log(deque.length); // 6;
43
- *
44
- * // Pop from the end
45
- * const last = deque.pop();
46
- * console.log(last); // 6;
47
- * @example
48
- * // Deque shift and unshift operations
49
- * const deque = new Deque<number>([20, 30, 40]);
50
- *
51
- * // Unshift adds to the front
52
- * deque.unshift(10);
53
- * console.log([...deque]); // [10, 20, 30, 40];
54
- *
55
- * // Shift removes from the front (O(1) complexity!)
56
- * const first = deque.shift();
57
- * console.log(first); // 10;
58
- *
59
- * // Verify remaining elements
60
- * console.log([...deque]); // [20, 30, 40];
61
- * console.log(deque.length); // 3;
62
- * @example
63
- * // Deque peek at both ends
64
- * const deque = new Deque<number>([10, 20, 30, 40, 50]);
65
- *
66
- * // Get first element without removing
67
- * const first = deque.at(0);
68
- * console.log(first); // 10;
69
- *
70
- * // Get last element without removing
71
- * const last = deque.at(deque.length - 1);
72
- * console.log(last); // 50;
73
- *
74
- * // Length unchanged
75
- * console.log(deque.length); // 5;
76
- * @example
77
- * // Deque for...of iteration and reverse
78
- * const deque = new Deque<string>(['A', 'B', 'C', 'D']);
79
- *
80
- * // Iterate forward
81
- * const forward: string[] = [];
82
- * for (const item of deque) {
83
- * forward.push(item);
84
- * }
85
- * console.log(forward); // ['A', 'B', 'C', 'D'];
86
- *
87
- * // Reverse the deque
88
- * deque.reverse();
89
- * const backward: string[] = [];
90
- * for (const item of deque) {
91
- * backward.push(item);
92
- * }
93
- * console.log(backward); // ['D', 'C', 'B', 'A'];
94
- * @example
95
30
  * // Deque as sliding window for stream processing
96
31
  * interface DataPoint {
97
32
  * timestamp: number;
@@ -142,6 +77,10 @@ import { LinearBase } from '../base/linear-base';
142
77
  * console.log(windowResults[2].windowSize); // 3; // Windows are at max size from 3rd onwards
143
78
  * console.log(windowResults[4].windowSize); // 3; // Last window still has 3 elements
144
79
  * console.log(dataWindow.length); // 3;
80
+ * @example
81
+ * // Convert deque to array
82
+ * const dq = new Deque<number>([10, 20, 30]);
83
+ * console.log(dq.toArray()); // [10, 20, 30];
145
84
  */
146
85
  export class Deque<E = any, R = any> extends LinearBase<E, R> {
147
86
  protected _equals: (a: E, b: E) => boolean = (a, b) => Object.is(a, b);
@@ -154,12 +93,15 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
154
93
  * @returns New Deque instance.
155
94
  */
156
95
 
96
+ constructor(elements?: IterableWithSizeOrLength<E>, options?: DequeOptions<E, R>);
97
+ constructor(elements: IterableWithSizeOrLength<R>, options: DequeOptions<E, R> & { toElementFn: (rawElement: R) => E });
157
98
  constructor(elements: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R> = [], options?: DequeOptions<E, R>) {
158
99
  super(options);
159
100
 
160
101
  if (options) {
161
- const { bucketSize } = options;
102
+ const { bucketSize, autoCompactRatio } = options;
162
103
  if (typeof bucketSize === 'number') this._bucketSize = bucketSize;
104
+ if (typeof autoCompactRatio === 'number') this._autoCompactRatio = autoCompactRatio;
163
105
  }
164
106
 
165
107
  let _size: number;
@@ -191,6 +133,34 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
191
133
  return this._bucketSize;
192
134
  }
193
135
 
136
+ protected _autoCompactRatio = 0.5;
137
+
138
+ /**
139
+ * Get the auto-compaction ratio.
140
+ * When `elements / (bucketCount * bucketSize)` drops below this ratio after
141
+ * enough shift/pop operations, the deque auto-compacts.
142
+ * @remarks Time O(1), Space O(1)
143
+ * @returns Current ratio threshold. 0 means auto-compact is disabled.
144
+ */
145
+ get autoCompactRatio(): number {
146
+ return this._autoCompactRatio;
147
+ }
148
+
149
+ /**
150
+ * Set the auto-compaction ratio.
151
+ * @remarks Time O(1), Space O(1)
152
+ * @param value - Ratio in [0,1]. 0 disables auto-compact.
153
+ */
154
+ set autoCompactRatio(value: number) {
155
+ this._autoCompactRatio = value;
156
+ }
157
+
158
+ /**
159
+ * Counter for shift/pop operations since last compaction check.
160
+ * Only checks ratio every `_bucketSize` operations to minimize overhead.
161
+ */
162
+ protected _compactCounter = 0;
163
+
194
164
  protected _bucketFirst = 0;
195
165
 
196
166
  /**
@@ -279,6 +249,31 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
279
249
  * Get the first element without removing it.
280
250
  * @remarks Time O(1), Space O(1)
281
251
  * @returns First element or undefined.
252
+
253
+
254
+
255
+
256
+
257
+
258
+
259
+
260
+
261
+
262
+
263
+ * @example
264
+ * // Deque peek at both ends
265
+ * const deque = new Deque<number>([10, 20, 30, 40, 50]);
266
+ *
267
+ * // Get first element without removing
268
+ * const first = deque.at(0);
269
+ * console.log(first); // 10;
270
+ *
271
+ * // Get last element without removing
272
+ * const last = deque.at(deque.length - 1);
273
+ * console.log(last); // 50;
274
+ *
275
+ * // Length unchanged
276
+ * console.log(deque.length); // 5;
282
277
  */
283
278
 
284
279
  get first(): E | undefined {
@@ -290,6 +285,22 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
290
285
  * Get the last element without removing it.
291
286
  * @remarks Time O(1), Space O(1)
292
287
  * @returns Last element or undefined.
288
+
289
+
290
+
291
+
292
+
293
+
294
+
295
+
296
+
297
+
298
+
299
+ * @example
300
+ * // Peek at the back element
301
+ * const dq = new Deque<string>(['a', 'b', 'c']);
302
+ * console.log(dq.last); // 'c';
303
+ * console.log(dq.first); // 'a';
293
304
  */
294
305
 
295
306
  get last(): E | undefined {
@@ -324,6 +335,35 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
324
335
  * @remarks Time O(1) amortized, Space O(1)
325
336
  * @param element - Element to append.
326
337
  * @returns True when appended.
338
+
339
+
340
+
341
+
342
+
343
+
344
+
345
+
346
+
347
+
348
+
349
+ * @example
350
+ * // basic Deque creation and push/pop operations
351
+ * // Create a simple Deque with initial values
352
+ * const deque = new Deque([1, 2, 3, 4, 5]);
353
+ *
354
+ * // Verify the deque maintains insertion order
355
+ * console.log([...deque]); // [1, 2, 3, 4, 5];
356
+ *
357
+ * // Check length
358
+ * console.log(deque.length); // 5;
359
+ *
360
+ * // Push to the end
361
+ * deque.push(6);
362
+ * console.log(deque.length); // 6;
363
+ *
364
+ * // Pop from the end
365
+ * const last = deque.pop();
366
+ * console.log(last); // 6;
327
367
  */
328
368
 
329
369
  push(element: E): boolean {
@@ -349,6 +389,22 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
349
389
  * Remove and return the last element.
350
390
  * @remarks Time O(1), Space O(1)
351
391
  * @returns Removed element or undefined.
392
+
393
+
394
+
395
+
396
+
397
+
398
+
399
+
400
+
401
+
402
+
403
+ * @example
404
+ * // Remove from the back
405
+ * const dq = new Deque<number>([1, 2, 3]);
406
+ * console.log(dq.pop()); // 3;
407
+ * console.log(dq.length); // 2;
352
408
  */
353
409
 
354
410
  pop(): E | undefined {
@@ -366,6 +422,7 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
366
422
  }
367
423
  }
368
424
  this._length -= 1;
425
+ this._autoCompact();
369
426
  return element;
370
427
  }
371
428
 
@@ -373,6 +430,22 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
373
430
  * Remove and return the first element.
374
431
  * @remarks Time O(1) amortized, Space O(1)
375
432
  * @returns Removed element or undefined.
433
+
434
+
435
+
436
+
437
+
438
+
439
+
440
+
441
+
442
+
443
+
444
+ * @example
445
+ * // Remove from the front
446
+ * const dq = new Deque<number>([1, 2, 3]);
447
+ * console.log(dq.shift()); // 1;
448
+ * console.log(dq.length); // 2;
376
449
  */
377
450
 
378
451
  shift(): E | undefined {
@@ -390,6 +463,7 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
390
463
  }
391
464
  }
392
465
  this._length -= 1;
466
+ this._autoCompact();
393
467
  return element;
394
468
  }
395
469
 
@@ -398,6 +472,32 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
398
472
  * @remarks Time O(1) amortized, Space O(1)
399
473
  * @param element - Element to prepend.
400
474
  * @returns True when prepended.
475
+
476
+
477
+
478
+
479
+
480
+
481
+
482
+
483
+
484
+
485
+
486
+ * @example
487
+ * // Deque shift and unshift operations
488
+ * const deque = new Deque<number>([20, 30, 40]);
489
+ *
490
+ * // Unshift adds to the front
491
+ * deque.unshift(10);
492
+ * console.log([...deque]); // [10, 20, 30, 40];
493
+ *
494
+ * // Shift removes from the front (O(1) complexity!)
495
+ * const first = deque.shift();
496
+ * console.log(first); // 10;
497
+ *
498
+ * // Verify remaining elements
499
+ * console.log([...deque]); // [20, 30, 40];
500
+ * console.log(deque.length); // 3;
401
501
  */
402
502
 
403
503
  unshift(element: E): boolean {
@@ -461,6 +561,19 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
461
561
  * Check whether the deque is empty.
462
562
  * @remarks Time O(1), Space O(1)
463
563
  * @returns True if length is 0.
564
+
565
+
566
+
567
+
568
+
569
+
570
+
571
+
572
+
573
+ * @example
574
+ * // Check if empty
575
+ * const dq = new Deque();
576
+ * console.log(dq.isEmpty()); // true;
464
577
  */
465
578
 
466
579
  isEmpty(): boolean {
@@ -471,6 +584,20 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
471
584
  * Remove all elements and reset structure.
472
585
  * @remarks Time O(1), Space O(1)
473
586
  * @returns void
587
+
588
+
589
+
590
+
591
+
592
+
593
+
594
+
595
+
596
+ * @example
597
+ * // Remove all elements
598
+ * const dq = new Deque<number>([1, 2, 3]);
599
+ * dq.clear();
600
+ * console.log(dq.length); // 0;
474
601
  */
475
602
 
476
603
  clear(): void {
@@ -485,6 +612,19 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
485
612
  * @remarks Time O(1), Space O(1)
486
613
  * @param pos - Zero-based position from the front.
487
614
  * @returns Element or undefined.
615
+
616
+
617
+
618
+
619
+
620
+
621
+
622
+
623
+ * @example
624
+ * // Access by index
625
+ * const dq = new Deque<string>(['a', 'b', 'c']);
626
+ * console.log(dq.at(0)); // 'a';
627
+ * console.log(dq.at(2)); // 'c';
488
628
  */
489
629
 
490
630
  at(pos: number): E | undefined {
@@ -672,6 +812,19 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
672
812
  * @remarks Time O(N), Space O(1)
673
813
  * @param element - Element to remove (using the configured equality).
674
814
  * @returns True if an element was removed.
815
+
816
+
817
+
818
+
819
+
820
+
821
+
822
+
823
+ * @example
824
+ * // Remove element
825
+ * const dq = new Deque<number>([1, 2, 3]);
826
+ * dq.delete(2);
827
+ * console.log(dq.length); // 2;
675
828
  */
676
829
 
677
830
  delete(element: E): boolean {
@@ -725,6 +878,35 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
725
878
  * Reverse the deque by reversing buckets and pointers.
726
879
  * @remarks Time O(N), Space O(N)
727
880
  * @returns This deque.
881
+
882
+
883
+
884
+
885
+
886
+
887
+
888
+
889
+
890
+
891
+
892
+ * @example
893
+ * // Deque for...of iteration and reverse
894
+ * const deque = new Deque<string>(['A', 'B', 'C', 'D']);
895
+ *
896
+ * // Iterate forward
897
+ * const forward: string[] = [];
898
+ * for (const item of deque) {
899
+ * forward.push(item);
900
+ * }
901
+ * console.log(forward); // ['A', 'B', 'C', 'D'];
902
+ *
903
+ * // Reverse the deque
904
+ * deque.reverse();
905
+ * const backward: string[] = [];
906
+ * for (const item of deque) {
907
+ * backward.push(item);
908
+ * }
909
+ * console.log(backward); // ['D', 'C', 'B', 'A'];
728
910
  */
729
911
 
730
912
  reverse(): this {
@@ -768,11 +950,59 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
768
950
  * @returns void
769
951
  */
770
952
 
953
+ /**
954
+ * (Protected) Trigger auto-compaction if space utilization drops below threshold.
955
+ * Only checks every `_bucketSize` operations to minimize hot-path overhead.
956
+ * Uses element-based ratio: `elements / (bucketCount * bucketSize)`.
957
+ */
958
+ protected _autoCompact(): void {
959
+ if (this._autoCompactRatio <= 0 || this._bucketCount <= 1) return;
960
+
961
+ this._compactCounter++;
962
+ if (this._compactCounter < this._bucketSize) return;
963
+ this._compactCounter = 0;
964
+
965
+ const utilization = this._length / (this._bucketCount * this._bucketSize);
966
+ if (utilization < this._autoCompactRatio) {
967
+ this.shrinkToFit();
968
+ }
969
+ }
970
+
971
+ /**
972
+ * Compact the deque by removing unused buckets.
973
+ * @remarks Time O(N), Space O(1)
974
+ * @returns True if compaction was performed (bucket count reduced).
975
+ */
976
+ /**
977
+ * Compact the deque by removing unused buckets.
978
+ * @remarks Time O(N), Space O(1)
979
+ * @returns True if compaction was performed (bucket count reduced).
980
+
981
+
982
+
983
+
984
+
985
+
986
+
987
+
988
+ * @example
989
+ * // Reclaim memory
990
+ * const dq = new Deque<number>([1, 2, 3, 4, 5]);
991
+ * dq.shift();
992
+ * dq.shift();
993
+ * dq.compact();
994
+ * console.log(dq.length); // 3;
995
+ */
996
+ compact(): boolean {
997
+ const before = this._bucketCount;
998
+ this.shrinkToFit();
999
+ return this._bucketCount < before;
1000
+ }
1001
+
771
1002
  shrinkToFit(): void {
772
1003
  if (this._length === 0) return;
773
1004
  const newBuckets = [] as E[][];
774
- if (this._bucketFirst === this._bucketLast) return;
775
- else if (this._bucketFirst < this._bucketLast) {
1005
+ if (this._bucketFirst <= this._bucketLast) {
776
1006
  for (let i = this._bucketFirst; i <= this._bucketLast; ++i) {
777
1007
  newBuckets.push(this._buckets[i]);
778
1008
  }
@@ -787,12 +1017,30 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
787
1017
  this._bucketFirst = 0;
788
1018
  this._bucketLast = newBuckets.length - 1;
789
1019
  this._buckets = newBuckets;
1020
+ this._bucketCount = newBuckets.length;
1021
+ this._compactCounter = 0;
790
1022
  }
791
1023
 
792
1024
  /**
793
1025
  * Deep clone this deque, preserving options.
794
1026
  * @remarks Time O(N), Space O(N)
795
1027
  * @returns A new deque with the same content and options.
1028
+
1029
+
1030
+
1031
+
1032
+
1033
+
1034
+
1035
+
1036
+
1037
+ * @example
1038
+ * // Create independent copy
1039
+ * const dq = new Deque<number>([1, 2, 3]);
1040
+ * const copy = dq.clone();
1041
+ * copy.pop();
1042
+ * console.log(dq.length); // 3;
1043
+ * console.log(copy.length); // 2;
796
1044
  */
797
1045
 
798
1046
  clone(): this {
@@ -809,6 +1057,20 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
809
1057
  * @param predicate - Predicate (value, index, deque) → boolean to keep element.
810
1058
  * @param [thisArg] - Value for `this` inside the predicate.
811
1059
  * @returns A new deque with kept elements.
1060
+
1061
+
1062
+
1063
+
1064
+
1065
+
1066
+
1067
+
1068
+
1069
+ * @example
1070
+ * // Filter elements
1071
+ * const dq = new Deque<number>([1, 2, 3, 4]);
1072
+ * const result = dq.filter(x => x > 2);
1073
+ * console.log(result.length); // 2;
812
1074
  */
813
1075
 
814
1076
  filter(predicate: ElementCallback<E, R, boolean>, thisArg?: any): this {
@@ -850,6 +1112,19 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
850
1112
  * @param [options] - Options for the output deque (e.g., bucketSize, toElementFn, maxLen).
851
1113
  * @param [thisArg] - Value for `this` inside the callback.
852
1114
  * @returns A new Deque with mapped elements.
1115
+
1116
+
1117
+
1118
+
1119
+
1120
+
1121
+
1122
+
1123
+ * @example
1124
+ * // Transform elements
1125
+ * const dq = new Deque<number>([1, 2, 3]);
1126
+ * const result = dq.map(x => x * 10);
1127
+ * console.log(result.toArray()); // [10, 20, 30];
853
1128
  */
854
1129
 
855
1130
  map<EM, RM>(