data-structure-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.
- package/CHANGELOG.md +22 -1
- package/README.md +24 -1
- package/dist/cjs/index.cjs +459 -132
- package/dist/cjs-legacy/index.cjs +459 -130
- package/dist/esm/index.mjs +459 -133
- package/dist/esm-legacy/index.mjs +459 -131
- package/dist/types/common/error.d.ts +23 -0
- package/dist/types/common/index.d.ts +1 -0
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +10 -0
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +7 -1
- package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
- package/dist/types/data-structures/graph/directed-graph.d.ts +1 -0
- package/dist/types/data-structures/graph/undirected-graph.d.ts +14 -0
- package/dist/types/data-structures/queue/deque.d.ts +41 -1
- package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
- package/dist/umd/data-structure-typed.js +458 -129
- package/dist/umd/data-structure-typed.min.js +4 -2
- package/package.json +2 -2
- package/src/common/error.ts +60 -0
- package/src/common/index.ts +2 -0
- package/src/data-structures/base/iterable-element-base.ts +3 -2
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +6 -5
- package/src/data-structures/binary-tree/binary-tree.ts +113 -42
- package/src/data-structures/binary-tree/bst.ts +11 -3
- package/src/data-structures/binary-tree/red-black-tree.ts +20 -0
- package/src/data-structures/binary-tree/tree-map.ts +8 -7
- package/src/data-structures/binary-tree/tree-multi-map.ts +4 -4
- package/src/data-structures/binary-tree/tree-multi-set.ts +5 -4
- package/src/data-structures/binary-tree/tree-set.ts +7 -6
- package/src/data-structures/graph/abstract-graph.ts +106 -1
- package/src/data-structures/graph/directed-graph.ts +4 -0
- package/src/data-structures/graph/undirected-graph.ts +95 -0
- package/src/data-structures/hash/hash-map.ts +13 -2
- package/src/data-structures/heap/heap.ts +4 -3
- package/src/data-structures/heap/max-heap.ts +2 -3
- package/src/data-structures/matrix/matrix.ts +9 -10
- package/src/data-structures/priority-queue/max-priority-queue.ts +2 -3
- package/src/data-structures/queue/deque.ts +71 -3
- package/src/data-structures/trie/trie.ts +2 -1
- package/src/types/data-structures/queue/deque.ts +7 -0
- package/src/utils/utils.ts +4 -2
package/dist/esm/index.mjs
CHANGED
|
@@ -183,6 +183,55 @@ var IterableEntryBase = class {
|
|
|
183
183
|
}
|
|
184
184
|
};
|
|
185
185
|
|
|
186
|
+
// src/common/error.ts
|
|
187
|
+
var ERR = {
|
|
188
|
+
// Range / index
|
|
189
|
+
indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
|
|
190
|
+
invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
|
|
191
|
+
// Type / argument
|
|
192
|
+
invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
|
|
193
|
+
comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
|
|
194
|
+
invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
|
|
195
|
+
notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
|
|
196
|
+
invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
|
|
197
|
+
invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
|
|
198
|
+
invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
|
|
199
|
+
reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
|
|
200
|
+
callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
|
|
201
|
+
// State / operation
|
|
202
|
+
invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
|
|
203
|
+
// Matrix
|
|
204
|
+
matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
|
|
205
|
+
matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
|
|
206
|
+
matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
|
|
207
|
+
matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
|
|
208
|
+
matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// src/common/index.ts
|
|
212
|
+
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
213
|
+
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
214
|
+
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
215
|
+
return DFSOperation2;
|
|
216
|
+
})(DFSOperation || {});
|
|
217
|
+
var Range = class {
|
|
218
|
+
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
219
|
+
this.low = low;
|
|
220
|
+
this.high = high;
|
|
221
|
+
this.includeLow = includeLow;
|
|
222
|
+
this.includeHigh = includeHigh;
|
|
223
|
+
}
|
|
224
|
+
static {
|
|
225
|
+
__name(this, "Range");
|
|
226
|
+
}
|
|
227
|
+
// Determine whether a key is within the range
|
|
228
|
+
isInRange(key, comparator) {
|
|
229
|
+
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
230
|
+
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
231
|
+
return lowCheck && highCheck;
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
|
|
186
235
|
// src/data-structures/base/iterable-element-base.ts
|
|
187
236
|
var IterableElementBase = class {
|
|
188
237
|
static {
|
|
@@ -201,7 +250,7 @@ var IterableElementBase = class {
|
|
|
201
250
|
if (options) {
|
|
202
251
|
const { toElementFn } = options;
|
|
203
252
|
if (typeof toElementFn === "function") this._toElementFn = toElementFn;
|
|
204
|
-
else if (toElementFn) throw new TypeError("toElementFn
|
|
253
|
+
else if (toElementFn) throw new TypeError(ERR.notAFunction("toElementFn"));
|
|
205
254
|
}
|
|
206
255
|
}
|
|
207
256
|
/**
|
|
@@ -364,7 +413,7 @@ var IterableElementBase = class {
|
|
|
364
413
|
acc = initialValue;
|
|
365
414
|
} else {
|
|
366
415
|
const first = iter.next();
|
|
367
|
-
if (first.done) throw new TypeError(
|
|
416
|
+
if (first.done) throw new TypeError(ERR.reduceEmpty());
|
|
368
417
|
acc = first.value;
|
|
369
418
|
index = 1;
|
|
370
419
|
}
|
|
@@ -432,8 +481,10 @@ var getMSB = /* @__PURE__ */ __name((value) => {
|
|
|
432
481
|
}
|
|
433
482
|
return 1 << 31 - Math.clz32(value);
|
|
434
483
|
}, "getMSB");
|
|
435
|
-
var rangeCheck = /* @__PURE__ */ __name((index, min, max, message
|
|
436
|
-
if (index < min || index > max)
|
|
484
|
+
var rangeCheck = /* @__PURE__ */ __name((index, min, max, message) => {
|
|
485
|
+
if (index < min || index > max) {
|
|
486
|
+
throw new RangeError(message ?? `Index ${index} is out of range [${min}, ${max}].`);
|
|
487
|
+
}
|
|
437
488
|
}, "rangeCheck");
|
|
438
489
|
var throwRangeError = /* @__PURE__ */ __name((message = "The value is off-limits.") => {
|
|
439
490
|
throw new RangeError(message);
|
|
@@ -856,8 +907,8 @@ var LinkedHashMap = class extends IterableEntryBase {
|
|
|
856
907
|
if (this.isEntry(rawElement)) {
|
|
857
908
|
return rawElement;
|
|
858
909
|
}
|
|
859
|
-
throw new
|
|
860
|
-
"If
|
|
910
|
+
throw new TypeError(
|
|
911
|
+
ERR.invalidArgument("If elements do not adhere to [key, value], provide options.toEntryFn to transform raw records.", "HashMap")
|
|
861
912
|
);
|
|
862
913
|
}, "_toEntryFn");
|
|
863
914
|
get toEntryFn() {
|
|
@@ -1094,6 +1145,13 @@ var LinkedHashMap = class extends IterableEntryBase {
|
|
|
1094
1145
|
}
|
|
1095
1146
|
}
|
|
1096
1147
|
_deleteNode(node) {
|
|
1148
|
+
const key = node.key;
|
|
1149
|
+
if (isWeakKey(key)) {
|
|
1150
|
+
this._objMap.delete(key);
|
|
1151
|
+
} else {
|
|
1152
|
+
const hash = this._hashFn(key);
|
|
1153
|
+
delete this._noObjMap[hash];
|
|
1154
|
+
}
|
|
1097
1155
|
const { prev, next } = node;
|
|
1098
1156
|
prev.next = next;
|
|
1099
1157
|
next.prev = prev;
|
|
@@ -3608,18 +3666,12 @@ var Deque = class extends LinearBase {
|
|
|
3608
3666
|
__name(this, "Deque");
|
|
3609
3667
|
}
|
|
3610
3668
|
_equals = /* @__PURE__ */ __name((a, b) => Object.is(a, b), "_equals");
|
|
3611
|
-
/**
|
|
3612
|
-
* Create a Deque and optionally bulk-insert elements.
|
|
3613
|
-
* @remarks Time O(N), Space O(N)
|
|
3614
|
-
* @param [elements] - Iterable (or iterable-like) of elements/records to insert.
|
|
3615
|
-
* @param [options] - Options such as bucketSize, toElementFn, and maxLen.
|
|
3616
|
-
* @returns New Deque instance.
|
|
3617
|
-
*/
|
|
3618
3669
|
constructor(elements = [], options) {
|
|
3619
3670
|
super(options);
|
|
3620
3671
|
if (options) {
|
|
3621
|
-
const { bucketSize } = options;
|
|
3672
|
+
const { bucketSize, autoCompactRatio } = options;
|
|
3622
3673
|
if (typeof bucketSize === "number") this._bucketSize = bucketSize;
|
|
3674
|
+
if (typeof autoCompactRatio === "number") this._autoCompactRatio = autoCompactRatio;
|
|
3623
3675
|
}
|
|
3624
3676
|
let _size;
|
|
3625
3677
|
if ("length" in elements) {
|
|
@@ -3645,6 +3697,30 @@ var Deque = class extends LinearBase {
|
|
|
3645
3697
|
get bucketSize() {
|
|
3646
3698
|
return this._bucketSize;
|
|
3647
3699
|
}
|
|
3700
|
+
_autoCompactRatio = 0.5;
|
|
3701
|
+
/**
|
|
3702
|
+
* Get the auto-compaction ratio.
|
|
3703
|
+
* When `elements / (bucketCount * bucketSize)` drops below this ratio after
|
|
3704
|
+
* enough shift/pop operations, the deque auto-compacts.
|
|
3705
|
+
* @remarks Time O(1), Space O(1)
|
|
3706
|
+
* @returns Current ratio threshold. 0 means auto-compact is disabled.
|
|
3707
|
+
*/
|
|
3708
|
+
get autoCompactRatio() {
|
|
3709
|
+
return this._autoCompactRatio;
|
|
3710
|
+
}
|
|
3711
|
+
/**
|
|
3712
|
+
* Set the auto-compaction ratio.
|
|
3713
|
+
* @remarks Time O(1), Space O(1)
|
|
3714
|
+
* @param value - Ratio in [0,1]. 0 disables auto-compact.
|
|
3715
|
+
*/
|
|
3716
|
+
set autoCompactRatio(value) {
|
|
3717
|
+
this._autoCompactRatio = value;
|
|
3718
|
+
}
|
|
3719
|
+
/**
|
|
3720
|
+
* Counter for shift/pop operations since last compaction check.
|
|
3721
|
+
* Only checks ratio every `_bucketSize` operations to minimize overhead.
|
|
3722
|
+
*/
|
|
3723
|
+
_compactCounter = 0;
|
|
3648
3724
|
_bucketFirst = 0;
|
|
3649
3725
|
/**
|
|
3650
3726
|
* Get the index of the first bucket in use.
|
|
@@ -3783,6 +3859,7 @@ var Deque = class extends LinearBase {
|
|
|
3783
3859
|
}
|
|
3784
3860
|
}
|
|
3785
3861
|
this._length -= 1;
|
|
3862
|
+
this._autoCompact();
|
|
3786
3863
|
return element;
|
|
3787
3864
|
}
|
|
3788
3865
|
/**
|
|
@@ -3805,6 +3882,7 @@ var Deque = class extends LinearBase {
|
|
|
3805
3882
|
}
|
|
3806
3883
|
}
|
|
3807
3884
|
this._length -= 1;
|
|
3885
|
+
this._autoCompact();
|
|
3808
3886
|
return element;
|
|
3809
3887
|
}
|
|
3810
3888
|
/**
|
|
@@ -4137,11 +4215,40 @@ var Deque = class extends LinearBase {
|
|
|
4137
4215
|
* @remarks Time O(N), Space O(1)
|
|
4138
4216
|
* @returns void
|
|
4139
4217
|
*/
|
|
4218
|
+
/**
|
|
4219
|
+
* (Protected) Trigger auto-compaction if space utilization drops below threshold.
|
|
4220
|
+
* Only checks every `_bucketSize` operations to minimize hot-path overhead.
|
|
4221
|
+
* Uses element-based ratio: `elements / (bucketCount * bucketSize)`.
|
|
4222
|
+
*/
|
|
4223
|
+
_autoCompact() {
|
|
4224
|
+
if (this._autoCompactRatio <= 0 || this._bucketCount <= 1) return;
|
|
4225
|
+
this._compactCounter++;
|
|
4226
|
+
if (this._compactCounter < this._bucketSize) return;
|
|
4227
|
+
this._compactCounter = 0;
|
|
4228
|
+
const utilization = this._length / (this._bucketCount * this._bucketSize);
|
|
4229
|
+
if (utilization < this._autoCompactRatio) {
|
|
4230
|
+
this.shrinkToFit();
|
|
4231
|
+
}
|
|
4232
|
+
}
|
|
4233
|
+
/**
|
|
4234
|
+
* Compact the deque by removing unused buckets.
|
|
4235
|
+
* @remarks Time O(N), Space O(1)
|
|
4236
|
+
* @returns True if compaction was performed (bucket count reduced).
|
|
4237
|
+
*/
|
|
4238
|
+
/**
|
|
4239
|
+
* Compact the deque by removing unused buckets.
|
|
4240
|
+
* @remarks Time O(N), Space O(1)
|
|
4241
|
+
* @returns True if compaction was performed (bucket count reduced).
|
|
4242
|
+
*/
|
|
4243
|
+
compact() {
|
|
4244
|
+
const before = this._bucketCount;
|
|
4245
|
+
this.shrinkToFit();
|
|
4246
|
+
return this._bucketCount < before;
|
|
4247
|
+
}
|
|
4140
4248
|
shrinkToFit() {
|
|
4141
4249
|
if (this._length === 0) return;
|
|
4142
4250
|
const newBuckets = [];
|
|
4143
|
-
if (this._bucketFirst
|
|
4144
|
-
else if (this._bucketFirst < this._bucketLast) {
|
|
4251
|
+
if (this._bucketFirst <= this._bucketLast) {
|
|
4145
4252
|
for (let i = this._bucketFirst; i <= this._bucketLast; ++i) {
|
|
4146
4253
|
newBuckets.push(this._buckets[i]);
|
|
4147
4254
|
}
|
|
@@ -4156,6 +4263,8 @@ var Deque = class extends LinearBase {
|
|
|
4156
4263
|
this._bucketFirst = 0;
|
|
4157
4264
|
this._bucketLast = newBuckets.length - 1;
|
|
4158
4265
|
this._buckets = newBuckets;
|
|
4266
|
+
this._bucketCount = newBuckets.length;
|
|
4267
|
+
this._compactCounter = 0;
|
|
4159
4268
|
}
|
|
4160
4269
|
/**
|
|
4161
4270
|
* Deep clone this deque, preserving options.
|
|
@@ -4654,7 +4763,7 @@ var Heap = class _Heap extends IterableElementBase {
|
|
|
4654
4763
|
*/
|
|
4655
4764
|
map(callback, options, thisArg) {
|
|
4656
4765
|
const { comparator, toElementFn, ...rest } = options ?? {};
|
|
4657
|
-
if (!comparator) throw new TypeError("Heap.map
|
|
4766
|
+
if (!comparator) throw new TypeError(ERR.comparatorRequired("Heap.map"));
|
|
4658
4767
|
const out = this._createLike([], { ...rest, comparator, toElementFn });
|
|
4659
4768
|
let i = 0;
|
|
4660
4769
|
for (const x of this) {
|
|
@@ -4681,7 +4790,7 @@ var Heap = class _Heap extends IterableElementBase {
|
|
|
4681
4790
|
}
|
|
4682
4791
|
_DEFAULT_COMPARATOR = /* @__PURE__ */ __name((a, b) => {
|
|
4683
4792
|
if (typeof a === "object" || typeof b === "object") {
|
|
4684
|
-
throw TypeError(
|
|
4793
|
+
throw new TypeError(ERR.comparatorRequired("Heap"));
|
|
4685
4794
|
}
|
|
4686
4795
|
if (a > b) return 1;
|
|
4687
4796
|
if (a < b) return -1;
|
|
@@ -4793,7 +4902,7 @@ var FibonacciHeap = class {
|
|
|
4793
4902
|
constructor(comparator) {
|
|
4794
4903
|
this.clear();
|
|
4795
4904
|
this._comparator = comparator || this._defaultComparator;
|
|
4796
|
-
if (typeof this.comparator !== "function") throw new
|
|
4905
|
+
if (typeof this.comparator !== "function") throw new TypeError(ERR.notAFunction("comparator", "FibonacciHeap"));
|
|
4797
4906
|
}
|
|
4798
4907
|
_root;
|
|
4799
4908
|
/**
|
|
@@ -5009,9 +5118,7 @@ var MaxHeap = class extends Heap {
|
|
|
5009
5118
|
super(elements, {
|
|
5010
5119
|
comparator: /* @__PURE__ */ __name((a, b) => {
|
|
5011
5120
|
if (typeof a === "object" || typeof b === "object") {
|
|
5012
|
-
throw TypeError(
|
|
5013
|
-
`When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
|
|
5014
|
-
);
|
|
5121
|
+
throw new TypeError(ERR.comparatorRequired("MaxHeap"));
|
|
5015
5122
|
}
|
|
5016
5123
|
if (a < b) return 1;
|
|
5017
5124
|
if (a > b) return -1;
|
|
@@ -5180,7 +5287,7 @@ var AbstractGraph = class extends IterableEntryBase {
|
|
|
5180
5287
|
const newEdge = this.createEdge(srcOrEdge, dest, weight, value);
|
|
5181
5288
|
return this._addEdge(newEdge);
|
|
5182
5289
|
} else {
|
|
5183
|
-
throw new
|
|
5290
|
+
throw new TypeError(ERR.invalidArgument("dest must be a Vertex or vertex key when srcOrEdge is an Edge.", "Graph"));
|
|
5184
5291
|
}
|
|
5185
5292
|
}
|
|
5186
5293
|
}
|
|
@@ -5860,6 +5967,92 @@ var AbstractGraph = class extends IterableEntryBase {
|
|
|
5860
5967
|
_getVertexKey(vertexOrKey) {
|
|
5861
5968
|
return vertexOrKey instanceof AbstractVertex ? vertexOrKey.key : vertexOrKey;
|
|
5862
5969
|
}
|
|
5970
|
+
/**
|
|
5971
|
+
* The edge connector string used in visual output.
|
|
5972
|
+
* Override in subclasses (e.g., '--' for undirected, '->' for directed).
|
|
5973
|
+
*/
|
|
5974
|
+
get _edgeConnector() {
|
|
5975
|
+
return "--";
|
|
5976
|
+
}
|
|
5977
|
+
/**
|
|
5978
|
+
* Generate a text-based visual representation of the graph.
|
|
5979
|
+
*
|
|
5980
|
+
* **Adjacency list format:**
|
|
5981
|
+
* ```
|
|
5982
|
+
* Graph (5 vertices, 6 edges):
|
|
5983
|
+
* A -> B (1), C (2)
|
|
5984
|
+
* B -> D (3)
|
|
5985
|
+
* C -> (no outgoing edges)
|
|
5986
|
+
* D -> A (1)
|
|
5987
|
+
* E (isolated)
|
|
5988
|
+
* ```
|
|
5989
|
+
*
|
|
5990
|
+
* @param options - Optional display settings.
|
|
5991
|
+
* @param options.showWeight - Whether to show edge weights (default: true).
|
|
5992
|
+
* @returns The visual string.
|
|
5993
|
+
*/
|
|
5994
|
+
toVisual(options) {
|
|
5995
|
+
const showWeight = options?.showWeight ?? true;
|
|
5996
|
+
const vertices = [...this._vertexMap.values()];
|
|
5997
|
+
const vertexCount = vertices.length;
|
|
5998
|
+
const edgeCount = this.edgeSet().length;
|
|
5999
|
+
const lines = [`Graph (${vertexCount} vertices, ${edgeCount} edges):`];
|
|
6000
|
+
for (const vertex of vertices) {
|
|
6001
|
+
const neighbors = this.getNeighbors(vertex);
|
|
6002
|
+
if (neighbors.length === 0) {
|
|
6003
|
+
lines.push(` ${vertex.key} (isolated)`);
|
|
6004
|
+
} else {
|
|
6005
|
+
const edgeStrs = neighbors.map((neighbor) => {
|
|
6006
|
+
const edge = this.getEdge(vertex, neighbor);
|
|
6007
|
+
if (edge && showWeight && edge.weight !== void 0 && edge.weight !== 1) {
|
|
6008
|
+
return `${neighbor.key} (${edge.weight})`;
|
|
6009
|
+
}
|
|
6010
|
+
return `${neighbor.key}`;
|
|
6011
|
+
});
|
|
6012
|
+
lines.push(` ${vertex.key} ${this._edgeConnector} ${edgeStrs.join(", ")}`);
|
|
6013
|
+
}
|
|
6014
|
+
}
|
|
6015
|
+
return lines.join("\n");
|
|
6016
|
+
}
|
|
6017
|
+
/**
|
|
6018
|
+
* Generate DOT language representation for Graphviz.
|
|
6019
|
+
*
|
|
6020
|
+
* @param options - Optional display settings.
|
|
6021
|
+
* @param options.name - Graph name (default: 'G').
|
|
6022
|
+
* @param options.showWeight - Whether to label edges with weight (default: true).
|
|
6023
|
+
* @returns DOT format string.
|
|
6024
|
+
*/
|
|
6025
|
+
toDot(options) {
|
|
6026
|
+
const name = options?.name ?? "G";
|
|
6027
|
+
const showWeight = options?.showWeight ?? true;
|
|
6028
|
+
const isDirected = this._edgeConnector === "->";
|
|
6029
|
+
const graphType = isDirected ? "digraph" : "graph";
|
|
6030
|
+
const edgeOp = isDirected ? "->" : "--";
|
|
6031
|
+
const lines = [`${graphType} ${name} {`];
|
|
6032
|
+
for (const vertex of this._vertexMap.values()) {
|
|
6033
|
+
lines.push(` "${vertex.key}";`);
|
|
6034
|
+
}
|
|
6035
|
+
const visited = /* @__PURE__ */ new Set();
|
|
6036
|
+
for (const vertex of this._vertexMap.values()) {
|
|
6037
|
+
for (const neighbor of this.getNeighbors(vertex)) {
|
|
6038
|
+
const edgeId = isDirected ? `${vertex.key}->${neighbor.key}` : [vertex.key, neighbor.key].sort().join("--");
|
|
6039
|
+
if (visited.has(edgeId)) continue;
|
|
6040
|
+
visited.add(edgeId);
|
|
6041
|
+
const edge = this.getEdge(vertex, neighbor);
|
|
6042
|
+
const label = edge && showWeight && edge.weight !== void 0 && edge.weight !== 1 ? ` [label="${edge.weight}"]` : "";
|
|
6043
|
+
lines.push(` "${vertex.key}" ${edgeOp} "${neighbor.key}"${label};`);
|
|
6044
|
+
}
|
|
6045
|
+
}
|
|
6046
|
+
lines.push("}");
|
|
6047
|
+
return lines.join("\n");
|
|
6048
|
+
}
|
|
6049
|
+
/**
|
|
6050
|
+
* Print the graph to console.
|
|
6051
|
+
* @param options - Display settings passed to `toVisual`.
|
|
6052
|
+
*/
|
|
6053
|
+
print(options) {
|
|
6054
|
+
console.log(this.toVisual(options));
|
|
6055
|
+
}
|
|
5863
6056
|
};
|
|
5864
6057
|
|
|
5865
6058
|
// src/data-structures/graph/directed-graph.ts
|
|
@@ -5895,6 +6088,9 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
|
|
|
5895
6088
|
constructor(options) {
|
|
5896
6089
|
super(options);
|
|
5897
6090
|
}
|
|
6091
|
+
get _edgeConnector() {
|
|
6092
|
+
return "->";
|
|
6093
|
+
}
|
|
5898
6094
|
_outEdgeMap = /* @__PURE__ */ new Map();
|
|
5899
6095
|
get outEdgeMap() {
|
|
5900
6096
|
return this._outEdgeMap;
|
|
@@ -6676,6 +6872,84 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
|
|
|
6676
6872
|
cutVertices
|
|
6677
6873
|
};
|
|
6678
6874
|
}
|
|
6875
|
+
/**
|
|
6876
|
+
* Find biconnected components using edge-stack Tarjan variant.
|
|
6877
|
+
* A biconnected component is a maximal biconnected subgraph.
|
|
6878
|
+
* @returns Array of edge arrays, each representing a biconnected component.
|
|
6879
|
+
* @remarks Time O(V + E), Space O(V + E)
|
|
6880
|
+
*/
|
|
6881
|
+
getBiconnectedComponents() {
|
|
6882
|
+
const dfn = /* @__PURE__ */ new Map();
|
|
6883
|
+
const low = /* @__PURE__ */ new Map();
|
|
6884
|
+
const edgeStack = [];
|
|
6885
|
+
const components = [];
|
|
6886
|
+
let time = 0;
|
|
6887
|
+
const dfs = /* @__PURE__ */ __name((vertex, parent) => {
|
|
6888
|
+
dfn.set(vertex, time);
|
|
6889
|
+
low.set(vertex, time);
|
|
6890
|
+
time++;
|
|
6891
|
+
const neighbors = this.getNeighbors(vertex);
|
|
6892
|
+
let childCount = 0;
|
|
6893
|
+
for (const neighbor of neighbors) {
|
|
6894
|
+
const edge = this.getEdge(vertex, neighbor);
|
|
6895
|
+
if (!edge) continue;
|
|
6896
|
+
if (!dfn.has(neighbor)) {
|
|
6897
|
+
childCount++;
|
|
6898
|
+
edgeStack.push(edge);
|
|
6899
|
+
dfs(neighbor, vertex);
|
|
6900
|
+
low.set(vertex, Math.min(low.get(vertex), low.get(neighbor)));
|
|
6901
|
+
if (parent === void 0 && childCount > 1 || parent !== void 0 && low.get(neighbor) >= dfn.get(vertex)) {
|
|
6902
|
+
const component = [];
|
|
6903
|
+
let e;
|
|
6904
|
+
do {
|
|
6905
|
+
e = edgeStack.pop();
|
|
6906
|
+
if (e) component.push(e);
|
|
6907
|
+
} while (e && e !== edge);
|
|
6908
|
+
if (component.length > 0) components.push(component);
|
|
6909
|
+
}
|
|
6910
|
+
} else if (neighbor !== parent && dfn.get(neighbor) < dfn.get(vertex)) {
|
|
6911
|
+
edgeStack.push(edge);
|
|
6912
|
+
low.set(vertex, Math.min(low.get(vertex), dfn.get(neighbor)));
|
|
6913
|
+
}
|
|
6914
|
+
}
|
|
6915
|
+
}, "dfs");
|
|
6916
|
+
for (const vertex of this.vertexMap.values()) {
|
|
6917
|
+
if (!dfn.has(vertex)) {
|
|
6918
|
+
dfs(vertex, void 0);
|
|
6919
|
+
if (edgeStack.length > 0) {
|
|
6920
|
+
components.push([...edgeStack]);
|
|
6921
|
+
edgeStack.length = 0;
|
|
6922
|
+
}
|
|
6923
|
+
}
|
|
6924
|
+
}
|
|
6925
|
+
return components;
|
|
6926
|
+
}
|
|
6927
|
+
/**
|
|
6928
|
+
* Detect whether the graph contains a cycle.
|
|
6929
|
+
* Uses DFS with parent tracking.
|
|
6930
|
+
* @returns `true` if a cycle exists, `false` otherwise.
|
|
6931
|
+
* @remarks Time O(V + E), Space O(V)
|
|
6932
|
+
*/
|
|
6933
|
+
hasCycle() {
|
|
6934
|
+
const visited = /* @__PURE__ */ new Set();
|
|
6935
|
+
const dfs = /* @__PURE__ */ __name((vertex, parent) => {
|
|
6936
|
+
visited.add(vertex);
|
|
6937
|
+
for (const neighbor of this.getNeighbors(vertex)) {
|
|
6938
|
+
if (!visited.has(neighbor)) {
|
|
6939
|
+
if (dfs(neighbor, vertex)) return true;
|
|
6940
|
+
} else if (neighbor !== parent) {
|
|
6941
|
+
return true;
|
|
6942
|
+
}
|
|
6943
|
+
}
|
|
6944
|
+
return false;
|
|
6945
|
+
}, "dfs");
|
|
6946
|
+
for (const vertex of this.vertexMap.values()) {
|
|
6947
|
+
if (!visited.has(vertex)) {
|
|
6948
|
+
if (dfs(vertex, void 0)) return true;
|
|
6949
|
+
}
|
|
6950
|
+
}
|
|
6951
|
+
return false;
|
|
6952
|
+
}
|
|
6679
6953
|
/**
|
|
6680
6954
|
* Get bridges discovered by `tarjan()`.
|
|
6681
6955
|
* @returns Array of edges that are bridges.
|
|
@@ -6829,30 +7103,6 @@ var MapGraph = class _MapGraph extends DirectedGraph {
|
|
|
6829
7103
|
}
|
|
6830
7104
|
};
|
|
6831
7105
|
|
|
6832
|
-
// src/common/index.ts
|
|
6833
|
-
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
6834
|
-
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
6835
|
-
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
6836
|
-
return DFSOperation2;
|
|
6837
|
-
})(DFSOperation || {});
|
|
6838
|
-
var Range = class {
|
|
6839
|
-
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
6840
|
-
this.low = low;
|
|
6841
|
-
this.high = high;
|
|
6842
|
-
this.includeLow = includeLow;
|
|
6843
|
-
this.includeHigh = includeHigh;
|
|
6844
|
-
}
|
|
6845
|
-
static {
|
|
6846
|
-
__name(this, "Range");
|
|
6847
|
-
}
|
|
6848
|
-
// Determine whether a key is within the range
|
|
6849
|
-
isInRange(key, comparator) {
|
|
6850
|
-
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
6851
|
-
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
6852
|
-
return lowCheck && highCheck;
|
|
6853
|
-
}
|
|
6854
|
-
};
|
|
6855
|
-
|
|
6856
7106
|
// src/data-structures/binary-tree/binary-tree.ts
|
|
6857
7107
|
var BinaryTreeNode = class {
|
|
6858
7108
|
static {
|
|
@@ -6991,7 +7241,7 @@ var BinaryTreeNode = class {
|
|
|
6991
7241
|
return "MAL_NODE";
|
|
6992
7242
|
}
|
|
6993
7243
|
};
|
|
6994
|
-
var BinaryTree = class extends IterableEntryBase {
|
|
7244
|
+
var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
6995
7245
|
static {
|
|
6996
7246
|
__name(this, "BinaryTree");
|
|
6997
7247
|
}
|
|
@@ -7011,7 +7261,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
7011
7261
|
if (isMapMode !== void 0) this._isMapMode = isMapMode;
|
|
7012
7262
|
if (isDuplicate !== void 0) this._isDuplicate = isDuplicate;
|
|
7013
7263
|
if (typeof toEntryFn === "function") this._toEntryFn = toEntryFn;
|
|
7014
|
-
else if (toEntryFn) throw TypeError("toEntryFn
|
|
7264
|
+
else if (toEntryFn) throw new TypeError(ERR.notAFunction("toEntryFn", "BinaryTree"));
|
|
7015
7265
|
}
|
|
7016
7266
|
if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
|
|
7017
7267
|
}
|
|
@@ -7249,7 +7499,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
7249
7499
|
if (!this._root) {
|
|
7250
7500
|
this._setRoot(newNode);
|
|
7251
7501
|
if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
|
|
7252
|
-
this._size = 1;
|
|
7502
|
+
if (newNode !== null) this._size = 1;
|
|
7253
7503
|
return true;
|
|
7254
7504
|
}
|
|
7255
7505
|
const queue = new Queue([this._root]);
|
|
@@ -7281,7 +7531,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
7281
7531
|
potentialParent.right = newNode;
|
|
7282
7532
|
}
|
|
7283
7533
|
if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
|
|
7284
|
-
this._size++;
|
|
7534
|
+
if (newNode !== null) this._size++;
|
|
7285
7535
|
return true;
|
|
7286
7536
|
}
|
|
7287
7537
|
return false;
|
|
@@ -7849,7 +8099,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
7849
8099
|
}
|
|
7850
8100
|
/**
|
|
7851
8101
|
* Finds all leaf nodes in the tree.
|
|
7852
|
-
* @remarks Time O(N), visits every node. Space O(H) for recursive
|
|
8102
|
+
* @remarks Time O(N), visits every node. Space O(H) for recursive or iterative stack.
|
|
7853
8103
|
*
|
|
7854
8104
|
* @template C - The type of the callback function.
|
|
7855
8105
|
* @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each leaf node.
|
|
@@ -7872,15 +8122,15 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
7872
8122
|
}, "dfs");
|
|
7873
8123
|
dfs(startNode);
|
|
7874
8124
|
} else {
|
|
7875
|
-
const
|
|
7876
|
-
while (
|
|
7877
|
-
const cur =
|
|
8125
|
+
const stack = [startNode];
|
|
8126
|
+
while (stack.length > 0) {
|
|
8127
|
+
const cur = stack.pop();
|
|
7878
8128
|
if (this.isRealNode(cur)) {
|
|
7879
8129
|
if (this.isLeaf(cur)) {
|
|
7880
8130
|
leaves.push(callback(cur));
|
|
7881
8131
|
}
|
|
7882
|
-
if (this.isRealNode(cur.
|
|
7883
|
-
if (this.isRealNode(cur.
|
|
8132
|
+
if (this.isRealNode(cur.right)) stack.push(cur.right);
|
|
8133
|
+
if (this.isRealNode(cur.left)) stack.push(cur.left);
|
|
7884
8134
|
}
|
|
7885
8135
|
}
|
|
7886
8136
|
}
|
|
@@ -8342,42 +8592,98 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
8342
8592
|
_displayAux(node, options) {
|
|
8343
8593
|
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
8344
8594
|
const emptyDisplayLayout = [["\u2500"], 1, 0, 0];
|
|
8345
|
-
|
|
8346
|
-
|
|
8347
|
-
|
|
8348
|
-
|
|
8349
|
-
|
|
8350
|
-
|
|
8351
|
-
|
|
8352
|
-
|
|
8353
|
-
|
|
8354
|
-
|
|
8355
|
-
|
|
8356
|
-
|
|
8357
|
-
|
|
8358
|
-
|
|
8359
|
-
|
|
8360
|
-
|
|
8361
|
-
|
|
8362
|
-
|
|
8363
|
-
|
|
8364
|
-
const
|
|
8365
|
-
|
|
8366
|
-
|
|
8367
|
-
|
|
8368
|
-
|
|
8369
|
-
|
|
8370
|
-
|
|
8371
|
-
|
|
8372
|
-
|
|
8595
|
+
const newFrame = /* @__PURE__ */ __name((n) => ({
|
|
8596
|
+
node: n,
|
|
8597
|
+
stage: 0,
|
|
8598
|
+
leftLayout: emptyDisplayLayout,
|
|
8599
|
+
rightLayout: emptyDisplayLayout
|
|
8600
|
+
}), "newFrame");
|
|
8601
|
+
const stack = [newFrame(node)];
|
|
8602
|
+
let result = emptyDisplayLayout;
|
|
8603
|
+
const setChildResult = /* @__PURE__ */ __name((layout) => {
|
|
8604
|
+
if (stack.length === 0) {
|
|
8605
|
+
result = layout;
|
|
8606
|
+
return;
|
|
8607
|
+
}
|
|
8608
|
+
const parent = stack[stack.length - 1];
|
|
8609
|
+
if (parent.stage === 1) parent.leftLayout = layout;
|
|
8610
|
+
else parent.rightLayout = layout;
|
|
8611
|
+
}, "setChildResult");
|
|
8612
|
+
while (stack.length > 0) {
|
|
8613
|
+
const frame = stack[stack.length - 1];
|
|
8614
|
+
const cur = frame.node;
|
|
8615
|
+
if (frame.stage === 0) {
|
|
8616
|
+
if (this._isDisplayLeaf(cur, options)) {
|
|
8617
|
+
stack.pop();
|
|
8618
|
+
const layout = this._resolveDisplayLeaf(cur, options, emptyDisplayLayout);
|
|
8619
|
+
setChildResult(layout);
|
|
8620
|
+
continue;
|
|
8621
|
+
}
|
|
8622
|
+
frame.stage = 1;
|
|
8623
|
+
stack.push(newFrame(cur.left));
|
|
8624
|
+
} else if (frame.stage === 1) {
|
|
8625
|
+
frame.stage = 2;
|
|
8626
|
+
stack.push(newFrame(cur.right));
|
|
8627
|
+
} else {
|
|
8628
|
+
stack.pop();
|
|
8629
|
+
const line = this.isNIL(cur) ? "S" : String(cur.key);
|
|
8630
|
+
const layout = _BinaryTree._buildNodeDisplay(line, line.length, frame.leftLayout, frame.rightLayout);
|
|
8631
|
+
setChildResult(layout);
|
|
8373
8632
|
}
|
|
8374
|
-
return [
|
|
8375
|
-
mergedLines,
|
|
8376
|
-
leftWidth + width + rightWidth,
|
|
8377
|
-
Math.max(leftHeight, rightHeight) + 2,
|
|
8378
|
-
leftWidth + Math.floor(width / 2)
|
|
8379
|
-
];
|
|
8380
8633
|
}
|
|
8634
|
+
return result;
|
|
8635
|
+
}
|
|
8636
|
+
static _buildNodeDisplay(line, width, left, right) {
|
|
8637
|
+
const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
|
|
8638
|
+
const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
|
|
8639
|
+
const firstLine = " ".repeat(Math.max(0, leftMiddle + 1)) + "_".repeat(Math.max(0, leftWidth - leftMiddle - 1)) + line + "_".repeat(Math.max(0, rightMiddle)) + " ".repeat(Math.max(0, rightWidth - rightMiddle));
|
|
8640
|
+
const secondLine = (leftHeight > 0 ? " ".repeat(leftMiddle) + "/" + " ".repeat(leftWidth - leftMiddle - 1) : " ".repeat(leftWidth)) + " ".repeat(width) + (rightHeight > 0 ? " ".repeat(rightMiddle) + "\\" + " ".repeat(rightWidth - rightMiddle - 1) : " ".repeat(rightWidth));
|
|
8641
|
+
const mergedLines = [firstLine, secondLine];
|
|
8642
|
+
for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
|
|
8643
|
+
const leftLine = i < leftHeight ? leftLines[i] : " ".repeat(leftWidth);
|
|
8644
|
+
const rightLine = i < rightHeight ? rightLines[i] : " ".repeat(rightWidth);
|
|
8645
|
+
mergedLines.push(leftLine + " ".repeat(width) + rightLine);
|
|
8646
|
+
}
|
|
8647
|
+
return [
|
|
8648
|
+
mergedLines,
|
|
8649
|
+
leftWidth + width + rightWidth,
|
|
8650
|
+
Math.max(leftHeight, rightHeight) + 2,
|
|
8651
|
+
leftWidth + Math.floor(width / 2)
|
|
8652
|
+
];
|
|
8653
|
+
}
|
|
8654
|
+
/**
|
|
8655
|
+
* Check if a node is a display leaf (empty, null, undefined, NIL, or real leaf).
|
|
8656
|
+
*/
|
|
8657
|
+
_isDisplayLeaf(node, options) {
|
|
8658
|
+
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
8659
|
+
if (node === null && !isShowNull) return true;
|
|
8660
|
+
if (node === void 0 && !isShowUndefined) return true;
|
|
8661
|
+
if (this.isNIL(node) && !isShowRedBlackNIL) return true;
|
|
8662
|
+
if (node === null || node === void 0) return true;
|
|
8663
|
+
const hasDisplayableLeft = this._hasDisplayableChild(node.left, options);
|
|
8664
|
+
const hasDisplayableRight = this._hasDisplayableChild(node.right, options);
|
|
8665
|
+
return !hasDisplayableLeft && !hasDisplayableRight;
|
|
8666
|
+
}
|
|
8667
|
+
_hasDisplayableChild(child, options) {
|
|
8668
|
+
if (child === null) return !!options.isShowNull;
|
|
8669
|
+
if (child === void 0) return !!options.isShowUndefined;
|
|
8670
|
+
if (this.isNIL(child)) return !!options.isShowRedBlackNIL;
|
|
8671
|
+
return true;
|
|
8672
|
+
}
|
|
8673
|
+
/**
|
|
8674
|
+
* Resolve a display leaf node to its layout.
|
|
8675
|
+
*/
|
|
8676
|
+
_resolveDisplayLeaf(node, options, emptyDisplayLayout) {
|
|
8677
|
+
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
8678
|
+
if (node === null && !isShowNull) return emptyDisplayLayout;
|
|
8679
|
+
if (node === void 0 && !isShowUndefined) return emptyDisplayLayout;
|
|
8680
|
+
if (this.isNIL(node) && !isShowRedBlackNIL) return emptyDisplayLayout;
|
|
8681
|
+
if (node !== null && node !== void 0) {
|
|
8682
|
+
const line2 = this.isNIL(node) ? "S" : String(node.key);
|
|
8683
|
+
return _BinaryTree._buildNodeDisplay(line2, line2.length, emptyDisplayLayout, emptyDisplayLayout);
|
|
8684
|
+
}
|
|
8685
|
+
const line = node === void 0 ? "U" : "N";
|
|
8686
|
+
return _BinaryTree._buildNodeDisplay(line, line.length, [[""], 1, 0, 0], [[""], 1, 0, 0]);
|
|
8381
8687
|
}
|
|
8382
8688
|
/**
|
|
8383
8689
|
* (Protected) Swaps the key/value properties of two nodes.
|
|
@@ -9383,9 +9689,15 @@ var BST = class extends BinaryTree {
|
|
|
9383
9689
|
if (a < b) return -1;
|
|
9384
9690
|
return 0;
|
|
9385
9691
|
}
|
|
9692
|
+
if (a instanceof Date && b instanceof Date) {
|
|
9693
|
+
const ta = a.getTime();
|
|
9694
|
+
const tb = b.getTime();
|
|
9695
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("BST"));
|
|
9696
|
+
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
9697
|
+
}
|
|
9386
9698
|
if (typeof a === "object" || typeof b === "object") {
|
|
9387
|
-
throw TypeError(
|
|
9388
|
-
|
|
9699
|
+
throw new TypeError(
|
|
9700
|
+
ERR.comparatorRequired("BST")
|
|
9389
9701
|
);
|
|
9390
9702
|
}
|
|
9391
9703
|
return 0;
|
|
@@ -9897,7 +10209,7 @@ var BinaryIndexedTree = class {
|
|
|
9897
10209
|
*/
|
|
9898
10210
|
read(count) {
|
|
9899
10211
|
if (!Number.isInteger(count)) {
|
|
9900
|
-
throw new Error("
|
|
10212
|
+
throw new Error(ERR.invalidArgument("count must be an integer", "BinaryIndexedTree"));
|
|
9901
10213
|
}
|
|
9902
10214
|
return this._read(Math.max(Math.min(count, this.max), 0));
|
|
9903
10215
|
}
|
|
@@ -9909,7 +10221,7 @@ var BinaryIndexedTree = class {
|
|
|
9909
10221
|
*/
|
|
9910
10222
|
lowerBound(sum) {
|
|
9911
10223
|
if (this.negativeCount > 0) {
|
|
9912
|
-
throw new Error("Sequence is not non-descending");
|
|
10224
|
+
throw new Error(ERR.invalidOperation("Sequence is not non-descending.", "BinaryIndexedTree"));
|
|
9913
10225
|
}
|
|
9914
10226
|
return this._binarySearch(sum, (x, y) => x < y);
|
|
9915
10227
|
}
|
|
@@ -9922,7 +10234,7 @@ var BinaryIndexedTree = class {
|
|
|
9922
10234
|
*/
|
|
9923
10235
|
upperBound(sum) {
|
|
9924
10236
|
if (this.negativeCount > 0) {
|
|
9925
|
-
throw new Error("
|
|
10237
|
+
throw new Error(ERR.invalidOperation("Sequence must not be descending.", "BinaryIndexedTree"));
|
|
9926
10238
|
}
|
|
9927
10239
|
return this._binarySearch(sum, (x, y) => x <= y);
|
|
9928
10240
|
}
|
|
@@ -9973,10 +10285,10 @@ var BinaryIndexedTree = class {
|
|
|
9973
10285
|
*/
|
|
9974
10286
|
_checkIndex(index) {
|
|
9975
10287
|
if (!Number.isInteger(index)) {
|
|
9976
|
-
throw new
|
|
10288
|
+
throw new TypeError(ERR.invalidIndex("BinaryIndexedTree"));
|
|
9977
10289
|
}
|
|
9978
10290
|
if (index < 0 || index >= this.max) {
|
|
9979
|
-
throw new
|
|
10291
|
+
throw new RangeError(ERR.indexOutOfRange(index, 0, this.max - 1, "BinaryIndexedTree"));
|
|
9980
10292
|
}
|
|
9981
10293
|
}
|
|
9982
10294
|
/**
|
|
@@ -11568,6 +11880,24 @@ var RedBlackTree = class extends BST {
|
|
|
11568
11880
|
* @param [thisArg] - See parameter type for details.
|
|
11569
11881
|
* @returns A new RedBlackTree with mapped entries.
|
|
11570
11882
|
*/
|
|
11883
|
+
/**
|
|
11884
|
+
* Red-Black trees are self-balancing — `perfectlyBalance` rebuilds via
|
|
11885
|
+
* sorted bulk insert, which naturally produces a balanced RBT.
|
|
11886
|
+
* @remarks Time O(N), Space O(N)
|
|
11887
|
+
*/
|
|
11888
|
+
perfectlyBalance(iterationType) {
|
|
11889
|
+
const entries = [];
|
|
11890
|
+
for (const [key, value] of this) entries.push([key, value]);
|
|
11891
|
+
if (entries.length <= 1) return true;
|
|
11892
|
+
this.clear();
|
|
11893
|
+
this.setMany(
|
|
11894
|
+
entries.map(([k]) => k),
|
|
11895
|
+
entries.map(([, v]) => v),
|
|
11896
|
+
true
|
|
11897
|
+
// isBalanceAdd
|
|
11898
|
+
);
|
|
11899
|
+
return true;
|
|
11900
|
+
}
|
|
11571
11901
|
map(callback, options, thisArg) {
|
|
11572
11902
|
const out = this._createLike([], options);
|
|
11573
11903
|
let index = 0;
|
|
@@ -11889,7 +12219,7 @@ var TreeSet = class _TreeSet {
|
|
|
11889
12219
|
static createDefaultComparator() {
|
|
11890
12220
|
return (a, b) => {
|
|
11891
12221
|
if (typeof a === "number" && typeof b === "number") {
|
|
11892
|
-
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError("TreeSet
|
|
12222
|
+
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("TreeSet"));
|
|
11893
12223
|
const aa = Object.is(a, -0) ? 0 : a;
|
|
11894
12224
|
const bb = Object.is(b, -0) ? 0 : b;
|
|
11895
12225
|
return aa > bb ? 1 : aa < bb ? -1 : 0;
|
|
@@ -11900,10 +12230,10 @@ var TreeSet = class _TreeSet {
|
|
|
11900
12230
|
if (a instanceof Date && b instanceof Date) {
|
|
11901
12231
|
const ta = a.getTime();
|
|
11902
12232
|
const tb = b.getTime();
|
|
11903
|
-
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError("TreeSet
|
|
12233
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("TreeSet"));
|
|
11904
12234
|
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
11905
12235
|
}
|
|
11906
|
-
throw new TypeError("TreeSet
|
|
12236
|
+
throw new TypeError(ERR.comparatorRequired("TreeSet"));
|
|
11907
12237
|
};
|
|
11908
12238
|
}
|
|
11909
12239
|
/**
|
|
@@ -11921,15 +12251,15 @@ var TreeSet = class _TreeSet {
|
|
|
11921
12251
|
_validateKey(key) {
|
|
11922
12252
|
if (!this.#isDefaultComparator) return;
|
|
11923
12253
|
if (typeof key === "number") {
|
|
11924
|
-
if (Number.isNaN(key)) throw new TypeError("TreeSet
|
|
12254
|
+
if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeSet"));
|
|
11925
12255
|
return;
|
|
11926
12256
|
}
|
|
11927
12257
|
if (typeof key === "string") return;
|
|
11928
12258
|
if (key instanceof Date) {
|
|
11929
|
-
if (Number.isNaN(key.getTime())) throw new TypeError("TreeSet
|
|
12259
|
+
if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeSet"));
|
|
11930
12260
|
return;
|
|
11931
12261
|
}
|
|
11932
|
-
throw new TypeError("TreeSet
|
|
12262
|
+
throw new TypeError(ERR.comparatorRequired("TreeSet"));
|
|
11933
12263
|
}
|
|
11934
12264
|
/**
|
|
11935
12265
|
* Add a key to the set (no-op if already present).
|
|
@@ -12248,15 +12578,15 @@ var TreeMultiMap = class _TreeMultiMap {
|
|
|
12248
12578
|
_validateKey(key) {
|
|
12249
12579
|
if (!this.#isDefaultComparator) return;
|
|
12250
12580
|
if (typeof key === "number") {
|
|
12251
|
-
if (Number.isNaN(key)) throw new TypeError("TreeMultiMap
|
|
12581
|
+
if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMultiMap"));
|
|
12252
12582
|
return;
|
|
12253
12583
|
}
|
|
12254
12584
|
if (typeof key === "string") return;
|
|
12255
12585
|
if (key instanceof Date) {
|
|
12256
|
-
if (Number.isNaN(key.getTime())) throw new TypeError("TreeMultiMap
|
|
12586
|
+
if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMultiMap"));
|
|
12257
12587
|
return;
|
|
12258
12588
|
}
|
|
12259
|
-
throw new TypeError("TreeMultiMap
|
|
12589
|
+
throw new TypeError(ERR.comparatorRequired("TreeMultiMap"));
|
|
12260
12590
|
}
|
|
12261
12591
|
/**
|
|
12262
12592
|
* Number of distinct keys.
|
|
@@ -12678,7 +13008,7 @@ var TreeMap = class _TreeMap {
|
|
|
12678
13008
|
[k, v] = toEntryFn(item);
|
|
12679
13009
|
} else {
|
|
12680
13010
|
if (!Array.isArray(item) || item.length < 2) {
|
|
12681
|
-
throw new TypeError("TreeMap
|
|
13011
|
+
throw new TypeError(ERR.invalidEntry("TreeMap"));
|
|
12682
13012
|
}
|
|
12683
13013
|
k = item[0];
|
|
12684
13014
|
v = item[1];
|
|
@@ -12699,7 +13029,7 @@ var TreeMap = class _TreeMap {
|
|
|
12699
13029
|
static createDefaultComparator() {
|
|
12700
13030
|
return (a, b) => {
|
|
12701
13031
|
if (typeof a === "number" && typeof b === "number") {
|
|
12702
|
-
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError("TreeMap
|
|
13032
|
+
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("TreeMap"));
|
|
12703
13033
|
const aa = Object.is(a, -0) ? 0 : a;
|
|
12704
13034
|
const bb = Object.is(b, -0) ? 0 : b;
|
|
12705
13035
|
return aa > bb ? 1 : aa < bb ? -1 : 0;
|
|
@@ -12710,24 +13040,24 @@ var TreeMap = class _TreeMap {
|
|
|
12710
13040
|
if (a instanceof Date && b instanceof Date) {
|
|
12711
13041
|
const ta = a.getTime();
|
|
12712
13042
|
const tb = b.getTime();
|
|
12713
|
-
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError("TreeMap
|
|
13043
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("TreeMap"));
|
|
12714
13044
|
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
12715
13045
|
}
|
|
12716
|
-
throw new TypeError("TreeMap
|
|
13046
|
+
throw new TypeError(ERR.comparatorRequired("TreeMap"));
|
|
12717
13047
|
};
|
|
12718
13048
|
}
|
|
12719
13049
|
_validateKey(key) {
|
|
12720
13050
|
if (!this.#isDefaultComparator) return;
|
|
12721
13051
|
if (typeof key === "number") {
|
|
12722
|
-
if (Number.isNaN(key)) throw new TypeError("TreeMap
|
|
13052
|
+
if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMap"));
|
|
12723
13053
|
return;
|
|
12724
13054
|
}
|
|
12725
13055
|
if (typeof key === "string") return;
|
|
12726
13056
|
if (key instanceof Date) {
|
|
12727
|
-
if (Number.isNaN(key.getTime())) throw new TypeError("TreeMap
|
|
13057
|
+
if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMap"));
|
|
12728
13058
|
return;
|
|
12729
13059
|
}
|
|
12730
|
-
throw new TypeError("TreeMap
|
|
13060
|
+
throw new TypeError(ERR.comparatorRequired("TreeMap"));
|
|
12731
13061
|
}
|
|
12732
13062
|
/**
|
|
12733
13063
|
* Number of entries in the map.
|
|
@@ -13051,22 +13381,22 @@ var TreeMultiSet = class _TreeMultiSet {
|
|
|
13051
13381
|
_validateKey(key) {
|
|
13052
13382
|
if (!this.#isDefaultComparator) return;
|
|
13053
13383
|
if (typeof key === "number") {
|
|
13054
|
-
if (Number.isNaN(key)) throw new TypeError("TreeMultiSet
|
|
13384
|
+
if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMultiSet"));
|
|
13055
13385
|
return;
|
|
13056
13386
|
}
|
|
13057
13387
|
if (typeof key === "string") return;
|
|
13058
13388
|
if (key instanceof Date) {
|
|
13059
|
-
if (Number.isNaN(key.getTime())) throw new TypeError("TreeMultiSet
|
|
13389
|
+
if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMultiSet"));
|
|
13060
13390
|
return;
|
|
13061
13391
|
}
|
|
13062
|
-
throw new TypeError("TreeMultiSet
|
|
13392
|
+
throw new TypeError(ERR.comparatorRequired("TreeMultiSet"));
|
|
13063
13393
|
}
|
|
13064
13394
|
/**
|
|
13065
13395
|
* Validates that count is a non-negative safe integer.
|
|
13066
13396
|
* @remarks Time O(1), Space O(1)
|
|
13067
13397
|
*/
|
|
13068
13398
|
_validateCount(n) {
|
|
13069
|
-
if (!Number.isSafeInteger(n) || n < 0) throw new RangeError("
|
|
13399
|
+
if (!Number.isSafeInteger(n) || n < 0) throw new RangeError(ERR.invalidArgument("count must be a safe integer >= 0.", "TreeMultiSet"));
|
|
13070
13400
|
}
|
|
13071
13401
|
/**
|
|
13072
13402
|
* Total occurrences (sumCounts).
|
|
@@ -13490,9 +13820,7 @@ var MaxPriorityQueue = class extends PriorityQueue {
|
|
|
13490
13820
|
super(elements, {
|
|
13491
13821
|
comparator: /* @__PURE__ */ __name((a, b) => {
|
|
13492
13822
|
if (typeof a === "object" || typeof b === "object") {
|
|
13493
|
-
throw TypeError(
|
|
13494
|
-
`When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
|
|
13495
|
-
);
|
|
13823
|
+
throw new TypeError(ERR.comparatorRequired("MaxPriorityQueue"));
|
|
13496
13824
|
}
|
|
13497
13825
|
if (a < b) return 1;
|
|
13498
13826
|
if (a > b) return -1;
|
|
@@ -13633,7 +13961,7 @@ var Matrix = class _Matrix {
|
|
|
13633
13961
|
*/
|
|
13634
13962
|
add(matrix) {
|
|
13635
13963
|
if (!this.isMatchForCalculate(matrix)) {
|
|
13636
|
-
throw new Error("
|
|
13964
|
+
throw new Error(ERR.matrixDimensionMismatch("addition"));
|
|
13637
13965
|
}
|
|
13638
13966
|
const resultData = [];
|
|
13639
13967
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -13665,7 +13993,7 @@ var Matrix = class _Matrix {
|
|
|
13665
13993
|
*/
|
|
13666
13994
|
subtract(matrix) {
|
|
13667
13995
|
if (!this.isMatchForCalculate(matrix)) {
|
|
13668
|
-
throw new Error("
|
|
13996
|
+
throw new Error(ERR.matrixDimensionMismatch("subtraction"));
|
|
13669
13997
|
}
|
|
13670
13998
|
const resultData = [];
|
|
13671
13999
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -13696,7 +14024,7 @@ var Matrix = class _Matrix {
|
|
|
13696
14024
|
*/
|
|
13697
14025
|
multiply(matrix) {
|
|
13698
14026
|
if (this.cols !== matrix.rows) {
|
|
13699
|
-
throw new Error("
|
|
14027
|
+
throw new Error(ERR.matrixDimensionMismatch("multiplication (A.cols must equal B.rows)"));
|
|
13700
14028
|
}
|
|
13701
14029
|
const resultData = [];
|
|
13702
14030
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -13730,7 +14058,7 @@ var Matrix = class _Matrix {
|
|
|
13730
14058
|
*/
|
|
13731
14059
|
transpose() {
|
|
13732
14060
|
if (this.data.some((row) => row.length !== this.rows)) {
|
|
13733
|
-
throw new Error(
|
|
14061
|
+
throw new Error(ERR.matrixNotRectangular());
|
|
13734
14062
|
}
|
|
13735
14063
|
const resultData = [];
|
|
13736
14064
|
for (let j = 0; j < this.cols; j++) {
|
|
@@ -13754,7 +14082,7 @@ var Matrix = class _Matrix {
|
|
|
13754
14082
|
*/
|
|
13755
14083
|
inverse() {
|
|
13756
14084
|
if (this.rows !== this.cols) {
|
|
13757
|
-
throw new Error(
|
|
14085
|
+
throw new Error(ERR.matrixNotSquare());
|
|
13758
14086
|
}
|
|
13759
14087
|
const augmentedMatrixData = [];
|
|
13760
14088
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -13776,12 +14104,12 @@ var Matrix = class _Matrix {
|
|
|
13776
14104
|
pivotRow++;
|
|
13777
14105
|
}
|
|
13778
14106
|
if (pivotRow === this.rows) {
|
|
13779
|
-
throw new Error(
|
|
14107
|
+
throw new Error(ERR.matrixSingular());
|
|
13780
14108
|
}
|
|
13781
14109
|
augmentedMatrix._swapRows(i, pivotRow);
|
|
13782
14110
|
const pivotElement = augmentedMatrix.get(i, i) ?? 1;
|
|
13783
14111
|
if (pivotElement === 0) {
|
|
13784
|
-
throw new Error(
|
|
14112
|
+
throw new Error(ERR.matrixSingular());
|
|
13785
14113
|
}
|
|
13786
14114
|
augmentedMatrix._scaleRow(i, 1 / pivotElement);
|
|
13787
14115
|
for (let j = 0; j < this.rows; j++) {
|
|
@@ -13811,9 +14139,7 @@ var Matrix = class _Matrix {
|
|
|
13811
14139
|
*/
|
|
13812
14140
|
dot(matrix) {
|
|
13813
14141
|
if (this.cols !== matrix.rows) {
|
|
13814
|
-
throw new Error(
|
|
13815
|
-
"Number of columns in the first matrix must be equal to the number of rows in the second matrix for dot product."
|
|
13816
|
-
);
|
|
14142
|
+
throw new Error(ERR.matrixDimensionMismatch("dot product (A.cols must equal B.rows)"));
|
|
13817
14143
|
}
|
|
13818
14144
|
const resultData = [];
|
|
13819
14145
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -14439,7 +14765,7 @@ var Trie = class extends IterableElementBase {
|
|
|
14439
14765
|
for (const x of this) {
|
|
14440
14766
|
const v = thisArg === void 0 ? callback(x, i++, this) : callback.call(thisArg, x, i++, this);
|
|
14441
14767
|
if (typeof v !== "string") {
|
|
14442
|
-
throw new TypeError(
|
|
14768
|
+
throw new TypeError(ERR.callbackReturnType("string", typeof v, "Trie.map"));
|
|
14443
14769
|
}
|
|
14444
14770
|
newTrie.add(v);
|
|
14445
14771
|
}
|
|
@@ -14671,6 +14997,6 @@ var TreeNode = class _TreeNode {
|
|
|
14671
14997
|
* @license MIT License
|
|
14672
14998
|
*/
|
|
14673
14999
|
|
|
14674
|
-
export { AVLTree, AVLTreeNode, AbstractEdge, AbstractGraph, AbstractVertex, BST, BSTNode, BinaryIndexedTree, BinaryTree, BinaryTreeNode, Character, DFSOperation, Deque, DirectedEdge, DirectedGraph, DirectedVertex, DoublyLinkedList, DoublyLinkedListNode, FibonacciHeap, FibonacciHeapNode, HashMap, Heap, IterableElementBase, IterableEntryBase, LinkedHashMap, LinkedListQueue, MapEdge, MapGraph, MapVertex, Matrix, MaxHeap, MaxPriorityQueue, MinHeap, MinPriorityQueue, Navigator, PriorityQueue, Queue, Range, RedBlackTree, RedBlackTreeNode, SegmentTree, SegmentTreeNode, SinglyLinkedList, SinglyLinkedListNode, SkipList, SkipListNode, Stack, TreeMap, TreeMultiMap, TreeMultiMapNode, TreeMultiSet, TreeNode, TreeSet, Trie, TrieNode, UndirectedEdge, UndirectedGraph, UndirectedVertex, arrayRemove, asyncTrampoline, calcMinUnitsRequired, getMSB, isComparable, isTrampolineThunk, isWeakKey, makeAsyncTrampoline, makeTrampoline, makeTrampolineThunk, rangeCheck, roundFixed, throwRangeError, toBinaryString, trampoline, uuidV4 };
|
|
15000
|
+
export { AVLTree, AVLTreeNode, AbstractEdge, AbstractGraph, AbstractVertex, BST, BSTNode, BinaryIndexedTree, BinaryTree, BinaryTreeNode, Character, DFSOperation, Deque, DirectedEdge, DirectedGraph, DirectedVertex, DoublyLinkedList, DoublyLinkedListNode, ERR, FibonacciHeap, FibonacciHeapNode, HashMap, Heap, IterableElementBase, IterableEntryBase, LinkedHashMap, LinkedListQueue, MapEdge, MapGraph, MapVertex, Matrix, MaxHeap, MaxPriorityQueue, MinHeap, MinPriorityQueue, Navigator, PriorityQueue, Queue, Range, RedBlackTree, RedBlackTreeNode, SegmentTree, SegmentTreeNode, SinglyLinkedList, SinglyLinkedListNode, SkipList, SkipListNode, Stack, TreeMap, TreeMultiMap, TreeMultiMapNode, TreeMultiSet, TreeNode, TreeSet, Trie, TrieNode, UndirectedEdge, UndirectedGraph, UndirectedVertex, arrayRemove, asyncTrampoline, calcMinUnitsRequired, getMSB, isComparable, isTrampolineThunk, isWeakKey, makeAsyncTrampoline, makeTrampoline, makeTrampolineThunk, rangeCheck, roundFixed, throwRangeError, toBinaryString, trampoline, uuidV4 };
|
|
14675
15001
|
//# sourceMappingURL=index.mjs.map
|
|
14676
15002
|
//# sourceMappingURL=index.mjs.map
|