data-structure-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 (80) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +34 -1
  3. package/dist/cjs/index.cjs +10639 -2151
  4. package/dist/cjs-legacy/index.cjs +10694 -2195
  5. package/dist/esm/index.mjs +10639 -2150
  6. package/dist/esm-legacy/index.mjs +10694 -2194
  7. package/dist/types/common/error.d.ts +23 -0
  8. package/dist/types/common/index.d.ts +1 -0
  9. package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
  10. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +128 -51
  11. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +210 -164
  12. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +439 -78
  13. package/dist/types/data-structures/binary-tree/bst.d.ts +311 -28
  14. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +217 -31
  15. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +218 -152
  16. package/dist/types/data-structures/binary-tree/tree-map.d.ts +1281 -5
  17. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1087 -201
  18. package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +858 -65
  19. package/dist/types/data-structures/binary-tree/tree-set.d.ts +1133 -5
  20. package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
  21. package/dist/types/data-structures/graph/directed-graph.d.ts +220 -47
  22. package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
  23. package/dist/types/data-structures/graph/undirected-graph.d.ts +218 -59
  24. package/dist/types/data-structures/hash/hash-map.d.ts +230 -77
  25. package/dist/types/data-structures/heap/heap.d.ts +287 -99
  26. package/dist/types/data-structures/heap/max-heap.d.ts +46 -0
  27. package/dist/types/data-structures/heap/min-heap.d.ts +59 -0
  28. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +286 -44
  29. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +278 -65
  30. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +415 -12
  31. package/dist/types/data-structures/matrix/matrix.d.ts +331 -0
  32. package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +57 -0
  33. package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +60 -0
  34. package/dist/types/data-structures/priority-queue/priority-queue.d.ts +60 -0
  35. package/dist/types/data-structures/queue/deque.d.ts +313 -66
  36. package/dist/types/data-structures/queue/queue.d.ts +211 -42
  37. package/dist/types/data-structures/stack/stack.d.ts +174 -32
  38. package/dist/types/data-structures/trie/trie.d.ts +213 -43
  39. package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
  40. package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
  41. package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
  42. package/dist/umd/data-structure-typed.js +10725 -2221
  43. package/dist/umd/data-structure-typed.min.js +4 -2
  44. package/package.json +5 -4
  45. package/src/common/error.ts +60 -0
  46. package/src/common/index.ts +2 -0
  47. package/src/data-structures/base/iterable-element-base.ts +2 -2
  48. package/src/data-structures/binary-tree/avl-tree.ts +146 -51
  49. package/src/data-structures/binary-tree/binary-indexed-tree.ts +317 -247
  50. package/src/data-structures/binary-tree/binary-tree.ts +567 -121
  51. package/src/data-structures/binary-tree/bst.ts +370 -37
  52. package/src/data-structures/binary-tree/red-black-tree.ts +328 -96
  53. package/src/data-structures/binary-tree/segment-tree.ts +378 -248
  54. package/src/data-structures/binary-tree/tree-map.ts +1411 -13
  55. package/src/data-structures/binary-tree/tree-multi-map.ts +1218 -215
  56. package/src/data-structures/binary-tree/tree-multi-set.ts +959 -69
  57. package/src/data-structures/binary-tree/tree-set.ts +1257 -15
  58. package/src/data-structures/graph/abstract-graph.ts +106 -1
  59. package/src/data-structures/graph/directed-graph.ts +233 -47
  60. package/src/data-structures/graph/map-graph.ts +59 -1
  61. package/src/data-structures/graph/undirected-graph.ts +308 -59
  62. package/src/data-structures/hash/hash-map.ts +254 -79
  63. package/src/data-structures/heap/heap.ts +305 -102
  64. package/src/data-structures/heap/max-heap.ts +48 -3
  65. package/src/data-structures/heap/min-heap.ts +59 -0
  66. package/src/data-structures/linked-list/doubly-linked-list.ts +303 -44
  67. package/src/data-structures/linked-list/singly-linked-list.ts +293 -65
  68. package/src/data-structures/linked-list/skip-linked-list.ts +707 -90
  69. package/src/data-structures/matrix/matrix.ts +433 -22
  70. package/src/data-structures/priority-queue/max-priority-queue.ts +59 -3
  71. package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
  72. package/src/data-structures/priority-queue/priority-queue.ts +60 -0
  73. package/src/data-structures/queue/deque.ts +358 -68
  74. package/src/data-structures/queue/queue.ts +223 -42
  75. package/src/data-structures/stack/stack.ts +184 -32
  76. package/src/data-structures/trie/trie.ts +227 -44
  77. package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
  78. package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
  79. package/src/types/data-structures/queue/deque.ts +7 -0
  80. package/src/utils/utils.ts +4 -2
