deque-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/deque-typed.js +114 -35
  19. package/dist/umd/deque-typed.js.map +1 -1
  20. package/dist/umd/deque-typed.min.js +1 -1
  21. package/dist/umd/deque-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
@@ -2,11 +2,62 @@ var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
 
4
4
  // src/utils/utils.ts
5
- var rangeCheck = /* @__PURE__ */ __name((index, min, max, message = "Index out of bounds.") => {
6
- if (index < min || index > max) throw new RangeError(message);
5
+ var rangeCheck = /* @__PURE__ */ __name((index, min, max, message) => {
6
+ if (index < min || index > max) {
7
+ throw new RangeError(message ?? `Index ${index} is out of range [${min}, ${max}].`);
8
+ }
7
9
  }, "rangeCheck");
8
10
  var calcMinUnitsRequired = /* @__PURE__ */ __name((totalQuantity, unitSize) => Math.floor((totalQuantity + unitSize - 1) / unitSize), "calcMinUnitsRequired");
9
11
 
12
+ // src/common/error.ts
13
+ var ERR = {
14
+ // Range / index
15
+ indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
16
+ invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
17
+ // Type / argument
18
+ invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
19
+ comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
20
+ invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
21
+ notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
22
+ invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
23
+ invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
24
+ invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
25
+ reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
26
+ callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
27
+ // State / operation
28
+ invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
29
+ // Matrix
30
+ matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
31
+ matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
32
+ matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
33
+ matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
34
+ matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
35
+ };
36
+
37
+ // src/common/index.ts
38
+ var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
39
+ DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
40
+ DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
41
+ return DFSOperation2;
42
+ })(DFSOperation || {});
43
+ var Range = class {
44
+ constructor(low, high, includeLow = true, includeHigh = true) {
45
+ this.low = low;
46
+ this.high = high;
47
+ this.includeLow = includeLow;
48
+ this.includeHigh = includeHigh;
49
+ }
50
+ static {
51
+ __name(this, "Range");
52
+ }
53
+ // Determine whether a key is within the range
54
+ isInRange(key, comparator) {
55
+ const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
56
+ const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
57
+ return lowCheck && highCheck;
58
+ }
59
+ };
60
+
10
61
  // src/data-structures/base/iterable-element-base.ts
