queue-typed 2.4.4 → 2.4.5

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 (45) hide show
  1. package/dist/cjs/index.cjs +117 -38
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs-legacy/index.cjs +116 -37
  4. package/dist/cjs-legacy/index.cjs.map +1 -1
  5. package/dist/esm/index.mjs +117 -39
  6. package/dist/esm/index.mjs.map +1 -1
  7. package/dist/esm-legacy/index.mjs +116 -38
  8. package/dist/esm-legacy/index.mjs.map +1 -1
  9. package/dist/types/common/error.d.ts +23 -0
  10. package/dist/types/common/index.d.ts +1 -0
  11. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +10 -0
  12. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +7 -1
  13. package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
  14. package/dist/types/data-structures/graph/directed-graph.d.ts +1 -0
  15. package/dist/types/data-structures/graph/undirected-graph.d.ts +14 -0
  16. package/dist/types/data-structures/queue/deque.d.ts +41 -1
  17. package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
  18. package/dist/umd/queue-typed.js +114 -35
  19. package/dist/umd/queue-typed.js.map +1 -1
  20. package/dist/umd/queue-typed.min.js +1 -1
  21. package/dist/umd/queue-typed.min.js.map +1 -1
  22. package/package.json +2 -2
  23. package/src/common/error.ts +60 -0
  24. package/src/common/index.ts +2 -0
  25. package/src/data-structures/base/iterable-element-base.ts +3 -2
  26. package/src/data-structures/binary-tree/binary-indexed-tree.ts +6 -5
  27. package/src/data-structures/binary-tree/binary-tree.ts +113 -42
  28. package/src/data-structures/binary-tree/bst.ts +11 -3
  29. package/src/data-structures/binary-tree/red-black-tree.ts +20 -0
  30. package/src/data-structures/binary-tree/tree-map.ts +8 -7
  31. package/src/data-structures/binary-tree/tree-multi-map.ts +4 -4
  32. package/src/data-structures/binary-tree/tree-multi-set.ts +5 -4
  33. package/src/data-structures/binary-tree/tree-set.ts +7 -6
  34. package/src/data-structures/graph/abstract-graph.ts +106 -1
  35. package/src/data-structures/graph/directed-graph.ts +4 -0
  36. package/src/data-structures/graph/undirected-graph.ts +95 -0
  37. package/src/data-structures/hash/hash-map.ts +13 -2
  38. package/src/data-structures/heap/heap.ts +4 -3
  39. package/src/data-structures/heap/max-heap.ts +2 -3
  40. package/src/data-structures/matrix/matrix.ts +9 -10
  41. package/src/data-structures/priority-queue/max-priority-queue.ts +2 -3
  42. package/src/data-structures/queue/deque.ts +71 -3
  43. package/src/data-structures/trie/trie.ts +2 -1
  44. package/src/types/data-structures/queue/deque.ts +7 -0
  45. package/src/utils/utils.ts +4 -2
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Centralized error message templates.
3
+ * Keep using native Error/TypeError/RangeError — this only standardizes messages.
4
+ */
5
+ export declare const ERR: {
6
+ readonly indexOutOfRange: (index: number, min: number, max: number, ctx?: string) => string;
7
+ readonly invalidIndex: (ctx?: string) => string;
8
+ readonly invalidArgument: (reason: string, ctx?: string) => string;
9
+ readonly comparatorRequired: (ctx?: string) => string;
10
+ readonly invalidKey: (reason: string, ctx?: string) => string;
11
+ readonly notAFunction: (name: string, ctx?: string) => string;
12
+ readonly invalidEntry: (ctx?: string) => string;
13
+ readonly invalidNaN: (ctx?: string) => string;
14
+ readonly invalidDate: (ctx?: string) => string;
15
+ readonly reduceEmpty: (ctx?: string) => string;
16
+ readonly callbackReturnType: (expected: string, got: string, ctx?: string) => string;
17
+ readonly invalidOperation: (reason: string, ctx?: string) => string;
18
+ readonly matrixDimensionMismatch: (op: string) => string;
19
+ readonly matrixSingular: () => string;
20
+ readonly matrixNotSquare: () => string;
21
+ readonly matrixNotRectangular: () => string;
22
+ readonly matrixRowMismatch: (expected: number, got: number) => string;
23
+ };
@@ -1,3 +1,4 @@
1
+ export { ERR } from './error';
1
2
  export declare enum DFSOperation {
2
3
  VISIT = 0,
3
4
  PROCESS = 1
@@ -735,6 +735,16 @@ export declare class BinaryTree<K = any, V = any, R = any> extends IterableEntry
735
735
  * @returns Layout information for this subtree.
736
736
  */
737
737
  protected _displayAux(node: BinaryTreeNode<K, V> | null | undefined, options: BinaryTreePrintOptions): NodeDisplayLayout;
738
+ protected static _buildNodeDisplay(line: string, width: number, left: NodeDisplayLayout, right: NodeDisplayLayout): NodeDisplayLayout;
739
+ /**
740
+ * Check if a node is a display leaf (empty, null, undefined, NIL, or real leaf).
741
+ */
742
+ protected _isDisplayLeaf(node: BinaryTreeNode<K, V> | null | undefined, options: BinaryTreePrintOptions): boolean;
743
+ protected _hasDisplayableChild(child: BinaryTreeNode<K, V> | null | undefined, options: BinaryTreePrintOptions): boolean;
744
+ /**
745
+ * Resolve a display leaf node to its layout.
746
+ */
747
+ protected _resolveDisplayLeaf(node: BinaryTreeNode<K, V> | null | undefined, options: BinaryTreePrintOptions, emptyDisplayLayout: NodeDisplayLayout): NodeDisplayLayout;
738
748
  /**
739
749
  * (Protected) Swaps the key/value properties of two nodes.
740
750
  * @remarks Time O(1)
@@ -5,7 +5,7 @@
5
5
  * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
6
6
  * @license MIT License
7
7
  */
8
- import type { BinaryTreeDeleteResult, BTNRep, CRUD, EntryCallback, FamilyPosition, NodePredicate, RBTNColor, RedBlackTreeOptions } from '../../types';
8
+ import type { BinaryTreeDeleteResult, BTNRep, CRUD, EntryCallback, FamilyPosition, NodePredicate, RBTNColor, IterationType, RedBlackTreeOptions } from '../../types';
9
9
  import { BST } from './bst';
10
10
  import { IBinaryTree } from '../../interfaces';
11
11
  export declare class RedBlackTreeNode<K = any, V = any> {
@@ -375,6 +375,12 @@ export declare class RedBlackTree<K = any, V = any, R = any> extends BST<K, V, R
375
375
  * @param [thisArg] - See parameter type for details.
376
376
  * @returns A new RedBlackTree with mapped entries.
377
377
  */
378
+ /**
379
+ * Red-Black trees are self-balancing — `perfectlyBalance` rebuilds via
380
+ * sorted bulk insert, which naturally produces a balanced RBT.
381
+ * @remarks Time O(N), Space O(N)
382
+ */
383
+ perfectlyBalance(iterationType?: IterationType): boolean;
378
384
  map<MK = K, MV = V, MR = any>(callback: EntryCallback<K, V | undefined, [MK, MV]>, options?: Partial<RedBlackTreeOptions<MK, MV, MR>>, thisArg?: unknown): RedBlackTree<MK, MV, MR>;
379
385
  /**
380
386
  * (Internal) Create an empty instance of the same concrete tree type.
@@ -337,4 +337,48 @@ export declare abstract class AbstractGraph<V = any, E = any, VO extends Abstrac
337
337
  * @remarks Time O(1), Space O(1)
338
338
  */
339
339
  protected _getVertexKey(vertexOrKey: VO | VertexKey): VertexKey;
340
+ /**
341
+ * The edge connector string used in visual output.
342
+ * Override in subclasses (e.g., '--' for undirected, '->' for directed).
343
+ */
344
+ protected get _edgeConnector(): string;
345
+ /**
346
+ * Generate a text-based visual representation of the graph.
347
+ *
348
+ * **Adjacency list format:**
349
+ * ```
350
+ * Graph (5 vertices, 6 edges):
351
+ * A -> B (1), C (2)
352
+ * B -> D (3)
353
+ * C -> (no outgoing edges)
354
+ * D -> A (1)
355
+ * E (isolated)
356
+ * ```
357
+ *
358
+ * @param options - Optional display settings.
359
+ * @param options.showWeight - Whether to show edge weights (default: true).
360
+ * @returns The visual string.
361
+ */
362
+ toVisual(options?: {
363
+ showWeight?: boolean;
364
+ }): string;
365
+ /**
366
+ * Generate DOT language representation for Graphviz.
367
+ *
368
+ * @param options - Optional display settings.
369
+ * @param options.name - Graph name (default: 'G').
370
+ * @param options.showWeight - Whether to label edges with weight (default: true).
371
+ * @returns DOT format string.
372
+ */
373
+ toDot(options?: {
374
+ name?: string;
375
+ showWeight?: boolean;
376
+ }): string;
377
+ /**
378
+ * Print the graph to console.
379
+ * @param options - Display settings passed to `toVisual`.
380
+ */
381
+ print(options?: {
382
+ showWeight?: boolean;
383
+ }): void;
340
384
  }
@@ -157,6 +157,7 @@ export declare class DirectedGraph<V = any, E = any, VO extends DirectedVertex<V
157
157
  * @remarks Time O(1), Space O(1)
158
158
  */
159
159
  constructor(options?: Partial<GraphOptions<V>>);
160
+ protected get _edgeConnector(): string;
160
161
  protected _outEdgeMap: Map<VO, EO[]>;
161
162
  get outEdgeMap(): Map<VO, EO[]>;
162
163
  set outEdgeMap(v: Map<VO, EO[]>);
@@ -313,6 +313,20 @@ export declare class UndirectedGraph<V = any, E = any, VO extends UndirectedVert
313
313
  bridges: EO[];
314
314
  cutVertices: VO[];
315
315
  };
