data-structure-typed 2.5.3 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/.github/workflows/ci.yml +7 -2
  2. package/.github/workflows/release-package.yml +9 -2
  3. package/.husky/pre-commit +3 -0
  4. package/CHANGELOG.md +1 -1
  5. package/MIGRATION.md +48 -0
  6. package/README.md +20 -2
  7. package/README_CN.md +20 -2
  8. package/SPECIFICATION.md +24 -0
  9. package/SPECIFICATION.zh-CN.md +24 -0
  10. package/dist/cjs/binary-tree.cjs +1897 -19
  11. package/dist/cjs/graph.cjs +174 -0
  12. package/dist/cjs/hash.cjs +33 -0
  13. package/dist/cjs/heap.cjs +71 -0
  14. package/dist/cjs/index.cjs +2383 -3
  15. package/dist/cjs/linked-list.cjs +224 -2
  16. package/dist/cjs/matrix.cjs +24 -0
  17. package/dist/cjs/priority-queue.cjs +71 -0
  18. package/dist/cjs/queue.cjs +221 -1
  19. package/dist/cjs/stack.cjs +59 -0
  20. package/dist/cjs/trie.cjs +62 -0
  21. package/dist/cjs-legacy/binary-tree.cjs +1897 -19
  22. package/dist/cjs-legacy/graph.cjs +174 -0
  23. package/dist/cjs-legacy/hash.cjs +33 -0
  24. package/dist/cjs-legacy/heap.cjs +71 -0
  25. package/dist/cjs-legacy/index.cjs +2383 -3
  26. package/dist/cjs-legacy/linked-list.cjs +224 -2
  27. package/dist/cjs-legacy/matrix.cjs +24 -0
  28. package/dist/cjs-legacy/priority-queue.cjs +71 -0
  29. package/dist/cjs-legacy/queue.cjs +221 -1
  30. package/dist/cjs-legacy/stack.cjs +59 -0
  31. package/dist/cjs-legacy/trie.cjs +62 -0
  32. package/dist/esm/binary-tree.mjs +1897 -19
  33. package/dist/esm/graph.mjs +174 -0
  34. package/dist/esm/hash.mjs +33 -0
  35. package/dist/esm/heap.mjs +71 -0
  36. package/dist/esm/index.mjs +2383 -3
  37. package/dist/esm/linked-list.mjs +224 -2
  38. package/dist/esm/matrix.mjs +24 -0
  39. package/dist/esm/priority-queue.mjs +71 -0
  40. package/dist/esm/queue.mjs +221 -1
  41. package/dist/esm/stack.mjs +59 -0
  42. package/dist/esm/trie.mjs +62 -0
  43. package/dist/esm-legacy/binary-tree.mjs +1897 -19
  44. package/dist/esm-legacy/graph.mjs +174 -0
  45. package/dist/esm-legacy/hash.mjs +33 -0
  46. package/dist/esm-legacy/heap.mjs +71 -0
  47. package/dist/esm-legacy/index.mjs +2383 -3
  48. package/dist/esm-legacy/linked-list.mjs +224 -2
  49. package/dist/esm-legacy/matrix.mjs +24 -0
  50. package/dist/esm-legacy/priority-queue.mjs +71 -0
  51. package/dist/esm-legacy/queue.mjs +221 -1
  52. package/dist/esm-legacy/stack.mjs +59 -0
  53. package/dist/esm-legacy/trie.mjs +62 -0
  54. package/dist/types/data-structures/base/iterable-element-base.d.ts +17 -0
  55. package/dist/types/data-structures/base/linear-base.d.ts +6 -0
  56. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +36 -0
  57. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +42 -0
  58. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +75 -0
  59. package/dist/types/data-structures/binary-tree/bst.d.ts +72 -0
  60. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +57 -0
  61. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +18 -0
  62. package/dist/types/data-structures/binary-tree/tree-map.d.ts +375 -0
  63. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +389 -0
  64. package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +330 -0
  65. package/dist/types/data-structures/binary-tree/tree-set.d.ts +438 -0
  66. package/dist/types/data-structures/graph/directed-graph.d.ts +30 -0
  67. package/dist/types/data-structures/graph/undirected-graph.d.ts +27 -0
  68. package/dist/types/data-structures/hash/hash-map.d.ts +33 -0
  69. package/dist/types/data-structures/heap/heap.d.ts +42 -0
  70. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +75 -2
  71. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +45 -0
  72. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +54 -0
  73. package/dist/types/data-structures/matrix/matrix.d.ts +24 -0
  74. package/dist/types/data-structures/queue/deque.d.ts +90 -1
  75. package/dist/types/data-structures/queue/queue.d.ts +36 -0
  76. package/dist/types/data-structures/stack/stack.d.ts +30 -0
  77. package/dist/types/data-structures/trie/trie.d.ts +36 -0
  78. package/dist/umd/data-structure-typed.js +2383 -3
  79. package/dist/umd/data-structure-typed.min.js +3 -3
  80. package/docs-site-docusaurus/docs/api/classes/AVLTree.md +108 -108
  81. package/docs-site-docusaurus/docs/api/classes/BST.md +101 -101
  82. package/docs-site-docusaurus/docs/api/classes/BinaryIndexedTree.md +13 -13
  83. package/docs-site-docusaurus/docs/api/classes/BinaryTree.md +66 -66
  84. package/docs-site-docusaurus/docs/api/classes/Deque.md +235 -51
  85. package/docs-site-docusaurus/docs/api/classes/DirectedGraph.md +21 -21
  86. package/docs-site-docusaurus/docs/api/classes/DoublyLinkedList.md +231 -67
  87. package/docs-site-docusaurus/docs/api/classes/FibonacciHeap.md +9 -9
  88. package/docs-site-docusaurus/docs/api/classes/FibonacciHeapNode.md +1 -1
  89. package/docs-site-docusaurus/docs/api/classes/HashMap.md +14 -14
  90. package/docs-site-docusaurus/docs/api/classes/Heap.md +117 -34
  91. package/docs-site-docusaurus/docs/api/classes/IterableElementBase.md +83 -13
  92. package/docs-site-docusaurus/docs/api/classes/LinearBase.md +124 -20
  93. package/docs-site-docusaurus/docs/api/classes/LinearLinkedBase.md +140 -32
  94. package/docs-site-docusaurus/docs/api/classes/LinkedHashMap.md +30 -26
  95. package/docs-site-docusaurus/docs/api/classes/LinkedListQueue.md +159 -51
  96. package/docs-site-docusaurus/docs/api/classes/MapGraph.md +20 -20
  97. package/docs-site-docusaurus/docs/api/classes/Matrix.md +23 -23
  98. package/docs-site-docusaurus/docs/api/classes/MaxHeap.md +117 -34
  99. package/docs-site-docusaurus/docs/api/classes/MaxPriorityQueue.md +117 -34
  100. package/docs-site-docusaurus/docs/api/classes/MinHeap.md +117 -34
  101. package/docs-site-docusaurus/docs/api/classes/MinPriorityQueue.md +117 -34
  102. package/docs-site-docusaurus/docs/api/classes/PriorityQueue.md +117 -34
  103. package/docs-site-docusaurus/docs/api/classes/Queue.md +142 -34
  104. package/docs-site-docusaurus/docs/api/classes/RedBlackTree.md +117 -117
  105. package/docs-site-docusaurus/docs/api/classes/SegmentTree.md +8 -8
  106. package/docs-site-docusaurus/docs/api/classes/SinglyLinkedList.md +158 -50
  107. package/docs-site-docusaurus/docs/api/classes/SkipList.md +21 -21
  108. package/docs-site-docusaurus/docs/api/classes/Stack.md +108 -26
  109. package/docs-site-docusaurus/docs/api/classes/TreeMap.md +33 -33
  110. package/docs-site-docusaurus/docs/api/classes/TreeMultiMap.md +75 -39
  111. package/docs-site-docusaurus/docs/api/classes/TreeSet.md +301 -39
  112. package/docs-site-docusaurus/docs/api/classes/Trie.md +110 -28
  113. package/docs-site-docusaurus/docs/api/classes/UndirectedGraph.md +20 -20
  114. package/jest.integration.config.js +1 -2
  115. package/package.json +51 -50
  116. package/src/common/error.ts +15 -32
  117. package/src/common/index.ts +0 -3
  118. package/src/data-structures/base/iterable-element-base.ts +32 -3
  119. package/src/data-structures/base/linear-base.ts +13 -36
  120. package/src/data-structures/binary-tree/avl-tree.ts +31 -493
  121. package/src/data-structures/binary-tree/binary-indexed-tree.ts +47 -530
  122. package/src/data-structures/binary-tree/binary-tree.ts +326 -1236
  123. package/src/data-structures/binary-tree/bst.ts +158 -1010
  124. package/src/data-structures/binary-tree/red-black-tree.ts +451 -1233
  125. package/src/data-structures/binary-tree/segment-tree.ts +73 -333
  126. package/src/data-structures/binary-tree/tree-map.ts +462 -4749
  127. package/src/data-structures/binary-tree/tree-multi-map.ts +310 -4530
  128. package/src/data-structures/binary-tree/tree-multi-set.ts +300 -3652
  129. package/src/data-structures/binary-tree/tree-set.ts +437 -4443
  130. package/src/data-structures/graph/abstract-graph.ts +98 -167
  131. package/src/data-structures/graph/directed-graph.ts +137 -532
  132. package/src/data-structures/graph/map-graph.ts +0 -3
  133. package/src/data-structures/graph/undirected-graph.ts +132 -484
  134. package/src/data-structures/hash/hash-map.ts +154 -549
  135. package/src/data-structures/heap/heap.ts +200 -753
  136. package/src/data-structures/linked-list/doubly-linked-list.ts +153 -809
  137. package/src/data-structures/linked-list/singly-linked-list.ts +122 -749
  138. package/src/data-structures/linked-list/skip-linked-list.ts +211 -864
  139. package/src/data-structures/matrix/matrix.ts +179 -494
  140. package/src/data-structures/matrix/navigator.ts +0 -1
  141. package/src/data-structures/priority-queue/max-priority-queue.ts +1 -6
  142. package/src/data-structures/priority-queue/min-priority-queue.ts +6 -11
  143. package/src/data-structures/priority-queue/priority-queue.ts +1 -2
  144. package/src/data-structures/queue/deque.ts +241 -807
  145. package/src/data-structures/queue/queue.ts +102 -589
  146. package/src/data-structures/stack/stack.ts +76 -475
  147. package/src/data-structures/trie/trie.ts +98 -592
  148. package/src/types/common.ts +0 -10
  149. package/src/types/data-structures/binary-tree/bst.ts +0 -7
  150. package/src/types/data-structures/binary-tree/red-black-tree.ts +0 -1
  151. package/src/types/data-structures/graph/abstract-graph.ts +0 -2
  152. package/src/types/data-structures/hash/hash-map.ts +0 -3
  153. package/src/types/data-structures/hash/index.ts +0 -1
  154. package/src/types/data-structures/matrix/navigator.ts +0 -2
  155. package/src/types/utils/utils.ts +0 -7
  156. package/src/types/utils/validate-type.ts +0 -7
  157. package/src/utils/number.ts +0 -2
  158. package/src/utils/utils.ts +0 -5