@@ -15,6 +15,66 @@ import { PriorityQueue } from './priority-queue';
15
15
  * @template E Element type stored in the queue.
16
16
  * @template R Extra record/metadata associated with each element.
17
17
  * @example
18
+ * // Shortest job first scheduling
19
+ * const jobs = new MinPriorityQueue<number>();
20
+ *
21
+ * jobs.add(8); // 8 seconds
22
+ * jobs.add(2); // 2 seconds
23
+ * jobs.add(5); // 5 seconds
24
+ * jobs.add(1); // 1 second
25
+ *
26
+ * // Shortest job first
27
+ * console.log(jobs.poll()); // 1;
28
+ * console.log(jobs.poll()); // 2;
29
+ * console.log(jobs.poll()); // 5;
30
+ * console.log(jobs.poll()); // 8;
31
+ * @example
32
+ * // Event-driven simulation with timestamps
33
+ * interface Event {
34
+ * time: number;
35
+ * action: string;
36
+ * }
37
+ *
38
+ * const timeline = new MinPriorityQueue<Event>([], {
39
+ * comparator: (a, b) => a.time - b.time
40
+ * });
41
+ *
42
+ * timeline.add({ time: 300, action: 'Timeout' });
43
+ * timeline.add({ time: 100, action: 'Request received' });
44
+ * timeline.add({ time: 200, action: 'Processing done' });
45
+ * timeline.add({ time: 150, action: 'Cache hit' });
46
+ *
47
+ * const order = [];
48
+ * while (timeline.size > 0) {
49
+ * order.push(timeline.poll()!.action);
50
+ * }
51
+ * console.log(order); // [
52
+ * // 'Request received',
53
+ * // 'Cache hit',
54
+ * // 'Processing done',
55
+ * // 'Timeout'
56
+ * // ];
57
+ * @example
58
+ * // Huffman coding frequency selection
59
+ * // Character frequencies for Huffman tree building
60
+ * const freq = new MinPriorityQueue<[number, string]>([], {
61
+ * comparator: (a, b) => a[0] - b[0]
62
+ * });
63
+ *
64
+ * freq.add([5, 'a']);
65
+ * freq.add([9, 'b']);
66
+ * freq.add([12, 'c']);
67
+ * freq.add([2, 'd']);
68
+ *
69
+ * // Always pick two lowest frequencies
70
+ * const first = freq.poll()!;
71
+ * const second = freq.poll()!;
72
+ * console.log(first[1]); // 'd'; // freq 2
73
+ * console.log(second[1]); // 'a'; // freq 5
74
+ *
75
+ * // Combined node goes back
76
+ * freq.add([first[0] + second[0], first[1] + second[1]]);
77
+ * console.log(freq.peek()![0]); // 7;
18
78
  */