316
+ /**
317
+ * Find biconnected components using edge-stack Tarjan variant.
318
+ * A biconnected component is a maximal biconnected subgraph.
319
+ * @returns Array of edge arrays, each representing a biconnected component.
320
+ * @remarks Time O(V + E), Space O(V + E)
321
+ */
322
+ getBiconnectedComponents(): EO[][];
323
+ /**
324
+ * Detect whether the graph contains a cycle.
325
+ * Uses DFS with parent tracking.
326
+ * @returns `true` if a cycle exists, `false` otherwise.
327
+ * @remarks Time O(V + E), Space O(V)
328
+ */
329
+ hasCycle(): boolean;
316
330
  /**
317
331
  * Get bridges discovered by `tarjan()`.
318
332
  * @returns Array of edges that are bridges.
@@ -143,7 +143,10 @@ export declare class Deque<E = any, R = any> extends LinearBase<E, R> {
143
143
  * @param [options] - Options such as bucketSize, toElementFn, and maxLen.
144
144
  * @returns New Deque instance.
145
145
  */
146
- constructor(elements?: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R>, options?: DequeOptions<E, R>);
146
+ constructor(elements?: IterableWithSizeOrLength<E>, options?: DequeOptions<E, R>);
147
+ constructor(elements: IterableWithSizeOrLength<R>, options: DequeOptions<E, R> & {
148
+ toElementFn: (rawElement: R) => E;
149
+ });
147
150
  protected _bucketSize: number;