11
62
  var IterableElementBase = class {
12
63
  static {
@@ -25,7 +76,7 @@ var IterableElementBase = class {
25
76
  if (options) {
26
77
  const { toElementFn } = options;
27
78
  if (typeof toElementFn === "function") this._toElementFn = toElementFn;
28
- else if (toElementFn) throw new TypeError("toElementFn must be a function type");
79
+ else if (toElementFn) throw new TypeError(ERR.notAFunction("toElementFn"));
29
80
  }
30
81
  }
31
82
  /**
@@ -188,7 +239,7 @@ var IterableElementBase = class {
188
239
  acc = initialValue;
189
240
  } else {
190
241
  const first = iter.next();
191
- if (first.done) throw new TypeError("Reduce of empty structure with no initial value");
242
+ if (first.done) throw new TypeError(ERR.reduceEmpty());
192
243
  acc = first.value;
193
244
  index = 1;
194
245
  }
@@ -429,18 +480,12 @@ var Deque = class extends LinearBase {
429
480
  __name(this, "Deque");
430
481
  }
431
482
  _equals = /* @__PURE__ */ __name((a, b) => Object.is(a, b), "_equals");
432
- /**
433
- * Create a Deque and optionally bulk-insert elements.
434
- * @remarks Time O(N), Space O(N)
435
- * @param [elements] - Iterable (or iterable-like) of elements/records to insert.
436
- * @param [options] - Options such as bucketSize, toElementFn, and maxLen.
437
- * @returns New Deque instance.
438
- */
439
483
  constructor(elements = [], options) {
440
484
  super(options);
441
485
  if (options) {
442
- const { bucketSize } = options;
486
+ const { bucketSize, autoCompactRatio } = options;
443
487
  if (typeof bucketSize === "number") this._bucketSize = bucketSize;
488
+ if (typeof autoCompactRatio === "number") this._autoCompactRatio = autoCompactRatio;
444
489
  }
445
490
  let _size;
446
491
  if ("length" in elements) {
@@ -466,6 +511,30 @@ var Deque = class extends LinearBase {
466
511
  get bucketSize() {
467
512
  return this._bucketSize;
468
513
  }
514
+ _autoCompactRatio = 0.5;
515
+ /**
516
+ * Get the auto-compaction ratio.
517
+ * When `elements / (bucketCount * bucketSize)` drops below this ratio after
518
+ * enough shift/pop operations, the deque auto-compacts.
519
+ * @remarks Time O(1), Space O(1)
520
+ * @returns Current ratio threshold. 0 means auto-compact is disabled.
521
+ */
522
+ get autoCompactRatio() {
523
+ return this._autoCompactRatio;
524
+ }
525
+ /**
526
+ * Set the auto-compaction ratio.
527
+ * @remarks Time O(1), Space O(1)
528
+ * @param value - Ratio in [0,1]. 0 disables auto-compact.
529
+ */
530
+ set autoCompactRatio(value) {
531
+ this._autoCompactRatio = value;
532
+ }
533
+ /**
534
+ * Counter for shift/pop operations since last compaction check.
535
+ * Only checks ratio every `_bucketSize` operations to minimize overhead.
536
+ */
537
+ _compactCounter = 0;
469
538
  _bucketFirst = 0;
470
539
  /**
471
540
  * Get the index of the first bucket in use.
@@ -604,6 +673,7 @@ var Deque = class extends LinearBase {
604
673
  }
605
674
  }
606
675
  this._length -= 1;
676
+ this._autoCompact();
607
677
  return element;
608
678
  }
609
679
  /**
@@ -626,6 +696,7 @@ var Deque = class extends LinearBase {
626
696
  }
627
697
  }
628
698
  this._length -= 1;
699
+ this._autoCompact();
629
700
  return element;
630
701
  }
631
702
  /**
@@ -958,11 +1029,40 @@ var Deque = class extends LinearBase {
958
1029
  * @remarks Time O(N), Space O(1)
959
1030
  * @returns void
960
1031
  */
1032
+ /**
1033
+ * (Protected) Trigger auto-compaction if space utilization drops below threshold.
1034
+ * Only checks every `_bucketSize` operations to minimize hot-path overhead.
1035
+ * Uses element-based ratio: `elements / (bucketCount * bucketSize)`.
1036
+ */
1037
+ _autoCompact() {
1038
+ if (this._autoCompactRatio <= 0 || this._bucketCount <= 1) return;
1039
+ this._compactCounter++;
1040
+ if (this._compactCounter < this._bucketSize) return;
1041
+ this._compactCounter = 0;
1042
+ const utilization = this._length / (this._bucketCount * this._bucketSize);
1043
+ if (utilization < this._autoCompactRatio) {
1044
+ this.shrinkToFit();
1045
+ }
1046
+ }
1047
+ /**
1048
+ * Compact the deque by removing unused buckets.
1049
+ * @remarks Time O(N), Space O(1)
1050
+ * @returns True if compaction was performed (bucket count reduced).
1051
+ */
1052
+ /**
1053
+ * Compact the deque by removing unused buckets.
1054
+ * @remarks Time O(N), Space O(1)
1055
+ * @returns True if compaction was performed (bucket count reduced).
1056
+ */
1057
+ compact() {
1058
+ const before = this._bucketCount;
1059
+ this.shrinkToFit();
1060
+ return this._bucketCount < before;
1061
+ }
961
1062
  shrinkToFit() {
962
1063
  if (this._length === 0) return;
963
1064
  const newBuckets = [];
964
- if (this._bucketFirst === this._bucketLast) return;
965
- else if (this._bucketFirst < this._bucketLast) {
1065
+ if (this._bucketFirst <= this._bucketLast) {
966
1066
  for (let i = this._bucketFirst; i <= this._bucketLast; ++i) {
967
1067
  newBuckets.push(this._buckets[i]);
968
1068
  }
@@ -977,6 +1077,8 @@ var Deque = class extends LinearBase {
977
1077
  this._bucketFirst = 0;
978
1078
  this._bucketLast = newBuckets.length - 1;
979
1079
  this._buckets = newBuckets;
1080
+ this._bucketCount = newBuckets.length;
1081
+ this._compactCounter = 0;
980
1082
  }
981
1083
  /**
982
1084
  * Deep clone this deque, preserving options.
@@ -1156,30 +1258,6 @@ var Deque = class extends LinearBase {
1156
1258
  }
1157
1259
  }
1158
1260
  };
1159
-
1160
- // src/common/index.ts
1161
- var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
1162
- DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
1163
- DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
1164
- return DFSOperation2;
1165
- })(DFSOperation || {});
1166
- var Range = class {
1167
- constructor(low, high, includeLow = true, includeHigh = true) {
1168
- this.low = low;
1169
- this.high = high;
1170
- this.includeLow = includeLow;
1171
- this.includeHigh = includeHigh;
1172
- }
1173
- static {
1174
- __name(this, "Range");
1175
- }
1176
- // Determine whether a key is within the range
1177
- isInRange(key, comparator) {
1178
- const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
1179
- const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
1180
- return lowCheck && highCheck;
1181
- }
1182
- };
1183
1261
  /**
1184
1262
  * data-structure-typed
1185
1263
  *
@@ -1188,6 +1266,6 @@ var Range = class {
1188
1266
  * @license MIT License
1189
1267
  */
1190
1268
 
1191
- export { DFSOperation, Deque, Range };
1269
+ export { DFSOperation, Deque, ERR, Range };
1192
1270
  //# sourceMappingURL=index.mjs.map
1193
1271
  //# sourceMappingURL=index.mjs.map