19
79
  export class MinPriorityQueue<E = any, R = any> extends PriorityQueue<E, R> {
20
80
  /**
@@ -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,32 @@ 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
+
264
+ * @example
265
+ * // Deque peek at both ends
266
+ * const deque = new Deque<number>([10, 20, 30, 40, 50]);
267
+ *
268
+ * // Get first element without removing
269
+ * const first = deque.at(0);
270
+ * console.log(first); // 10;
271
+ *
272
+ * // Get last element without removing
273
+ * const last = deque.at(deque.length - 1);
274
+ * console.log(last); // 50;
275
+ *
276
+ * // Length unchanged
277
+ * console.log(deque.length); // 5;
282
278
  */
283
279
 
284
280
  get first(): E | undefined {
@@ -290,6 +286,23 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
290
286
  * Get the last element without removing it.
291
287
  * @remarks Time O(1), Space O(1)
292
288
  * @returns Last element or undefined.
289
+
290
+
291
+
292
+
293
+
294
+
295
+
296
+
297
+
298
+
299
+
300
+
301
+ * @example
302
+ * // Peek at the back element
303
+ * const dq = new Deque<string>(['a', 'b', 'c']);
304
+ * console.log(dq.last); // 'c';
305
+ * console.log(dq.first); // 'a';
293
306
  */
294
307
 
295
308
  get last(): E | undefined {
@@ -324,6 +337,36 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
324
337
  * @remarks Time O(1) amortized, Space O(1)
325
338
  * @param element - Element to append.
326
339
  * @returns True when appended.
340
+
341
+
342
+
343
+
344
+
345
+
346
+
347
+
348
+
349
+
350
+
351
+
352
+ * @example
353
+ * // basic Deque creation and push/pop operations
354
+ * // Create a simple Deque with initial values
355
+ * const deque = new Deque([1, 2, 3, 4, 5]);
356
+ *
357
+ * // Verify the deque maintains insertion order
358
+ * console.log([...deque]); // [1, 2, 3, 4, 5];
359
+ *
360
+ * // Check length
361
+ * console.log(deque.length); // 5;
362
+ *
363
+ * // Push to the end
364
+ * deque.push(6);
365
+ * console.log(deque.length); // 6;
366
+ *
367
+ * // Pop from the end
368
+ * const last = deque.pop();
369
+ * console.log(last); // 6;
327
370
  */
328
371
 
329
372
  push(element: E): boolean {
@@ -349,6 +392,23 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
349
392
  * Remove and return the last element.
350
393
  * @remarks Time O(1), Space O(1)
351
394
  * @returns Removed element or undefined.
395
+
396
+
397
+
398
+
399
+
400
+
401
+
402
+
403
+
404
+
405
+
406
+
407
+ * @example
408
+ * // Remove from the back
409
+ * const dq = new Deque<number>([1, 2, 3]);
410
+ * console.log(dq.pop()); // 3;
411
+ * console.log(dq.length); // 2;
352
412
  */
353
413
 
354
414
  pop(): E | undefined {
@@ -366,6 +426,7 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
366
426
  }
367
427
  }
368
428
  this._length -= 1;
429
+ this._autoCompact();
369
430
  return element;
370
431
  }
371
432
 
@@ -373,6 +434,23 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
373
434
  * Remove and return the first element.
374
435
  * @remarks Time O(1) amortized, Space O(1)
375
436
  * @returns Removed element or undefined.
437
+
438
+
439
+
440
+
441
+
442
+
443
+
444
+
445
+
446
+
447
+
448
+
449
+ * @example
450
+ * // Remove from the front
451
+ * const dq = new Deque<number>([1, 2, 3]);
452
+ * console.log(dq.shift()); // 1;
453
+ * console.log(dq.length); // 2;
376
454
  */
377
455
 
378
456
  shift(): E | undefined {
@@ -390,6 +468,7 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
390
468
  }
391
469
  }
392
470
  this._length -= 1;
471
+ this._autoCompact();
393
472
  return element;
394
473
  }
395
474
 
@@ -398,6 +477,33 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
398
477
  * @remarks Time O(1) amortized, Space O(1)
399
478
  * @param element - Element to prepend.
400
479
  * @returns True when prepended.
480
+
481
+
482
+
483
+
484
+
485
+
486
+
487
+
488
+
489
+
490
+
491
+
492
+ * @example
493
+ * // Deque shift and unshift operations
494
+ * const deque = new Deque<number>([20, 30, 40]);
495
+ *
496
+ * // Unshift adds to the front
497
+ * deque.unshift(10);
498
+ * console.log([...deque]); // [10, 20, 30, 40];
499
+ *
500
+ * // Shift removes from the front (O(1) complexity!)
501
+ * const first = deque.shift();
502
+ * console.log(first); // 10;
503
+ *
504
+ * // Verify remaining elements
505
+ * console.log([...deque]); // [20, 30, 40];
506
+ * console.log(deque.length); // 3;
401
507
  */