148
151
  /**
149
152
  * Get the current bucket size.
@@ -151,6 +154,26 @@ export declare class Deque<E = any, R = any> extends LinearBase<E, R> {
151
154
  * @returns Bucket capacity per bucket.
152
155
  */
153
156
  get bucketSize(): number;
157
+ protected _autoCompactRatio: number;
158
+ /**
159
+ * Get the auto-compaction ratio.
160
+ * When `elements / (bucketCount * bucketSize)` drops below this ratio after
161
+ * enough shift/pop operations, the deque auto-compacts.
162
+ * @remarks Time O(1), Space O(1)
163
+ * @returns Current ratio threshold. 0 means auto-compact is disabled.
164
+ */
165
+ get autoCompactRatio(): number;
166
+ /**
167
+ * Set the auto-compaction ratio.
168
+ * @remarks Time O(1), Space O(1)
169
+ * @param value - Ratio in [0,1]. 0 disables auto-compact.
170
+ */
171
+ set autoCompactRatio(value: number);
172
+ /**
173
+ * Counter for shift/pop operations since last compaction check.
174
+ * Only checks ratio every `_bucketSize` operations to minimize overhead.
175
+ */
176
+ protected _compactCounter: number;
154
177
  protected _bucketFirst: number;
155
178
  /**
156
179
  * Get the index of the first bucket in use.
@@ -369,6 +392,23 @@ export declare class Deque<E = any, R = any> extends LinearBase<E, R> {
369
392
  * @remarks Time O(N), Space O(1)
370
393
  * @returns void
371
394
  */