@@ -5,7 +5,6 @@
5
5
  * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
6
6
  * @license MIT License
7
7
  */
8
-
9
8
  import type {
10
9
  DequeOptions,
11
10
  ElementCallback,
@@ -83,7 +82,11 @@ import { LinearBase } from '../base/linear-base';
83
82
  * console.log(dq.toArray()); // [10, 20, 30];
84
83
  */
85
84
  export class Deque<E = any, R = any> extends LinearBase<E, R> {
86
- protected _equals: (a: E, b: E) => boolean = (a, b) => Object.is(a, b);
85
+ /**
86
+ * Counter for shift/pop operations since last compaction check.
87
+ * Only checks ratio every `_bucketSize` operations to minimize overhead.
88
+ */
89
+ protected _compactCounter = 0;
87
90
 
88
91
  /**
89
92
  * Create a Deque and optionally bulk-insert elements.
@@ -92,25 +95,26 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
92
95
  * @param [options] - Options such as bucketSize, toElementFn, and maxLen.
93
96
  * @returns New Deque instance.
94
97
  */
95
-
96
98
  constructor(elements?: IterableWithSizeOrLength<E>, options?: DequeOptions<E, R>);
97
- constructor(elements: IterableWithSizeOrLength<R>, options: DequeOptions<E, R> & { toElementFn: (rawElement: R) => E });
99
+ constructor(
100
+ elements: IterableWithSizeOrLength<R>,
101
+ options: DequeOptions<E, R> & {
102
+ toElementFn: (rawElement: R) => E;
103
+ }
104
+ );
98
105
  constructor(elements: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R> = [], options?: DequeOptions<E, R>) {
99
106
  super(options);
100
-
101
107
  if (options) {
102
108
  const { bucketSize, autoCompactRatio } = options;
103
109
  if (typeof bucketSize === 'number') this._bucketSize = bucketSize;
104
110
  if (typeof autoCompactRatio === 'number') this._autoCompactRatio = autoCompactRatio;
105
111
  }
106
-
107
112
  let _size: number;
108
113
  if ('length' in elements) {
109
114
  _size = typeof elements.length === 'function' ? elements.length() : elements.length;
110
115
  } else {
111
116
  _size = typeof elements.size === 'function' ? elements.size() : elements.size;
112
117
  }
113
-
114
118
  this._bucketCount = calcMinUnitsRequired(_size, this._bucketSize) || 1;
115
119
  for (let i = 0; i < this._bucketCount; ++i) {
116
120
  this._buckets.push(new Array(this._bucketSize));
@@ -128,7 +132,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
128
132
  * @remarks Time O(1), Space O(1)
129
133
  * @returns Bucket capacity per bucket.
130
134
  */
131
-
132
135
  get bucketSize() {
133
136
  return this._bucketSize;
134
137
  }
@@ -155,12 +158,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
155
158
  this._autoCompactRatio = value;
156
159
  }
157
160
 
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
-
164
161
  protected _bucketFirst = 0;
165
162
 
166
163
  /**
@@ -168,7 +165,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
168
165
  * @remarks Time O(1), Space O(1)
169
166
  * @returns Zero-based bucket index.
170
167
  */
171
-
172
168
  get bucketFirst(): number {
173
169
  return this._bucketFirst;
174
170
  }
@@ -180,7 +176,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
180
176
  * @remarks Time O(1), Space O(1)
181
177
  * @returns Zero-based index within the first bucket.
182
178
  */
183
-
184
179
  get firstInBucket(): number {
185
180
  return this._firstInBucket;
186
181
  }
@@ -192,7 +187,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
192
187
  * @remarks Time O(1), Space O(1)
193
188
  * @returns Zero-based bucket index.
194
189
  */
195
-
196
190
  get bucketLast(): number {
197
191
  return this._bucketLast;
198
192
  }
@@ -204,7 +198,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
204
198
  * @remarks Time O(1), Space O(1)
205
199
  * @returns Zero-based index within the last bucket.
206
200
  */
207
-
208
201
  get lastInBucket(): number {
209
202
  return this._lastInBucket;
210
203
  }
@@ -216,7 +209,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
216
209
  * @remarks Time O(1), Space O(1)
217
210
  * @returns Bucket count.
218
211
  */
219
-
220
212
  get bucketCount(): number {
221
213
  return this._bucketCount;
222
214
  }
@@ -228,7 +220,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
228
220
  * @remarks Time O(1), Space O(1)
229
221
  * @returns Array of buckets storing values.
230
222
  */
231
-
232
223
  get buckets() {
233
224
  return this._buckets;
234
225
  }
@@ -240,94 +231,26 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
240
231
  * @remarks Time O(1), Space O(1)
241
232
  * @returns Current length.
242
233
  */
243
-
244
234
  get length() {
245
235
  return this._length;
246
236
  }
247
237
 
248
238
  /**
249
- * Get the first element without removing it.
250
- * @remarks Time O(1), Space O(1)
251
- * @returns First element or undefined.
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
-
283
-
284
-
285
-
286
-
287
-
288
-
289
-
290
- * @example
291
- * // Deque peek at both ends
292
- * const deque = new Deque<number>([10, 20, 30, 40, 50]);
293
- *
294
- * // Get first element without removing
295
- * const first = deque.at(0);
296
- * console.log(first); // 10;
297
- *
298
- * // Get last element without removing
299
- * const last = deque.at(deque.length - 1);
300
- * console.log(last); // 50;
301
- *
302
- * // Length unchanged
303
- * console.log(deque.length); // 5;
304
- */
305
-
306
- /**
307
- * Peek at the front element without removing it (alias for `first`).
308
- * @remarks Time O(1), Space O(1)
309
- * @returns Front element or undefined.
310
- */
311
- peek(): E | undefined {
312
- return this.first;
313
- }
314
-
315
- /**
316
239
  * Deque peek at both ends
317
240
  * @example
318
- * // Deque peek at both ends
319
- * const deque = new Deque<number>([10, 20, 30, 40, 50]);
320
- *
321
- * // Get first element without removing
322
- * const first = deque.at(0);
323
- * console.log(first); // 10;
324
- *
325
- * // Get last element without removing
326
- * const last = deque.at(deque.length - 1);
327
- * console.log(last); // 50;
328
- *
329
- * // Length unchanged
330
- * console.log(deque.length); // 5;
241
+ * // Deque peek at both ends
242
+ * const deque = new Deque<number>([10, 20, 30, 40, 50]);
243
+ *
244
+ * // Get first element without removing
245
+ * const first = deque.at(0);
246
+ * console.log(first); // 10;
247
+ *
248
+ * // Get last element without removing
249
+ * const last = deque.at(deque.length - 1);
250
+ * console.log(last); // 50;
251
+ *
252
+ * // Length unchanged
253
+ * console.log(deque.length); // 5;
331
254
  */
332
255
  get first(): E | undefined {
333
256
  if (this._length === 0) return;
@@ -338,52 +261,12 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
338
261
  * Get the last element without removing it.
339
262
  * @remarks Time O(1), Space O(1)
340
263
  * @returns Last element or undefined.
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
-
367
-
368
-
369
-
370
-
371
-
372
-
373
-
374
-
375
-
376
-
377
-
378
-
379
-
380
- * @example
381
- * // Peek at the back element
382
- * const dq = new Deque<string>(['a', 'b', 'c']);
383
- * console.log(dq.last); // 'c';
384
- * console.log(dq.first); // 'a';
264
+ * @example
265
+ * // Peek at the back element
266
+ * const dq = new Deque<string>(['a', 'b', 'c']);
267
+ * console.log(dq.last); // 'c';
268
+ * console.log(dq.first); // 'a';
385
269
  */
386
-
387
270
  get last(): E | undefined {
388
271
  if (this._length === 0) return;
389
272
  return this._buckets[this._bucketLast][this._lastInBucket];
@@ -399,7 +282,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
399
282
  * @param [options] - Options forwarded to the constructor.
400
283
  * @returns A new Deque populated from the array.
401
284
  */
402
-
403
285
  static fromArray<E, R = any>(
404
286
  this: new (
405
287
  elements?: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R>,
@@ -411,70 +293,58 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
411
293
  return new this(data, options);
412
294
  }
413
295
 
296
+ /**
297
+ * Get the first element without removing it.
298
+ * @remarks Time O(1), Space O(1)
299
+ * @returns First element or undefined.
300
+ * @example
301
+ * // Deque peek at both ends
302
+ * const deque = new Deque<number>([10, 20, 30, 40, 50]);
303
+ *
304
+ * // Get first element without removing
305
+ * const first = deque.at(0);
306
+ * console.log(first); // 10;
307
+ *
308
+ * // Get last element without removing
309
+ * const last = deque.at(deque.length - 1);
310
+ * console.log(last); // 50;
311
+ *
312
+ * // Length unchanged
313
+ * console.log(deque.length); // 5;
314
+ */
315
+ /**
316
+ * Peek at the front element without removing it (alias for `first`).
317
+ * @remarks Time O(1), Space O(1)
318
+ * @returns Front element or undefined.
319
+ */
320
+ peek(): E | undefined {
321
+ return this.first;
322
+ }
323
+
414
324
  /**
415
325
  * Append one element at the back.
416
326
  * @remarks Time O(1) amortized, Space O(1)
417
327
  * @param element - Element to append.
418
328
  * @returns True when appended.
419
-
420
-
421
-
422
-
423
-
424
-
425
-
426
-
427
-
428
-
429
-
430
-
431
-
432
-
433
-
434
-
435
-
436
-
437
-
438
-
439
-
440
-
441
-
442
-
443
-
444
-
445
-
446
-
447
-
448
-
449
-
450
-
451
-
452
-
453
-
454
-
455
-
456
-
457
-
458
- * @example
459
- * // basic Deque creation and push/pop operations
460
- * // Create a simple Deque with initial values
461
- * const deque = new Deque([1, 2, 3, 4, 5]);
462
- *
463
- * // Verify the deque maintains insertion order
464
- * console.log([...deque]); // [1, 2, 3, 4, 5];
465
- *
466
- * // Check length
467
- * console.log(deque.length); // 5;
468
- *
469
- * // Push to the end
470
- * deque.push(6);
471
- * console.log(deque.length); // 6;
472
- *
473
- * // Pop from the end
474
- * const last = deque.pop();
475
- * console.log(last); // 6;
329
+ * @example
330
+ * // basic Deque creation and push/pop operations
331
+ * // Create a simple Deque with initial values
332
+ * const deque = new Deque([1, 2, 3, 4, 5]);
333
+ *
334
+ * // Verify the deque maintains insertion order
335
+ * console.log([...deque]); // [1, 2, 3, 4, 5];
336
+ *
337
+ * // Check length
338
+ * console.log(deque.length); // 5;
339
+ *
340
+ * // Push to the end
341
+ * deque.push(6);
342
+ * console.log(deque.length); // 6;
343
+ *
344
+ * // Pop from the end
345
+ * const last = deque.pop();
346
+ * console.log(last); // 6;
476
347
  */
477
-
478
348
  push(element: E): boolean {
479
349
  if (this._length) {
480
350
  if (this._lastInBucket < this._bucketSize - 1) {
@@ -498,52 +368,12 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
498
368
  * Remove and return the last element.
499
369
  * @remarks Time O(1), Space O(1)
500
370
  * @returns Removed element or undefined.
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
-
526
-
527
-
528
-
529
-
530
-
531
-
532
-
533
-
534
-
535
-
536
-
537
-
538
-
539
-
540
- * @example
541
- * // Remove from the back
542
- * const dq = new Deque<number>([1, 2, 3]);
543
- * console.log(dq.pop()); // 3;
544
- * console.log(dq.length); // 2;
371
+ * @example
372
+ * // Remove from the back
373
+ * const dq = new Deque<number>([1, 2, 3]);
374
+ * console.log(dq.pop()); // 3;
375
+ * console.log(dq.length); // 2;
545
376
  */
546
-
547
377
  pop(): E | undefined {
548
378
  if (this._length === 0) return;
549
379
  const element = this._buckets[this._bucketLast][this._lastInBucket];
@@ -567,52 +397,12 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
567
397
  * Remove and return the first element.
568
398
  * @remarks Time O(1) amortized, Space O(1)
569
399
  * @returns Removed element or undefined.
570
-
571
-
572
-
573
-
574
-
575
-
576
-
577
-
578
-
579
-
580
-
581
-
582
-
583
-
584
-
585
-
586
-
587
-
588
-
589
-
590
-
591
-
592
-
593
-
594
-
595
-
596
-
597
-
598
-
599
-
600
-
601
-
602
-
603
-
604
-
605
-
606
-
607
-
608
-
609
- * @example
610
- * // Remove from the front
611
- * const dq = new Deque<number>([1, 2, 3]);
612
- * console.log(dq.shift()); // 1;
613
- * console.log(dq.length); // 2;
400
+ * @example
401
+ * // Remove from the front
402
+ * const dq = new Deque<number>([1, 2, 3]);
403
+ * console.log(dq.shift()); // 1;
404
+ * console.log(dq.length); // 2;
614
405
  */
615
-
616
406
  shift(): E | undefined {
617
407
  if (this._length === 0) return;
618
408
  const element = this._buckets[this._bucketFirst][this._firstInBucket];
@@ -637,62 +427,22 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
637
427
  * @remarks Time O(1) amortized, Space O(1)
638
428
  * @param element - Element to prepend.
639
429
  * @returns True when prepended.
640
-
641
-
642
-
643
-
644
-
645
-
646
-
647
-
648
-
649
-
650
-
651
-
652
-
653
-
654
-
655
-
656
-
657
-
658
-
659
-
660
-
661
-
662
-
663
-
664
-
665
-
666
-
667
-
668
-
669
-
670
-
671
-
672
-
673
-
674
-
675
-
676
-
677
-
678
-
679
- * @example
680
- * // Deque shift and unshift operations
681
- * const deque = new Deque<number>([20, 30, 40]);
682
- *
683
- * // Unshift adds to the front
684
- * deque.unshift(10);
685
- * console.log([...deque]); // [10, 20, 30, 40];
686
- *
687
- * // Shift removes from the front (O(1) complexity!)
688
- * const first = deque.shift();
689
- * console.log(first); // 10;
690
- *
691
- * // Verify remaining elements
692
- * console.log([...deque]); // [20, 30, 40];
693
- * console.log(deque.length); // 3;
430
+ * @example
431
+ * // Deque shift and unshift operations
432
+ * const deque = new Deque<number>([20, 30, 40]);
433
+ *
434
+ * // Unshift adds to the front
435
+ * deque.unshift(10);
436
+ * console.log([...deque]); // [10, 20, 30, 40];
437
+ *
438
+ * // Shift removes from the front (O(1) complexity!)
439
+ * const first = deque.shift();
440
+ * console.log(first); // 10;
441
+ *
442
+ * // Verify remaining elements
443
+ * console.log([...deque]); // [20, 30, 40];
444
+ * console.log(deque.length); // 3;
694
445
  */
695
-
696
446
  unshift(element: E): boolean {
697
447
  if (this._length) {
698
448
  if (this._firstInBucket > 0) {
@@ -718,7 +468,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
718
468
  * @param elements - Iterable (or iterable-like) of elements/records.
719
469
  * @returns Array of per-element success flags.
720
470
  */
721
-
722
471
  pushMany(elements: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R>) {
723
472
  const ans: boolean[] = [];
724
473
  for (const el of elements) {
@@ -737,7 +486,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
737
486
  * @param [elements] - Iterable (or iterable-like) of elements/records.
738
487
  * @returns Array of per-element success flags.
739
488
  */
740
-
741
489
  unshiftMany(elements: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R> = []) {
742
490
  const ans: boolean[] = [];
743
491
  for (const el of elements) {
@@ -754,49 +502,11 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
754
502
  * Check whether the deque is empty.
755
503
  * @remarks Time O(1), Space O(1)
756
504
  * @returns True if length is 0.
757
-
758
-
759
-
760
-
761
-
762
-
763
-
764
-
765
-
766
-
767
-
768
-
769
-
770
-
771
-
772
-
773
-
774
-
775
-
776
-
777
-
778
-
779
-
780
-
781
-
782
-
783
-
784
-
785
-
786
-
787
-
788
-
789
-
790
-
791
-
792
-
793
-
794
- * @example
795
- * // Check if empty
796
- * const dq = new Deque();
797
- * console.log(dq.isEmpty()); // true;
505
+ * @example
506
+ * // Check if empty
507
+ * const dq = new Deque();
508
+ * console.log(dq.isEmpty()); // true;
798
509
  */
799
-
800
510
  isEmpty(): boolean {
801
511
  return this._length === 0;
802
512
  }
@@ -805,50 +515,12 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
805
515
  * Remove all elements and reset structure.
806
516
  * @remarks Time O(1), Space O(1)
807
517
  * @returns void
808
-
809
-
810
-
811
-
812
-
813
-
814
-
815
-
816
-
817
-
818
-
819
-
820
-
821
-
822
-
823
-
824
-
825
-
826
-
827
-
828
-
829
-
830
-
831
-
832
-
833
-
834
-
835
-
836
-
837
-
838
-
839
-
840
-
841
-
842
-
843
-
844
-
845
- * @example
846
- * // Remove all elements
847
- * const dq = new Deque<number>([1, 2, 3]);
848
- * dq.clear();
849
- * console.log(dq.length); // 0;
518
+ * @example
519
+ * // Remove all elements
520
+ * const dq = new Deque<number>([1, 2, 3]);
521
+ * dq.clear();
522
+ * console.log(dq.length); // 0;
850
523
  */
851
-
852
524
  clear(): void {
853
525
  this._buckets = [new Array(this._bucketSize)];
854
526
  this._bucketCount = 1;
@@ -861,49 +533,12 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
861
533
  * @remarks Time O(1), Space O(1)
862
534
  * @param pos - Zero-based position from the front.
863
535
  * @returns Element or undefined.
864
-
865
-
866
-
867
-
868
-
869
-
870
-
871
-
872
-
873
-
874
-
875
-
876
-
877
-
878
-
879
-
880
-
881
-
882
-
883
-
884
-
885
-
886
-
887
-
888
-
889
-
890
-
891
-
892
-
893
-
894
-
895
-
896
-
897
-
898
-
899
-
900
- * @example
901
- * // Access by index
902
- * const dq = new Deque<string>(['a', 'b', 'c']);
903
- * console.log(dq.at(0)); // 'a';
904
- * console.log(dq.at(2)); // 'c';
536
+ * @example
537
+ * // Access by index
538
+ * const dq = new Deque<string>(['a', 'b', 'c']);
539
+ * console.log(dq.at(0)); // 'a';
540
+ * console.log(dq.at(2)); // 'c';
905
541
  */
906
-
907
542
  at(pos: number): E | undefined {
908
543
  if (pos < 0 || pos >= this._length) return undefined;
909
544
  const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);
@@ -917,7 +552,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
917
552
  * @param element - New element value.
918
553
  * @returns True if updated.
919
554
  */
920
-
921
555
  setAt(pos: number, element: E): boolean {
922
556
  rangeCheck(pos, 0, this._length - 1);
923
557
  const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);
@@ -933,7 +567,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
933
567
  * @param [num] - Number of times to insert (default 1).
934
568
  * @returns True if inserted.
935
569
  */
936
-
937
570
  addAt(pos: number, element: E, num = 1): boolean {
938
571
  const length = this._length;
939
572
  rangeCheck(pos, 0, length);
@@ -961,7 +594,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
961
594
  * @param [isCutSelf] - When true, mutate this deque; otherwise return a new deque.
962
595
  * @returns This deque if in-place; otherwise a new deque of the prefix.
963
596
  */
964
-
965
597
  cut(pos: number, isCutSelf = false): Deque<E> {
966
598
  if (isCutSelf) {
967
599
  if (pos < 0) {
@@ -980,7 +612,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
980
612
  const v = this.at(i);
981
613
  if (v !== undefined) newDeque.push(v);
982
614
  }
983
-
984
615
  return newDeque;
985
616
  }
986
617
  }
@@ -993,31 +624,24 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
993
624
  * @param [items] - Elements to insert after `start`.
994
625
  * @returns A new deque containing the removed elements (typed as `this`).
995
626
  */
996
-
997
627
  override splice(start: number, deleteCount: number = this._length - start, ...items: E[]): this {
998
628
  rangeCheck(start, 0, this._length);
999
629
  if (deleteCount < 0) deleteCount = 0;
1000
630
  if (start + deleteCount > this._length) deleteCount = this._length - start;
1001
-
1002
631
  const removed = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
1003
632
  removed._setBucketSize(this._bucketSize);
1004
633
  for (let i = 0; i < deleteCount; i++) {
1005
634
  const v = this.at(start + i);
1006
635
  if (v !== undefined) removed.push(v);
1007
636
  }
1008
-
1009
637
  const tail: E[] = [];
1010
638
  for (let i = start + deleteCount; i < this._length; i++) {
1011
639
  const v = this.at(i);
1012
640
  if (v !== undefined) tail.push(v);
1013
641
  }
1014
-
1015
642
  this.cut(start - 1, true);
1016
-
1017
643
  for (const it of items) this.push(it);
1018
-
1019
644
  for (const v of tail) this.push(v);
1020
-
1021
645
  return removed as unknown as this;
1022
646
  }
1023
647
 
@@ -1028,7 +652,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1028
652
  * @param [isCutSelf] - When true, mutate this deque; otherwise return a new deque.
1029
653
  * @returns This deque if in-place; otherwise a new deque of the suffix.
1030
654
  */
1031
-
1032
655
  cutRest(pos: number, isCutSelf = false): Deque<E> {
1033
656
  if (isCutSelf) {
1034
657
  if (pos < 0) {
@@ -1057,10 +680,8 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1057
680
  * @param pos - Zero-based position from the front.
1058
681
  * @returns Removed element or undefined.
1059
682
  */
1060
-
1061
683
  deleteAt(pos: number): E | undefined {
1062
684
  rangeCheck(pos, 0, this._length - 1);
1063
-
1064
685
  let deleted: E | undefined;
1065
686
  if (pos === 0) {
1066
687
  return this.shift();
@@ -1072,13 +693,11 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1072
693
  const length = this._length - 1;
1073
694
  const { bucketIndex: targetBucket, indexInBucket: targetPointer } = this._getBucketAndPosition(pos);
1074
695
  deleted = this._buckets[targetBucket][targetPointer];
1075
-
1076
696
  for (let i = pos; i < length; i++) {
1077
697
  const { bucketIndex: curBucket, indexInBucket: curPointer } = this._getBucketAndPosition(i);
1078
698
  const { bucketIndex: nextBucket, indexInBucket: nextPointer } = this._getBucketAndPosition(i + 1);
1079
699
  this._buckets[curBucket][curPointer] = this._buckets[nextBucket][nextPointer];
1080
700
  }
1081
-
1082
701
  this.pop();
1083
702
  return deleted;
1084
703
  }
@@ -1089,49 +708,12 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1089
708
  * @remarks Time O(N), Space O(1)
1090
709
  * @param element - Element to remove (using the configured equality).
1091
710
  * @returns True if an element was removed.
1092
-
1093
-
1094
-
1095
-
1096
-
1097
-
1098
-
1099
-
1100
-
1101
-
1102
-
1103
-
1104
-
1105
-
1106
-
1107
-
1108
-
1109
-
1110
-
1111
-
1112
-
1113
-
1114
-
1115
-
1116
-
1117
-
1118
-
1119
-
1120
-
1121
-
1122
-
1123
-
1124
-
1125
-
1126
-
1127
-
1128
- * @example
1129
- * // Remove element
1130
- * const dq = new Deque<number>([1, 2, 3]);
1131
- * dq.delete(2);
1132
- * console.log(dq.length); // 2;
711
+ * @example
712
+ * // Remove element
713
+ * const dq = new Deque<number>([1, 2, 3]);
714
+ * dq.delete(2);
715
+ * console.log(dq.length); // 2;
1133
716
  */
1134
-
1135
717
  delete(element: E): boolean {
1136
718
  const size = this._length;
1137
719
  if (size === 0) return false;
@@ -1155,7 +737,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1155
737
  * @param predicate - Function (value, index, deque) → boolean.
1156
738
  * @returns True if a match was removed.
1157
739
  */
1158
-
1159
740
  deleteWhere(predicate: (value: E, index: number, deque: this) => boolean): boolean {
1160
741
  for (let i = 0; i < this._length; i++) {
1161
742
  const v = this.at(i);
@@ -1173,7 +754,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1173
754
  * @param equals - Equality predicate (a, b) → boolean.
1174
755
  * @returns This deque.
1175
756
  */
1176
-
1177
757
  setEquality(equals: (a: E, b: E) => boolean): this {
1178
758
  this._equals = equals;
1179
759
  return this;
@@ -1183,65 +763,83 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1183
763
  * Reverse the deque by reversing buckets and pointers.
1184
764
  * @remarks Time O(N), Space O(N)
1185
765
  * @returns This deque.
1186
-
1187
-
1188
-
1189
-
1190
-
1191
-
1192
-
1193
-
1194
-
1195
-
1196
-
1197
-
1198
-
1199
-
1200
-
1201
-
1202
-
1203
-
1204
-
1205
-
1206
-
1207
-
1208
-
1209
-
1210
-
1211
-
1212
-
1213
-
1214
-
1215
-
1216
-
1217
-
1218
-
1219
-
1220
-
1221
-
1222
-
1223
-
1224
-
1225
- * @example
1226
- * // Deque for...of iteration and reverse
1227
- * const deque = new Deque<string>(['A', 'B', 'C', 'D']);
1228
- *
1229
- * // Iterate forward
1230
- * const forward: string[] = [];
1231
- * for (const item of deque) {
1232
- * forward.push(item);
1233
- * }
1234
- * console.log(forward); // ['A', 'B', 'C', 'D'];
1235
- *
1236
- * // Reverse the deque
1237
- * deque.reverse();
1238
- * const backward: string[] = [];
1239
- * for (const item of deque) {
1240
- * backward.push(item);
1241
- * }
1242
- * console.log(backward); // ['D', 'C', 'B', 'A'];
766
+ * @example
767
+ * // Deque for...of iteration and reverse
768
+ * const deque = new Deque<string>(['A', 'B', 'C', 'D']);
769
+ *
770
+ * // Iterate forward
771
+ * const forward: string[] = [];
772
+ * for (const item of deque) {
773
+ * forward.push(item);
774
+ * }
775
+ * console.log(forward); // ['A', 'B', 'C', 'D'];
776
+ *
777
+ * // Reverse the deque
778
+ * deque.reverse();
779
+ * const backward: string[] = [];
780
+ * for (const item of deque) {
781
+ * backward.push(item);
782
+ * }
783
+ * console.log(backward); // ['D', 'C', 'B', 'A'];
784
+ */
785
+ /**
786
+ * Find the last value matching a predicate (scans back-to-front).
787
+ * @remarks Provided for familiarity when migrating from Array. Time O(n), Space O(1).
788
+ * @param predicate - Function called with (value, index, deque).
789
+ * @returns Matching value or undefined.
790
+ * @example
791
+ * // Find last matching value
792
+ * const d = new Deque([1, 2, 3, 4, 5]);
793
+ * console.log(d.findLast(v => v > 2)); // 5;
794
+ * console.log(d.findLast(v => v % 2 === 0)); // 4;
1243
795
  */
796
+ findLast(predicate: (value: E, index: number, deque: this) => boolean): E | undefined {
797
+ for (let i = this.length - 1; i >= 0; i--) {
798
+ const val = this.at(i)!;
799
+ if (predicate(val, i, this)) return val;
800
+ }
801
+ return undefined;
802
+ }
1244
803
 
804
+ /**
805
+ * Find the index of the last value matching a predicate (scans back-to-front).
806
+ * @remarks Provided for familiarity when migrating from Array. Time O(n), Space O(1).
807
+ * @param predicate - Function called with (value, index, deque).
808
+ * @returns Matching index, or -1 if not found.
809
+ * @example
810
+ * // Find last matching index
811
+ * const d = new Deque([10, 20, 30, 20, 10]);
812
+ * console.log(d.findLastIndex(v => v === 20)); // 3;
813
+ * console.log(d.findLastIndex(v => v === 10)); // 4;
814
+ */
815
+ findLastIndex(predicate: (value: E, index: number, deque: this) => boolean): number {
816
+ for (let i = this.length - 1; i >= 0; i--) {
817
+ if (predicate(this.at(i)!, i, this)) return i;
818
+ }
819
+ return -1;
820
+ }
821
+
822
+ /**
823
+ * Deque for...of iteration and reverse
824
+ * @example
825
+ * // Deque for...of iteration and reverse
826
+ * const deque = new Deque<string>(['A', 'B', 'C', 'D']);
827
+ *
828
+ * // Iterate forward
829
+ * const forward: string[] = [];
830
+ * for (const item of deque) {
831
+ * forward.push(item);
832
+ * }
833
+ * console.log(forward); // ['A', 'B', 'C', 'D'];
834
+ *
835
+ * // Reverse the deque
836
+ * deque.reverse();
837
+ * const backward: string[] = [];
838
+ * for (const item of deque) {
839
+ * backward.push(item);
840
+ * }
841
+ * console.log(backward); // ['D', 'C', 'B', 'A'];
842
+ */
1245
843
  reverse(): this {
1246
844
  this._buckets.reverse().forEach(function (bucket) {
1247
845
  bucket.reverse();
@@ -1259,7 +857,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1259
857
  * @remarks Time O(N), Space O(1)
1260
858
  * @returns This deque.
1261
859
  */
1262
-
1263
860
  unique(): this {
1264
861
  if (this._length <= 1) {
1265
862
  return this;
@@ -1277,30 +874,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1277
874
  return this;
1278
875
  }
1279
876
 
1280
- /**
1281
- * Trim unused buckets to fit exactly the active range.
1282
- * @remarks Time O(N), Space O(1)
1283
- * @returns void
1284
- */
1285
-
1286
- /**
1287
- * (Protected) Trigger auto-compaction if space utilization drops below threshold.
1288
- * Only checks every `_bucketSize` operations to minimize hot-path overhead.
1289
- * Uses element-based ratio: `elements / (bucketCount * bucketSize)`.
1290
- */
1291
- protected _autoCompact(): void {
1292
- if (this._autoCompactRatio <= 0 || this._bucketCount <= 1) return;
1293
-
1294
- this._compactCounter++;
1295
- if (this._compactCounter < this._bucketSize) return;
1296
- this._compactCounter = 0;
1297
-
1298
- const utilization = this._length / (this._bucketCount * this._bucketSize);
1299
- if (utilization < this._autoCompactRatio) {
1300
- this.shrinkToFit();
1301
- }
1302
- }
1303
-
1304
877
  /**
1305
878
  * Compact the deque by removing unused buckets.
1306
879
  * @remarks Time O(N), Space O(1)
@@ -1310,49 +883,13 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1310
883
  * Compact the deque by removing unused buckets.
1311
884
  * @remarks Time O(N), Space O(1)
1312
885
  * @returns True if compaction was performed (bucket count reduced).
1313
-
1314
-
1315
-
1316
-
1317
-
1318
-
1319
-
1320
-
1321
-
1322
-
1323
-
1324
-
1325
-
1326
-
1327
-
1328
-
1329
-
1330
-
1331
-
1332
-
1333
-
1334
-
1335
-
1336
-
1337
-
1338
-
1339
-
1340
-
1341
-
1342
-
1343
-
1344
-
1345
-
1346
-
1347
-
1348
-
1349
- * @example
1350
- * // Reclaim memory
1351
- * const dq = new Deque<number>([1, 2, 3, 4, 5]);
1352
- * dq.shift();
1353
- * dq.shift();
1354
- * dq.compact();
1355
- * console.log(dq.length); // 3;
886
+ * @example
887
+ * // Reclaim memory
888
+ * const dq = new Deque<number>([1, 2, 3, 4, 5]);
889
+ * dq.shift();
890
+ * dq.shift();
891
+ * dq.compact();
892
+ * console.log(dq.length); // 3;
1356
893
  */
1357
894
  compact(): boolean {
1358
895
  const before = this._bucketCount;
@@ -1386,52 +923,14 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1386
923
  * Deep clone this deque, preserving options.
1387
924
  * @remarks Time O(N), Space O(N)
1388
925
  * @returns A new deque with the same content and options.
1389
-
1390
-
1391
-
1392
-
1393
-
1394
-
1395
-
1396
-
1397
-
1398
-
1399
-
1400
-
1401
-
1402
-
1403
-
1404
-
1405
-
1406
-
1407
-
1408
-
1409
-
1410
-
1411
-
1412
-
1413
-
1414
-
1415
-
1416
-
1417
-
1418
-
1419
-
1420
-
1421
-
1422
-
1423
-
1424
-
1425
-
1426
- * @example
1427
- * // Create independent copy
1428
- * const dq = new Deque<number>([1, 2, 3]);
1429
- * const copy = dq.clone();
1430
- * copy.pop();
1431
- * console.log(dq.length); // 3;
1432
- * console.log(copy.length); // 2;
926
+ * @example
927
+ * // Create independent copy
928
+ * const dq = new Deque<number>([1, 2, 3]);
929
+ * const copy = dq.clone();
930
+ * copy.pop();
931
+ * console.log(dq.length); // 3;
932
+ * console.log(copy.length); // 2;
1433
933
  */
1434
-
1435
934
  clone(): this {
1436
935
  return this._createLike<E, R>(this, {
1437
936
  bucketSize: this.bucketSize,
@@ -1446,50 +945,12 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1446
945
  * @param predicate - Predicate (value, index, deque) → boolean to keep element.
1447
946
  * @param [thisArg] - Value for `this` inside the predicate.
1448
947
  * @returns A new deque with kept elements.
1449
-
1450
-
1451
-
1452
-
1453
-
1454
-
1455
-
1456
-
1457
-
1458
-
1459
-
1460
-
1461
-
1462
-
1463
-
1464
-
1465
-
1466
-
1467
-
1468
-
1469
-
1470
-
1471
-
1472
-
1473
-
1474
-
1475
-
1476
-
1477
-
1478
-
1479
-
1480
-
1481
-
1482
-
1483
-
1484
-
1485
-
1486
- * @example
1487
- * // Filter elements
1488
- * const dq = new Deque<number>([1, 2, 3, 4]);
1489
- * const result = dq.filter(x => x > 2);
1490
- * console.log(result.length); // 2;
948
+ * @example
949
+ * // Filter elements
950
+ * const dq = new Deque<number>([1, 2, 3, 4]);
951
+ * const result = dq.filter(x => x > 2);
952
+ * console.log(result.length); // 2;
1491
953
  */
1492
-
1493
954
  filter(predicate: ElementCallback<E, R, boolean>, thisArg?: unknown): this {
1494
955
  const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
1495
956
  out._setBucketSize(this._bucketSize);
@@ -1508,7 +969,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1508
969
  * @param [thisArg] - Value for `this` inside the callback.
1509
970
  * @returns A new deque with mapped values.
1510
971
  */
1511
-
1512
972
  mapSame(callback: ElementCallback<E, R, E>, thisArg?: unknown): this {
1513
973
  const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
1514
974
  out._setBucketSize(this._bucketSize);
@@ -1529,49 +989,12 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1529
989
  * @param [options] - Options for the output deque (e.g., bucketSize, toElementFn, maxLen).
1530
990
  * @param [thisArg] - Value for `this` inside the callback.
1531
991
  * @returns A new Deque with mapped elements.
1532
-
1533
-
1534
-
1535
-
1536
-
1537
-
1538
-
1539
-
1540
-
1541
-
1542
-
1543
-
1544
-
1545
-
1546
-
1547
-
1548
-
1549
-
1550
-
1551
-
1552
-
1553
-
1554
-
1555
-
1556
-
1557
-
1558
-
1559
-
1560
-
1561
-
1562
-
1563
-
1564
-
1565
-
1566
-
1567
-
1568
- * @example
1569
- * // Transform elements
1570
- * const dq = new Deque<number>([1, 2, 3]);
1571
- * const result = dq.map(x => x * 10);
1572
- * console.log(result.toArray()); // [10, 20, 30];
992
+ * @example
993
+ * // Transform elements
994
+ * const dq = new Deque<number>([1, 2, 3]);
995
+ * const result = dq.map(x => x * 10);
996
+ * console.log(result.toArray()); // [10, 20, 30];
1573
997
  */
1574
-
1575
998
  map<EM, RM>(
1576
999
  callback: ElementCallback<E, R, EM>,
1577
1000
  options?: IterableElementBaseOptions<EM, RM>,
@@ -1591,16 +1014,37 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1591
1014
  return out;
1592
1015
  }
1593
1016
 
1017
+ protected _equals: (a: E, b: E) => boolean = (a, b) => Object.is(a, b);
1018
+
1019
+ /**
1020
+ * Trim unused buckets to fit exactly the active range.
1021
+ * @remarks Time O(N), Space O(1)
1022
+ * @returns void
1023
+ */
1024
+ /**
1025
+ * (Protected) Trigger auto-compaction if space utilization drops below threshold.
1026
+ * Only checks every `_bucketSize` operations to minimize hot-path overhead.
1027
+ * Uses element-based ratio: `elements / (bucketCount * bucketSize)`.
1028
+ */
1029
+ protected _autoCompact(): void {
1030
+ if (this._autoCompactRatio <= 0 || this._bucketCount <= 1) return;
1031
+ this._compactCounter++;
1032
+ if (this._compactCounter < this._bucketSize) return;
1033
+ this._compactCounter = 0;
1034
+ const utilization = this._length / (this._bucketCount * this._bucketSize);
1035
+ if (utilization < this._autoCompactRatio) {
1036
+ this.shrinkToFit();
1037
+ }
1038
+ }
1039
+
1594
1040
  /**
1595
1041
  * (Protected) Set the internal bucket size.
1596
1042
  * @remarks Time O(1), Space O(1)
1597
1043
  * @param size - Bucket capacity to assign.
1598
1044
  * @returns void
1599
1045
  */
1600
-
1601
1046
  protected _setBucketSize(size: number): void {
1602
1047
  this._bucketSize = size;
1603
-
1604
1048
  // When adjusting bucketSize on a freshly created empty deque (common in helpers like cut/splice/clone),
1605
1049
  // we must also realign internal pointers/buckets to avoid `_getBucketAndPosition` producing out-of-range
1606
1050
  // indices based on the previous bucketSize.
@@ -1617,7 +1061,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1617
1061
  * @remarks Time O(N), Space O(1)
1618
1062
  * @returns Iterator of elements.
1619
1063
  */
1620
-
1621
1064
  protected *_getIterator(): IterableIterator<E> {
1622
1065
  for (let i = 0; i < this._length; ++i) {
1623
1066
  const v = this.at(i);
@@ -1631,7 +1074,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1631
1074
  * @param [needBucketNum] - How many extra buckets to add; defaults to half of current.
1632
1075
  * @returns void
1633
1076
  */
1634
-
1635
1077
  protected _reallocate(needBucketNum?: number) {
1636
1078
  const newBuckets = [] as E[][];
1637
1079
  const addBucketNum = needBucketNum || this._bucketCount >> 1 || 1;
@@ -1660,23 +1102,18 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1660
1102
  * @param pos - Zero-based position.
1661
1103
  * @returns An object containing bucketIndex and indexInBucket.
1662
1104
  */
1663
-
1664
1105
  protected _getBucketAndPosition(pos: number) {
1665
1106
  let bucketIndex: number;
1666
1107
  let indexInBucket: number;
1667
-
1668
1108
  const overallIndex = this._firstInBucket + pos;
1669
1109
  bucketIndex = this._bucketFirst + Math.floor(overallIndex / this._bucketSize);
1670
-
1671
1110
  if (bucketIndex >= this._bucketCount) {
1672
1111
  bucketIndex -= this._bucketCount;
1673
1112
  }
1674
-
1675
1113
  indexInBucket = ((overallIndex + 1) % this._bucketSize) - 1;
1676
1114
  if (indexInBucket < 0) {
1677
1115
  indexInBucket = this._bucketSize - 1;
1678
1116
  }
1679
-
1680
1117
  return { bucketIndex, indexInBucket };
1681
1118
  }
1682
1119
 
@@ -1686,7 +1123,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1686
1123
  * @param [options] - Options forwarded to the constructor.
1687
1124
  * @returns An empty like-kind deque instance.
1688
1125
  */
1689
-
1690
1126
  protected override _createInstance(options?: LinearBaseOptions<E, R>): this {
1691
1127
  const Ctor = this.constructor as new (
1692
1128
  elements?: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R>,
@@ -1704,7 +1140,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1704
1140
  * @param [options] - Options forwarded to the constructor.
1705
1141
  * @returns A like-kind Deque instance.
1706
1142
  */
1707
-
1708
1143
  protected _createLike<T = E, RR = R>(
1709
1144
  elements: IterableWithSizeOrLength<T> | IterableWithSizeOrLength<RR> = [],
1710
1145
  options?: DequeOptions<T, RR>
@@ -1721,7 +1156,6 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
1721
1156
  * @remarks Time O(N), Space O(1)
1722
1157
  * @returns Iterator of elements.
1723
1158
  */
1724
-
1725
1159
  protected *_getReverseIterator(): IterableIterator<E> {
1726
1160
  for (let i = this._length - 1; i > -1; i--) {
1727
1161
  const v = this.at(i);