402
508
 
403
509
  unshift(element: E): boolean {
@@ -461,6 +567,20 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
461
567
  * Check whether the deque is empty.
462
568
  * @remarks Time O(1), Space O(1)
463
569
  * @returns True if length is 0.
570
+
571
+
572
+
573
+
574
+
575
+
576
+
577
+
578
+
579
+
580
+ * @example
581
+ * // Check if empty
582
+ * const dq = new Deque();
583
+ * console.log(dq.isEmpty()); // true;
464
584
  */
465
585
 
466
586
  isEmpty(): boolean {
@@ -471,6 +591,21 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
471
591
  * Remove all elements and reset structure.
472
592
  * @remarks Time O(1), Space O(1)
473
593
  * @returns void
594
+
595
+
596
+
597
+
598
+
599
+
600
+
601
+
602
+
603
+
604
+ * @example
605
+ * // Remove all elements
606
+ * const dq = new Deque<number>([1, 2, 3]);
607
+ * dq.clear();
608
+ * console.log(dq.length); // 0;
474
609
  */
475
610
 
476
611
  clear(): void {
@@ -485,6 +620,20 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
485
620
  * @remarks Time O(1), Space O(1)
486
621
  * @param pos - Zero-based position from the front.
487
622
  * @returns Element or undefined.
623
+
624
+
625
+
626
+
627
+
628
+
629
+
630
+
631
+
632
+ * @example
633
+ * // Access by index
634
+ * const dq = new Deque<string>(['a', 'b', 'c']);
635
+ * console.log(dq.at(0)); // 'a';
636
+ * console.log(dq.at(2)); // 'c';
488
637
  */
489
638
 
490
639
  at(pos: number): E | undefined {
@@ -672,6 +821,20 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
672
821
  * @remarks Time O(N), Space O(1)
673
822
  * @param element - Element to remove (using the configured equality).
674
823
  * @returns True if an element was removed.
824
+
825
+
826
+
827
+
828
+
829
+
830
+
831
+
832
+
833
+ * @example
834
+ * // Remove element
835
+ * const dq = new Deque<number>([1, 2, 3]);
836
+ * dq.delete(2);
837
+ * console.log(dq.length); // 2;
675
838
  */
676
839
 
677
840
  delete(element: E): boolean {
@@ -725,6 +888,36 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
725
888
  * Reverse the deque by reversing buckets and pointers.
726
889
  * @remarks Time O(N), Space O(N)
727
890
  * @returns This deque.
891
+
892
+
893
+
894
+
895
+
896
+
897
+
898
+
899
+
900
+
901
+
902
+
903
+ * @example
904
+ * // Deque for...of iteration and reverse
905
+ * const deque = new Deque<string>(['A', 'B', 'C', 'D']);
906
+ *
907
+ * // Iterate forward
908
+ * const forward: string[] = [];
909
+ * for (const item of deque) {
910
+ * forward.push(item);
911
+ * }
912
+ * console.log(forward); // ['A', 'B', 'C', 'D'];
913
+ *
914
+ * // Reverse the deque
915
+ * deque.reverse();
916
+ * const backward: string[] = [];
917
+ * for (const item of deque) {
918
+ * backward.push(item);
919
+ * }
920
+ * console.log(backward); // ['D', 'C', 'B', 'A'];
728
921
  */
729
922
 
730
923
  reverse(): this {
@@ -768,11 +961,60 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
768
961
  * @returns void
769
962
  */
770
963
 
964
+ /**
965
+ * (Protected) Trigger auto-compaction if space utilization drops below threshold.
966
+ * Only checks every `_bucketSize` operations to minimize hot-path overhead.
967
+ * Uses element-based ratio: `elements / (bucketCount * bucketSize)`.
968
+ */
969
+ protected _autoCompact(): void {
970
+ if (this._autoCompactRatio <= 0 || this._bucketCount <= 1) return;
971
+
972
+ this._compactCounter++;
973
+ if (this._compactCounter < this._bucketSize) return;
974
+ this._compactCounter = 0;
975
+
976
+ const utilization = this._length / (this._bucketCount * this._bucketSize);
977
+ if (utilization < this._autoCompactRatio) {
978
+ this.shrinkToFit();
979
+ }
980
+ }
981
+
982
+ /**
983
+ * Compact the deque by removing unused buckets.
984
+ * @remarks Time O(N), Space O(1)
985
+ * @returns True if compaction was performed (bucket count reduced).
986
+ */
987
+ /**
988
+ * Compact the deque by removing unused buckets.
989
+ * @remarks Time O(N), Space O(1)
990
+ * @returns True if compaction was performed (bucket count reduced).
991
+
992
+
993
+
994
+
995
+
996
+
997
+
998
+
999
+
1000
+ * @example
1001
+ * // Reclaim memory
1002
+ * const dq = new Deque<number>([1, 2, 3, 4, 5]);
1003
+ * dq.shift();
1004
+ * dq.shift();
1005
+ * dq.compact();
1006
+ * console.log(dq.length); // 3;
1007
+ */
1008
+ compact(): boolean {
1009
+ const before = this._bucketCount;
1010
+ this.shrinkToFit();
1011
+ return this._bucketCount < before;
1012
+ }
1013
+
771
1014
  shrinkToFit(): void {
772
1015
  if (this._length === 0) return;
773
1016
  const newBuckets = [] as E[][];
774
- if (this._bucketFirst === this._bucketLast) return;
775
- else if (this._bucketFirst < this._bucketLast) {
1017
+ if (this._bucketFirst <= this._bucketLast) {
776
1018
  for (let i = this._bucketFirst; i <= this._bucketLast; ++i) {
777
1019
  newBuckets.push(this._buckets[i]);
778
1020
  }
@@ -787,12 +1029,31 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
787
1029
  this._bucketFirst = 0;
788
1030
  this._bucketLast = newBuckets.length - 1;
789
1031
  this._buckets = newBuckets;
1032
+ this._bucketCount = newBuckets.length;
1033
+ this._compactCounter = 0;
790
1034
  }
791
1035
 
792
1036
  /**
793
1037
  * Deep clone this deque, preserving options.
794
1038
  * @remarks Time O(N), Space O(N)
795
1039
  * @returns A new deque with the same content and options.
1040
+
1041
+
1042
+
1043
+
1044
+
1045
+
1046
+
1047
+
1048
+
1049
+
1050
+ * @example
1051
+ * // Create independent copy
1052
+ * const dq = new Deque<number>([1, 2, 3]);
1053
+ * const copy = dq.clone();
1054
+ * copy.pop();
1055
+ * console.log(dq.length); // 3;
1056
+ * console.log(copy.length); // 2;
796
1057
  */
797
1058
 
798
1059
  clone(): this {
@@ -809,6 +1070,21 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
809
1070
  * @param predicate - Predicate (value, index, deque) → boolean to keep element.
810
1071
  * @param [thisArg] - Value for `this` inside the predicate.
811
1072
  * @returns A new deque with kept elements.
1073
+
1074
+
1075
+
1076
+
1077
+
1078
+
1079
+
1080
+
1081
+
1082
+
1083
+ * @example
1084
+ * // Filter elements
1085
+ * const dq = new Deque<number>([1, 2, 3, 4]);
1086
+ * const result = dq.filter(x => x > 2);
1087
+ * console.log(result.length); // 2;
812
1088
  */
813
1089
 
814
1090
  filter(predicate: ElementCallback<E, R, boolean>, thisArg?: any): this {
@@ -850,6 +1126,20 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
850
1126
  * @param [options] - Options for the output deque (e.g., bucketSize, toElementFn, maxLen).
851
1127
  * @param [thisArg] - Value for `this` inside the callback.
852
1128
  * @returns A new Deque with mapped elements.
1129
+
1130
+
1131
+
1132
+
1133
+
1134
+
1135
+
1136
+
1137
+
1138
+ * @example
1139
+ * // Transform elements
1140
+ * const dq = new Deque<number>([1, 2, 3]);
1141
+ * const result = dq.map(x => x * 10);
1142
+ * console.log(result.toArray()); // [10, 20, 30];
853
1143
  */
854
1144
 
855
1145
  map<EM, RM>(