395
+ /**
396
+ * (Protected) Trigger auto-compaction if space utilization drops below threshold.
397
+ * Only checks every `_bucketSize` operations to minimize hot-path overhead.
398
+ * Uses element-based ratio: `elements / (bucketCount * bucketSize)`.
399
+ */
400
+ protected _autoCompact(): void;
401
+ /**
402
+ * Compact the deque by removing unused buckets.
403
+ * @remarks Time O(N), Space O(1)
404
+ * @returns True if compaction was performed (bucket count reduced).
405
+ */
406
+ /**
407
+ * Compact the deque by removing unused buckets.
408
+ * @remarks Time O(N), Space O(1)
409
+ * @returns True if compaction was performed (bucket count reduced).
410
+ */
411
+ compact(): boolean;
372
412
  shrinkToFit(): void;
373
413
  /**
374
414
  * Deep clone this deque, preserving options.
@@ -1,4 +1,10 @@
1
1
  import { LinearBaseOptions } from '../base';
2
2
  export type DequeOptions<E, R> = {
3
3
  bucketSize?: number;
4
+ /**
5
+ * When the ratio of used buckets to total buckets falls below this threshold
6
+ * after a shift/pop, auto-compact is triggered. Set to 0 to disable.
7
+ * Default: 0.5 (compact when less than half the buckets are in use).
8
+ */
9
+ autoCompactRatio?: number;
4
10
  } & LinearBaseOptions<E, R>;
@@ -25,11 +25,58 @@ var queueTyped = (() => {
25
25
  __export(src_exports, {
26
26
  DFSOperation: () => DFSOperation,
27
27
  Deque: () => Deque,
28
+ ERR: () => ERR,
28
29
  LinkedListQueue: () => LinkedListQueue,
29
30
  Queue: () => Queue,
30
31
  Range: () => Range
31
32
  });
32
33
 
34
+ // src/common/error.ts
35
+ var ERR = {
36
+ // Range / index
37
+ indexOutOfRange: (index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`,
38
+ invalidIndex: (ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`,
39
+ // Type / argument
40
+ invalidArgument: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
41
+ comparatorRequired: (ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`,
42
+ invalidKey: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
43
+ notAFunction: (name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`,
44
+ invalidEntry: (ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`,
45
+ invalidNaN: (ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`,
46
+ invalidDate: (ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`,
47
+ reduceEmpty: (ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`,
48
+ callbackReturnType: (expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`,
49
+ // State / operation
50
+ invalidOperation: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
51
+ // Matrix
52
+ matrixDimensionMismatch: (op) => `Matrix: Dimensions must be compatible for ${op}.`,
53
+ matrixSingular: () => "Matrix: Singular matrix, inverse does not exist.",
54
+ matrixNotSquare: () => "Matrix: Must be square for inversion.",
55
+ matrixNotRectangular: () => "Matrix: Must be rectangular for transposition.",
56
+ matrixRowMismatch: (expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`
57
+ };
58
+
59
+ // src/common/index.ts
60
+ var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
61
+ DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
62
+ DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
63
+ return DFSOperation2;
64
+ })(DFSOperation || {});
65
+ var Range = class {
66
+ constructor(low, high, includeLow = true, includeHigh = true) {
67
+ this.low = low;
68
+ this.high = high;
69
+ this.includeLow = includeLow;
70
+ this.includeHigh = includeHigh;
71
+ }
72
+ // Determine whether a key is within the range
73
+ isInRange(key, comparator) {
74
+ const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
75
+ const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
76
+ return lowCheck && highCheck;
77
+ }
78
+ };
79
+
33
80
  // src/data-structures/base/iterable-element-base.ts
34
81
  var IterableElementBase = class {
35
82
  /**
@@ -52,7 +99,7 @@ var queueTyped = (() => {
52
99
  if (options) {
53
100
  const { toElementFn } = options;
54
101
  if (typeof toElementFn === "function") this._toElementFn = toElementFn;
55
- else if (toElementFn) throw new TypeError("toElementFn must be a function type");
102
+ else if (toElementFn) throw new TypeError(ERR.notAFunction("toElementFn"));
56
103
  }
57
104
  }
58
105
  /**
@@ -208,7 +255,7 @@ var queueTyped = (() => {
208
255
  acc = initialValue;
209
256
  } else {
210
257
  const first = iter.next();
211
- if (first.done) throw new TypeError("Reduce of empty structure with no initial value");
258
+ if (first.done) throw new TypeError(ERR.reduceEmpty());
212
259
  acc = first.value;
213
260
  index = 1;
214
261
  }
@@ -1709,24 +1756,25 @@ var queueTyped = (() => {
1709
1756
  };
1710
1757
 
1711
1758
  // src/utils/utils.ts
1712
- var rangeCheck = (index, min, max, message = "Index out of bounds.") => {
1713
- if (index < min || index > max) throw new RangeError(message);
1759
+ var rangeCheck = (index, min, max, message) => {
1760
+ if (index < min || index > max) {
1761
+ throw new RangeError(message != null ? message : `Index ${index} is out of range [${min}, ${max}].`);
1762
+ }
1714
1763
  };
1715
1764
  var calcMinUnitsRequired = (totalQuantity, unitSize) => Math.floor((totalQuantity + unitSize - 1) / unitSize);
1716
1765
 
1717
1766
  // src/data-structures/queue/deque.ts
1718
1767
  var Deque = class extends LinearBase {
1719
- /**
1720
- * Create a Deque and optionally bulk-insert elements.
1721
- * @remarks Time O(N), Space O(N)
1722
- * @param [elements] - Iterable (or iterable-like) of elements/records to insert.
1723
- * @param [options] - Options such as bucketSize, toElementFn, and maxLen.
1724
- * @returns New Deque instance.
1725
- */
1726
1768
  constructor(elements = [], options) {
1727
1769
  super(options);
1728
1770
  __publicField(this, "_equals", (a, b) => Object.is(a, b));
1729
1771
  __publicField(this, "_bucketSize", 1 << 12);
1772
+ __publicField(this, "_autoCompactRatio", 0.5);
1773
+ /**
1774
+ * Counter for shift/pop operations since last compaction check.
1775
+ * Only checks ratio every `_bucketSize` operations to minimize overhead.
1776
+ */
1777
+ __publicField(this, "_compactCounter", 0);
1730
1778
  __publicField(this, "_bucketFirst", 0);
1731
1779
  __publicField(this, "_firstInBucket", 0);
1732
1780
  __publicField(this, "_bucketLast", 0);
@@ -1735,8 +1783,9 @@ var queueTyped = (() => {
1735
1783
  __publicField(this, "_buckets", []);
1736
1784
  __publicField(this, "_length", 0);
1737
1785
  if (options) {
1738
- const { bucketSize } = options;
1786
+ const { bucketSize, autoCompactRatio } = options;
1739
1787
  if (typeof bucketSize === "number") this._bucketSize = bucketSize;
1788
+ if (typeof autoCompactRatio === "number") this._autoCompactRatio = autoCompactRatio;
1740
1789
  }
1741
1790
  let _size;
1742
1791
  if ("length" in elements) {
@@ -1761,6 +1810,24 @@ var queueTyped = (() => {
1761
1810
  get bucketSize() {
1762
1811
  return this._bucketSize;
1763
1812
  }
1813
+ /**
1814
+ * Get the auto-compaction ratio.
1815
+ * When `elements / (bucketCount * bucketSize)` drops below this ratio after
1816
+ * enough shift/pop operations, the deque auto-compacts.
1817
+ * @remarks Time O(1), Space O(1)
1818
+ * @returns Current ratio threshold. 0 means auto-compact is disabled.
1819
+ */
1820
+ get autoCompactRatio() {
1821
+ return this._autoCompactRatio;
1822
+ }
1823
+ /**
1824
+ * Set the auto-compaction ratio.
1825
+ * @remarks Time O(1), Space O(1)
1826
+ * @param value - Ratio in [0,1]. 0 disables auto-compact.
1827
+ */
1828
+ set autoCompactRatio(value) {
1829
+ this._autoCompactRatio = value;
1830
+ }
1764
1831
  /**
1765
1832
  * Get the index of the first bucket in use.
1766
1833
  * @remarks Time O(1), Space O(1)
@@ -1892,6 +1959,7 @@ var queueTyped = (() => {
1892
1959
  }
1893
1960
  }
1894
1961
  this._length -= 1;
1962
+ this._autoCompact();
1895
1963
  return element;
1896
1964
  }
1897
1965
  /**
@@ -1914,6 +1982,7 @@ var queueTyped = (() => {
1914
1982
  }
1915
1983
  }
1916
1984
  this._length -= 1;
1985
+ this._autoCompact();
1917
1986
  return element;
1918
1987
  }
1919
1988
  /**
@@ -2246,11 +2315,40 @@ var queueTyped = (() => {
2246
2315
  * @remarks Time O(N), Space O(1)
2247
2316
  * @returns void
2248
2317
  */
2318
+ /**
2319
+ * (Protected) Trigger auto-compaction if space utilization drops below threshold.
2320
+ * Only checks every `_bucketSize` operations to minimize hot-path overhead.
2321
+ * Uses element-based ratio: `elements / (bucketCount * bucketSize)`.
2322
+ */
2323
+ _autoCompact() {
2324
+ if (this._autoCompactRatio <= 0 || this._bucketCount <= 1) return;
2325
+ this._compactCounter++;
2326
+ if (this._compactCounter < this._bucketSize) return;
2327
+ this._compactCounter = 0;
2328
+ const utilization = this._length / (this._bucketCount * this._bucketSize);
2329
+ if (utilization < this._autoCompactRatio) {
2330
+ this.shrinkToFit();
2331
+ }
2332
+ }
2333
+ /**
2334
+ * Compact the deque by removing unused buckets.
2335
+ * @remarks Time O(N), Space O(1)
2336
+ * @returns True if compaction was performed (bucket count reduced).
2337
+ */
2338
+ /**
2339
+ * Compact the deque by removing unused buckets.
2340
+ * @remarks Time O(N), Space O(1)
2341
+ * @returns True if compaction was performed (bucket count reduced).
2342
+ */
2343
+ compact() {
2344
+ const before = this._bucketCount;
2345
+ this.shrinkToFit();
2346
+ return this._bucketCount < before;
2347
+ }
2249
2348
  shrinkToFit() {
2250
2349
  if (this._length === 0) return;
2251
2350
  const newBuckets = [];
2252
- if (this._bucketFirst === this._bucketLast) return;
2253
- else if (this._bucketFirst < this._bucketLast) {
2351
+ if (this._bucketFirst <= this._bucketLast) {
2254
2352
  for (let i = this._bucketFirst; i <= this._bucketLast; ++i) {
2255
2353
  newBuckets.push(this._buckets[i]);
2256
2354
  }
@@ -2265,6 +2363,8 @@ var queueTyped = (() => {
2265
2363
  this._bucketFirst = 0;
2266
2364
  this._bucketLast = newBuckets.length - 1;
2267
2365
  this._buckets = newBuckets;
2366
+ this._bucketCount = newBuckets.length;
2367
+ this._compactCounter = 0;
2268
2368
  }
2269
2369
  /**
2270
2370
  * Deep clone this deque, preserving options.
@@ -2444,27 +2544,6 @@ var queueTyped = (() => {
2444
2544
  }
2445
2545
  }
2446
2546
  };
2447
-
2448
- // src/common/index.ts
2449
- var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
2450
- DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
2451
- DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
2452
- return DFSOperation2;
2453
- })(DFSOperation || {});
2454
- var Range = class {
2455
- constructor(low, high, includeLow = true, includeHigh = true) {
2456
- this.low = low;
2457
- this.high = high;
2458
- this.includeLow = includeLow;
2459
- this.includeHigh = includeHigh;
2460
- }
2461
- // Determine whether a key is within the range
2462
- isInRange(key, comparator) {
2463
- const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
2464
- const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
2465
- return lowCheck && highCheck;
2466
- }
2467
- };
2468
2547
  return __toCommonJS(src_exports);
2469
2548
  })();
2470
2549
  /**