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/cjs/index.cjs
CHANGED
|
@@ -185,6 +185,55 @@ var IterableEntryBase = class {
|
|
|
185
185
|
}
|
|
186
186
|
};
|
|
187
187
|
|
|
188
|
+
// src/common/error.ts
|
|
189
|
+
var ERR = {
|
|
190
|
+
// Range / index
|
|
191
|
+
indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
|
|
192
|
+
invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
|
|
193
|
+
// Type / argument
|
|
194
|
+
invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
|
|
195
|
+
comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
|
|
196
|
+
invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
|
|
197
|
+
notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
|
|
198
|
+
invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
|
|
199
|
+
invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
|
|
200
|
+
invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
|
|
201
|
+
reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
|
|
202
|
+
callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
|
|
203
|
+
// State / operation
|
|
204
|
+
invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
|
|
205
|
+
// Matrix
|
|
206
|
+
matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
|
|
207
|
+
matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
|
|
208
|
+
matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
|
|
209
|
+
matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
|
|
210
|
+
matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
// src/common/index.ts
|
|
214
|
+
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
215
|
+
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
216
|
+
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
217
|
+
return DFSOperation2;
|
|
218
|
+
})(DFSOperation || {});
|
|
219
|
+
var Range = class {
|
|
220
|
+
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
221
|
+
this.low = low;
|
|
222
|
+
this.high = high;
|
|
223
|
+
this.includeLow = includeLow;
|
|
224
|
+
this.includeHigh = includeHigh;
|
|
225
|
+
}
|
|
226
|
+
static {
|
|
227
|
+
__name(this, "Range");
|
|
228
|
+
}
|
|
229
|
+
// Determine whether a key is within the range
|
|
230
|
+
isInRange(key, comparator) {
|
|
231
|
+
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
232
|
+
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
233
|
+
return lowCheck && highCheck;
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
|
|
188
237
|
// src/data-structures/base/iterable-element-base.ts
|
|
189
238
|
var IterableElementBase = class {
|
|
190
239
|
static {
|
|
@@ -203,7 +252,7 @@ var IterableElementBase = class {
|
|
|
203
252
|
if (options) {
|
|
204
253
|
const { toElementFn } = options;
|
|
205
254
|
if (typeof toElementFn === "function") this._toElementFn = toElementFn;
|
|
206
|
-
else if (toElementFn) throw new TypeError("toElementFn
|
|
255
|
+
else if (toElementFn) throw new TypeError(ERR.notAFunction("toElementFn"));
|
|
207
256
|
}
|
|
208
257
|
}
|
|
209
258
|
/**
|
|
@@ -366,7 +415,7 @@ var IterableElementBase = class {
|
|
|
366
415
|
acc = initialValue;
|
|
367
416
|
} else {
|
|
368
417
|
const first = iter.next();
|
|
369
|
-
if (first.done) throw new TypeError(
|
|
418
|
+
if (first.done) throw new TypeError(ERR.reduceEmpty());
|
|
370
419
|
acc = first.value;
|
|
371
420
|
index = 1;
|
|
372
421
|
}
|
|
@@ -434,8 +483,10 @@ var getMSB = /* @__PURE__ */ __name((value) => {
|
|
|
434
483
|
}
|
|
435
484
|
return 1 << 31 - Math.clz32(value);
|
|
436
485
|
}, "getMSB");
|
|
437
|
-
var rangeCheck = /* @__PURE__ */ __name((index, min, max, message
|
|
438
|
-
if (index < min || index > max)
|
|
486
|
+
var rangeCheck = /* @__PURE__ */ __name((index, min, max, message) => {
|
|
487
|
+
if (index < min || index > max) {
|
|
488
|
+
throw new RangeError(message ?? `Index ${index} is out of range [${min}, ${max}].`);
|
|
489
|
+
}
|
|
439
490
|
}, "rangeCheck");
|
|
440
491
|
var throwRangeError = /* @__PURE__ */ __name((message = "The value is off-limits.") => {
|
|
441
492
|
throw new RangeError(message);
|
|
@@ -858,8 +909,8 @@ var LinkedHashMap = class extends IterableEntryBase {
|
|
|
858
909
|
if (this.isEntry(rawElement)) {
|
|
859
910
|
return rawElement;
|
|
860
911
|
}
|
|
861
|
-
throw new
|
|
862
|
-
"If
|
|
912
|
+
throw new TypeError(
|
|
913
|
+
ERR.invalidArgument("If elements do not adhere to [key, value], provide options.toEntryFn to transform raw records.", "HashMap")
|
|
863
914
|
);
|
|
864
915
|
}, "_toEntryFn");
|
|
865
916
|
get toEntryFn() {
|
|
@@ -1096,6 +1147,13 @@ var LinkedHashMap = class extends IterableEntryBase {
|
|
|
1096
1147
|
}
|
|
1097
1148
|
}
|
|
1098
1149
|
_deleteNode(node) {
|
|
1150
|
+
const key = node.key;
|
|
1151
|
+
if (isWeakKey(key)) {
|
|
1152
|
+
this._objMap.delete(key);
|
|
1153
|
+
} else {
|
|
1154
|
+
const hash = this._hashFn(key);
|
|
1155
|
+
delete this._noObjMap[hash];
|
|
1156
|
+
}
|
|
1099
1157
|
const { prev, next } = node;
|
|
1100
1158
|
prev.next = next;
|
|
1101
1159
|
next.prev = prev;
|
|
@@ -3610,18 +3668,12 @@ var Deque = class extends LinearBase {
|
|
|
3610
3668
|
__name(this, "Deque");
|
|
3611
3669
|
}
|
|
3612
3670
|
_equals = /* @__PURE__ */ __name((a, b) => Object.is(a, b), "_equals");
|
|
3613
|
-
/**
|
|
3614
|
-
* Create a Deque and optionally bulk-insert elements.
|
|
3615
|
-
* @remarks Time O(N), Space O(N)
|
|
3616
|
-
* @param [elements] - Iterable (or iterable-like) of elements/records to insert.
|
|
3617
|
-
* @param [options] - Options such as bucketSize, toElementFn, and maxLen.
|
|
3618
|
-
* @returns New Deque instance.
|
|
3619
|
-
*/
|
|
3620
3671
|
constructor(elements = [], options) {
|
|
3621
3672
|
super(options);
|
|
3622
3673
|
if (options) {
|
|
3623
|
-
const { bucketSize } = options;
|
|
3674
|
+
const { bucketSize, autoCompactRatio } = options;
|
|
3624
3675
|
if (typeof bucketSize === "number") this._bucketSize = bucketSize;
|
|
3676
|
+
if (typeof autoCompactRatio === "number") this._autoCompactRatio = autoCompactRatio;
|
|
3625
3677
|
}
|
|
3626
3678
|
let _size;
|
|
3627
3679
|
if ("length" in elements) {
|
|
@@ -3647,6 +3699,30 @@ var Deque = class extends LinearBase {
|
|
|
3647
3699
|
get bucketSize() {
|
|
3648
3700
|
return this._bucketSize;
|
|
3649
3701
|
}
|
|
3702
|
+
_autoCompactRatio = 0.5;
|
|
3703
|
+
/**
|
|
3704
|
+
* Get the auto-compaction ratio.
|
|
3705
|
+
* When `elements / (bucketCount * bucketSize)` drops below this ratio after
|
|
3706
|
+
* enough shift/pop operations, the deque auto-compacts.
|
|
3707
|
+
* @remarks Time O(1), Space O(1)
|
|
3708
|
+
* @returns Current ratio threshold. 0 means auto-compact is disabled.
|
|
3709
|
+
*/
|
|
3710
|
+
get autoCompactRatio() {
|
|
3711
|
+
return this._autoCompactRatio;
|
|
3712
|
+
}
|
|
3713
|
+
/**
|
|
3714
|
+
* Set the auto-compaction ratio.
|
|
3715
|
+
* @remarks Time O(1), Space O(1)
|
|
3716
|
+
* @param value - Ratio in [0,1]. 0 disables auto-compact.
|
|
3717
|
+
*/
|
|
3718
|
+
set autoCompactRatio(value) {
|
|
3719
|
+
this._autoCompactRatio = value;
|
|
3720
|
+
}
|
|
3721
|
+
/**
|
|
3722
|
+
* Counter for shift/pop operations since last compaction check.
|
|
3723
|
+
* Only checks ratio every `_bucketSize` operations to minimize overhead.
|
|
3724
|
+
*/
|
|
3725
|
+
_compactCounter = 0;
|
|
3650
3726
|
_bucketFirst = 0;
|
|
3651
3727
|
/**
|
|
3652
3728
|
* Get the index of the first bucket in use.
|
|
@@ -3785,6 +3861,7 @@ var Deque = class extends LinearBase {
|
|
|
3785
3861
|
}
|
|
3786
3862
|
}
|
|
3787
3863
|
this._length -= 1;
|
|
3864
|
+
this._autoCompact();
|
|
3788
3865
|
return element;
|
|
3789
3866
|
}
|
|
3790
3867
|
/**
|
|
@@ -3807,6 +3884,7 @@ var Deque = class extends LinearBase {
|
|
|
3807
3884
|
}
|
|
3808
3885
|
}
|
|
3809
3886
|
this._length -= 1;
|
|
3887
|
+
this._autoCompact();
|
|
3810
3888
|
return element;
|
|
3811
3889
|
}
|
|
3812
3890
|
/**
|
|
@@ -4139,11 +4217,40 @@ var Deque = class extends LinearBase {
|
|
|
4139
4217
|
* @remarks Time O(N), Space O(1)
|
|
4140
4218
|
* @returns void
|
|
4141
4219
|
*/
|
|
4220
|
+
/**
|
|
4221
|
+
* (Protected) Trigger auto-compaction if space utilization drops below threshold.
|
|
4222
|
+
* Only checks every `_bucketSize` operations to minimize hot-path overhead.
|
|
4223
|
+
* Uses element-based ratio: `elements / (bucketCount * bucketSize)`.
|
|
4224
|
+
*/
|
|
4225
|
+
_autoCompact() {
|
|
4226
|
+
if (this._autoCompactRatio <= 0 || this._bucketCount <= 1) return;
|
|
4227
|
+
this._compactCounter++;
|
|
4228
|
+
if (this._compactCounter < this._bucketSize) return;
|
|
4229
|
+
this._compactCounter = 0;
|
|
4230
|
+
const utilization = this._length / (this._bucketCount * this._bucketSize);
|
|
4231
|
+
if (utilization < this._autoCompactRatio) {
|
|
4232
|
+
this.shrinkToFit();
|
|
4233
|
+
}
|
|
4234
|
+
}
|
|
4235
|
+
/**
|
|
4236
|
+
* Compact the deque by removing unused buckets.
|
|
4237
|
+
* @remarks Time O(N), Space O(1)
|
|
4238
|
+
* @returns True if compaction was performed (bucket count reduced).
|
|
4239
|
+
*/
|
|
4240
|
+
/**
|
|
4241
|
+
* Compact the deque by removing unused buckets.
|
|
4242
|
+
* @remarks Time O(N), Space O(1)
|
|
4243
|
+
* @returns True if compaction was performed (bucket count reduced).
|
|
4244
|
+
*/
|
|
4245
|
+
compact() {
|
|
4246
|
+
const before = this._bucketCount;
|
|
4247
|
+
this.shrinkToFit();
|
|
4248
|
+
return this._bucketCount < before;
|
|
4249
|
+
}
|
|
4142
4250
|
shrinkToFit() {
|
|
4143
4251
|
if (this._length === 0) return;
|
|
4144
4252
|
const newBuckets = [];
|
|
4145
|
-
if (this._bucketFirst
|
|
4146
|
-
else if (this._bucketFirst < this._bucketLast) {
|
|
4253
|
+
if (this._bucketFirst <= this._bucketLast) {
|
|
4147
4254
|
for (let i = this._bucketFirst; i <= this._bucketLast; ++i) {
|
|
4148
4255
|
newBuckets.push(this._buckets[i]);
|
|
4149
4256
|
}
|
|
@@ -4158,6 +4265,8 @@ var Deque = class extends LinearBase {
|
|
|
4158
4265
|
this._bucketFirst = 0;
|
|
4159
4266
|
this._bucketLast = newBuckets.length - 1;
|
|
4160
4267
|
this._buckets = newBuckets;
|
|
4268
|
+
this._bucketCount = newBuckets.length;
|
|
4269
|
+
this._compactCounter = 0;
|
|
4161
4270
|
}
|
|
4162
4271
|
/**
|
|
4163
4272
|
* Deep clone this deque, preserving options.
|
|
@@ -4656,7 +4765,7 @@ var Heap = class _Heap extends IterableElementBase {
|
|
|
4656
4765
|
*/
|
|
4657
4766
|
map(callback, options, thisArg) {
|
|
4658
4767
|
const { comparator, toElementFn, ...rest } = options ?? {};
|
|
4659
|
-
if (!comparator) throw new TypeError("Heap.map
|
|
4768
|
+
if (!comparator) throw new TypeError(ERR.comparatorRequired("Heap.map"));
|
|
4660
4769
|
const out = this._createLike([], { ...rest, comparator, toElementFn });
|
|
4661
4770
|
let i = 0;
|
|
4662
4771
|
for (const x of this) {
|
|
@@ -4683,7 +4792,7 @@ var Heap = class _Heap extends IterableElementBase {
|
|
|
4683
4792
|
}
|
|
4684
4793
|
_DEFAULT_COMPARATOR = /* @__PURE__ */ __name((a, b) => {
|
|
4685
4794
|
if (typeof a === "object" || typeof b === "object") {
|
|
4686
|
-
throw TypeError(
|
|
4795
|
+
throw new TypeError(ERR.comparatorRequired("Heap"));
|
|
4687
4796
|
}
|
|
4688
4797
|
if (a > b) return 1;
|
|
4689
4798
|
if (a < b) return -1;
|
|
@@ -4795,7 +4904,7 @@ var FibonacciHeap = class {
|
|
|
4795
4904
|
constructor(comparator) {
|
|
4796
4905
|
this.clear();
|
|
4797
4906
|
this._comparator = comparator || this._defaultComparator;
|
|
4798
|
-
if (typeof this.comparator !== "function") throw new
|
|
4907
|
+
if (typeof this.comparator !== "function") throw new TypeError(ERR.notAFunction("comparator", "FibonacciHeap"));
|
|
4799
4908
|
}
|
|
4800
4909
|
_root;
|
|
4801
4910
|
/**
|
|
@@ -5011,9 +5120,7 @@ var MaxHeap = class extends Heap {
|
|
|
5011
5120
|
super(elements, {
|
|
5012
5121
|
comparator: /* @__PURE__ */ __name((a, b) => {
|
|
5013
5122
|
if (typeof a === "object" || typeof b === "object") {
|
|
5014
|
-
throw TypeError(
|
|
5015
|
-
`When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
|
|
5016
|
-
);
|
|
5123
|
+
throw new TypeError(ERR.comparatorRequired("MaxHeap"));
|
|
5017
5124
|
}
|
|
5018
5125
|
if (a < b) return 1;
|
|
5019
5126
|
if (a > b) return -1;
|
|
@@ -5182,7 +5289,7 @@ var AbstractGraph = class extends IterableEntryBase {
|
|
|
5182
5289
|
const newEdge = this.createEdge(srcOrEdge, dest, weight, value);
|
|
5183
5290
|
return this._addEdge(newEdge);
|
|
5184
5291
|
} else {
|
|
5185
|
-
throw new
|
|
5292
|
+
throw new TypeError(ERR.invalidArgument("dest must be a Vertex or vertex key when srcOrEdge is an Edge.", "Graph"));
|
|
5186
5293
|
}
|
|
5187
5294
|
}
|
|
5188
5295
|
}
|
|
@@ -5862,6 +5969,92 @@ var AbstractGraph = class extends IterableEntryBase {
|
|
|
5862
5969
|
_getVertexKey(vertexOrKey) {
|
|
5863
5970
|
return vertexOrKey instanceof AbstractVertex ? vertexOrKey.key : vertexOrKey;
|
|
5864
5971
|
}
|
|
5972
|
+
/**
|
|
5973
|
+
* The edge connector string used in visual output.
|
|
5974
|
+
* Override in subclasses (e.g., '--' for undirected, '->' for directed).
|
|
5975
|
+
*/
|
|
5976
|
+
get _edgeConnector() {
|
|
5977
|
+
return "--";
|
|
5978
|
+
}
|
|
5979
|
+
/**
|
|
5980
|
+
* Generate a text-based visual representation of the graph.
|
|
5981
|
+
*
|
|
5982
|
+
* **Adjacency list format:**
|
|
5983
|
+
* ```
|
|
5984
|
+
* Graph (5 vertices, 6 edges):
|
|
5985
|
+
* A -> B (1), C (2)
|
|
5986
|
+
* B -> D (3)
|
|
5987
|
+
* C -> (no outgoing edges)
|
|
5988
|
+
* D -> A (1)
|
|
5989
|
+
* E (isolated)
|
|
5990
|
+
* ```
|
|
5991
|
+
*
|
|
5992
|
+
* @param options - Optional display settings.
|
|
5993
|
+
* @param options.showWeight - Whether to show edge weights (default: true).
|
|
5994
|
+
* @returns The visual string.
|
|
5995
|
+
*/
|
|
5996
|
+
toVisual(options) {
|
|
5997
|
+
const showWeight = options?.showWeight ?? true;
|
|
5998
|
+
const vertices = [...this._vertexMap.values()];
|
|
5999
|
+
const vertexCount = vertices.length;
|
|
6000
|
+
const edgeCount = this.edgeSet().length;
|
|
6001
|
+
const lines = [`Graph (${vertexCount} vertices, ${edgeCount} edges):`];
|
|
6002
|
+
for (const vertex of vertices) {
|
|
6003
|
+
const neighbors = this.getNeighbors(vertex);
|
|
6004
|
+
if (neighbors.length === 0) {
|
|
6005
|
+
lines.push(` ${vertex.key} (isolated)`);
|
|
6006
|
+
} else {
|
|
6007
|
+
const edgeStrs = neighbors.map((neighbor) => {
|
|
6008
|
+
const edge = this.getEdge(vertex, neighbor);
|
|
6009
|
+
if (edge && showWeight && edge.weight !== void 0 && edge.weight !== 1) {
|
|
6010
|
+
return `${neighbor.key} (${edge.weight})`;
|
|
6011
|
+
}
|
|
6012
|
+
return `${neighbor.key}`;
|
|
6013
|
+
});
|
|
6014
|
+
lines.push(` ${vertex.key} ${this._edgeConnector} ${edgeStrs.join(", ")}`);
|
|
6015
|
+
}
|
|
6016
|
+
}
|
|
6017
|
+
return lines.join("\n");
|
|
6018
|
+
}
|
|
6019
|
+
/**
|
|
6020
|
+
* Generate DOT language representation for Graphviz.
|
|
6021
|
+
*
|
|
6022
|
+
* @param options - Optional display settings.
|
|
6023
|
+
* @param options.name - Graph name (default: 'G').
|
|
6024
|
+
* @param options.showWeight - Whether to label edges with weight (default: true).
|
|
6025
|
+
* @returns DOT format string.
|
|
6026
|
+
*/
|
|
6027
|
+
toDot(options) {
|
|
6028
|
+
const name = options?.name ?? "G";
|
|
6029
|
+
const showWeight = options?.showWeight ?? true;
|
|
6030
|
+
const isDirected = this._edgeConnector === "->";
|
|
6031
|
+
const graphType = isDirected ? "digraph" : "graph";
|
|
6032
|
+
const edgeOp = isDirected ? "->" : "--";
|
|
6033
|
+
const lines = [`${graphType} ${name} {`];
|
|
6034
|
+
for (const vertex of this._vertexMap.values()) {
|
|
6035
|
+
lines.push(` "${vertex.key}";`);
|
|
6036
|
+
}
|
|
6037
|
+
const visited = /* @__PURE__ */ new Set();
|
|
6038
|
+
for (const vertex of this._vertexMap.values()) {
|
|
6039
|
+
for (const neighbor of this.getNeighbors(vertex)) {
|
|
6040
|
+
const edgeId = isDirected ? `${vertex.key}->${neighbor.key}` : [vertex.key, neighbor.key].sort().join("--");
|
|
6041
|
+
if (visited.has(edgeId)) continue;
|
|
6042
|
+
visited.add(edgeId);
|
|
6043
|
+
const edge = this.getEdge(vertex, neighbor);
|
|
6044
|
+
const label = edge && showWeight && edge.weight !== void 0 && edge.weight !== 1 ? ` [label="${edge.weight}"]` : "";
|
|
6045
|
+
lines.push(` "${vertex.key}" ${edgeOp} "${neighbor.key}"${label};`);
|
|
6046
|
+
}
|
|
6047
|
+
}
|
|
6048
|
+
lines.push("}");
|
|
6049
|
+
return lines.join("\n");
|
|
6050
|
+
}
|
|
6051
|
+
/**
|
|
6052
|
+
* Print the graph to console.
|
|
6053
|
+
* @param options - Display settings passed to `toVisual`.
|
|
6054
|
+
*/
|
|
6055
|
+
print(options) {
|
|
6056
|
+
console.log(this.toVisual(options));
|
|
6057
|
+
}
|
|
5865
6058
|
};
|
|
5866
6059
|
|
|
5867
6060
|
// src/data-structures/graph/directed-graph.ts
|
|
@@ -5897,6 +6090,9 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
|
|
|
5897
6090
|
constructor(options) {
|
|
5898
6091
|
super(options);
|
|
5899
6092
|
}
|
|
6093
|
+
get _edgeConnector() {
|
|
6094
|
+
return "->";
|
|
6095
|
+
}
|
|
5900
6096
|
_outEdgeMap = /* @__PURE__ */ new Map();
|
|
5901
6097
|
get outEdgeMap() {
|
|
5902
6098
|
return this._outEdgeMap;
|
|
@@ -6678,6 +6874,84 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
|
|
|
6678
6874
|
cutVertices
|
|
6679
6875
|
};
|
|
6680
6876
|
}
|
|
6877
|
+
/**
|
|
6878
|
+
* Find biconnected components using edge-stack Tarjan variant.
|
|
6879
|
+
* A biconnected component is a maximal biconnected subgraph.
|
|
6880
|
+
* @returns Array of edge arrays, each representing a biconnected component.
|
|
6881
|
+
* @remarks Time O(V + E), Space O(V + E)
|
|
6882
|
+
*/
|
|
6883
|
+
getBiconnectedComponents() {
|
|
6884
|
+
const dfn = /* @__PURE__ */ new Map();
|
|
6885
|
+
const low = /* @__PURE__ */ new Map();
|
|
6886
|
+
const edgeStack = [];
|
|
6887
|
+
const components = [];
|
|
6888
|
+
let time = 0;
|
|
6889
|
+
const dfs = /* @__PURE__ */ __name((vertex, parent) => {
|
|
6890
|
+
dfn.set(vertex, time);
|
|
6891
|
+
low.set(vertex, time);
|
|
6892
|
+
time++;
|
|
6893
|
+
const neighbors = this.getNeighbors(vertex);
|
|
6894
|
+
let childCount = 0;
|
|
6895
|
+
for (const neighbor of neighbors) {
|
|
6896
|
+
const edge = this.getEdge(vertex, neighbor);
|
|
6897
|
+
if (!edge) continue;
|
|
6898
|
+
if (!dfn.has(neighbor)) {
|
|
6899
|
+
childCount++;
|
|
6900
|
+
edgeStack.push(edge);
|
|
6901
|
+
dfs(neighbor, vertex);
|
|
6902
|
+
low.set(vertex, Math.min(low.get(vertex), low.get(neighbor)));
|
|
6903
|
+
if (parent === void 0 && childCount > 1 || parent !== void 0 && low.get(neighbor) >= dfn.get(vertex)) {
|
|
6904
|
+
const component = [];
|
|
6905
|
+
let e;
|
|
6906
|
+
do {
|
|
6907
|
+
e = edgeStack.pop();
|
|
6908
|
+
if (e) component.push(e);
|
|
6909
|
+
} while (e && e !== edge);
|
|
6910
|
+
if (component.length > 0) components.push(component);
|
|
6911
|
+
}
|
|
6912
|
+
} else if (neighbor !== parent && dfn.get(neighbor) < dfn.get(vertex)) {
|
|
6913
|
+
edgeStack.push(edge);
|
|
6914
|
+
low.set(vertex, Math.min(low.get(vertex), dfn.get(neighbor)));
|
|
6915
|
+
}
|
|
6916
|
+
}
|
|
6917
|
+
}, "dfs");
|
|
6918
|
+
for (const vertex of this.vertexMap.values()) {
|
|
6919
|
+
if (!dfn.has(vertex)) {
|
|
6920
|
+
dfs(vertex, void 0);
|
|
6921
|
+
if (edgeStack.length > 0) {
|
|
6922
|
+
components.push([...edgeStack]);
|
|
6923
|
+
edgeStack.length = 0;
|
|
6924
|
+
}
|
|
6925
|
+
}
|
|
6926
|
+
}
|
|
6927
|
+
return components;
|
|
6928
|
+
}
|
|
6929
|
+
/**
|
|
6930
|
+
* Detect whether the graph contains a cycle.
|
|
6931
|
+
* Uses DFS with parent tracking.
|
|
6932
|
+
* @returns `true` if a cycle exists, `false` otherwise.
|
|
6933
|
+
* @remarks Time O(V + E), Space O(V)
|
|
6934
|
+
*/
|
|
6935
|
+
hasCycle() {
|
|
6936
|
+
const visited = /* @__PURE__ */ new Set();
|
|
6937
|
+
const dfs = /* @__PURE__ */ __name((vertex, parent) => {
|
|
6938
|
+
visited.add(vertex);
|
|
6939
|
+
for (const neighbor of this.getNeighbors(vertex)) {
|
|
6940
|
+
if (!visited.has(neighbor)) {
|
|
6941
|
+
if (dfs(neighbor, vertex)) return true;
|
|
6942
|
+
} else if (neighbor !== parent) {
|
|
6943
|
+
return true;
|
|
6944
|
+
}
|
|
6945
|
+
}
|
|
6946
|
+
return false;
|
|
6947
|
+
}, "dfs");
|
|
6948
|
+
for (const vertex of this.vertexMap.values()) {
|
|
6949
|
+
if (!visited.has(vertex)) {
|
|
6950
|
+
if (dfs(vertex, void 0)) return true;
|
|
6951
|
+
}
|
|
6952
|
+
}
|
|
6953
|
+
return false;
|
|
6954
|
+
}
|
|
6681
6955
|
/**
|
|
6682
6956
|
* Get bridges discovered by `tarjan()`.
|
|
6683
6957
|
* @returns Array of edges that are bridges.
|
|
@@ -6831,30 +7105,6 @@ var MapGraph = class _MapGraph extends DirectedGraph {
|
|
|
6831
7105
|
}
|
|
6832
7106
|
};
|
|
6833
7107
|
|
|
6834
|
-
// src/common/index.ts
|
|
6835
|
-
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
6836
|
-
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
6837
|
-
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
6838
|
-
return DFSOperation2;
|
|
6839
|
-
})(DFSOperation || {});
|
|
6840
|
-
var Range = class {
|
|
6841
|
-
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
6842
|
-
this.low = low;
|
|
6843
|
-
this.high = high;
|
|
6844
|
-
this.includeLow = includeLow;
|
|
6845
|
-
this.includeHigh = includeHigh;
|
|
6846
|
-
}
|
|
6847
|
-
static {
|
|
6848
|
-
__name(this, "Range");
|
|
6849
|
-
}
|
|
6850
|
-
// Determine whether a key is within the range
|
|
6851
|
-
isInRange(key, comparator) {
|
|
6852
|
-
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
6853
|
-
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
6854
|
-
return lowCheck && highCheck;
|
|
6855
|
-
}
|
|
6856
|
-
};
|
|
6857
|
-
|
|
6858
7108
|
// src/data-structures/binary-tree/binary-tree.ts
|
|
6859
7109
|
var BinaryTreeNode = class {
|
|
6860
7110
|
static {
|
|
@@ -6993,7 +7243,7 @@ var BinaryTreeNode = class {
|
|
|
6993
7243
|
return "MAL_NODE";
|
|
6994
7244
|
}
|
|
6995
7245
|
};
|
|
6996
|
-
var BinaryTree = class extends IterableEntryBase {
|
|
7246
|
+
var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
6997
7247
|
static {
|
|
6998
7248
|
__name(this, "BinaryTree");
|
|
6999
7249
|
}
|
|
@@ -7013,7 +7263,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
7013
7263
|
if (isMapMode !== void 0) this._isMapMode = isMapMode;
|
|
7014
7264
|
if (isDuplicate !== void 0) this._isDuplicate = isDuplicate;
|
|
7015
7265
|
if (typeof toEntryFn === "function") this._toEntryFn = toEntryFn;
|
|
7016
|
-
else if (toEntryFn) throw TypeError("toEntryFn
|
|
7266
|
+
else if (toEntryFn) throw new TypeError(ERR.notAFunction("toEntryFn", "BinaryTree"));
|
|
7017
7267
|
}
|
|
7018
7268
|
if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
|
|
7019
7269
|
}
|
|
@@ -7251,7 +7501,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
7251
7501
|
if (!this._root) {
|
|
7252
7502
|
this._setRoot(newNode);
|
|
7253
7503
|
if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
|
|
7254
|
-
this._size = 1;
|
|
7504
|
+
if (newNode !== null) this._size = 1;
|
|
7255
7505
|
return true;
|
|
7256
7506
|
}
|
|
7257
7507
|
const queue = new Queue([this._root]);
|
|
@@ -7283,7 +7533,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
7283
7533
|
potentialParent.right = newNode;
|
|
7284
7534
|
}
|
|
7285
7535
|
if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
|
|
7286
|
-
this._size++;
|
|
7536
|
+
if (newNode !== null) this._size++;
|
|
7287
7537
|
return true;
|
|
7288
7538
|
}
|
|
7289
7539
|
return false;
|
|
@@ -7851,7 +8101,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
7851
8101
|
}
|
|
7852
8102
|
/**
|
|
7853
8103
|
* Finds all leaf nodes in the tree.
|
|
7854
|
-
* @remarks Time O(N), visits every node. Space O(H) for recursive
|
|
8104
|
+
* @remarks Time O(N), visits every node. Space O(H) for recursive or iterative stack.
|
|
7855
8105
|
*
|
|
7856
8106
|
* @template C - The type of the callback function.
|
|
7857
8107
|
* @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each leaf node.
|
|
@@ -7874,15 +8124,15 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
7874
8124
|
}, "dfs");
|
|
7875
8125
|
dfs(startNode);
|
|
7876
8126
|
} else {
|
|
7877
|
-
const
|
|
7878
|
-
while (
|
|
7879
|
-
const cur =
|
|
8127
|
+
const stack = [startNode];
|
|
8128
|
+
while (stack.length > 0) {
|
|
8129
|
+
const cur = stack.pop();
|
|
7880
8130
|
if (this.isRealNode(cur)) {
|
|
7881
8131
|
if (this.isLeaf(cur)) {
|
|
7882
8132
|
leaves.push(callback(cur));
|
|
7883
8133
|
}
|
|
7884
|
-
if (this.isRealNode(cur.
|
|
7885
|
-
if (this.isRealNode(cur.
|
|
8134
|
+
if (this.isRealNode(cur.right)) stack.push(cur.right);
|
|
8135
|
+
if (this.isRealNode(cur.left)) stack.push(cur.left);
|
|
7886
8136
|
}
|
|
7887
8137
|
}
|
|
7888
8138
|
}
|
|
@@ -8344,42 +8594,98 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
8344
8594
|
_displayAux(node, options) {
|
|
8345
8595
|
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
8346
8596
|
const emptyDisplayLayout = [["\u2500"], 1, 0, 0];
|
|
8347
|
-
|
|
8348
|
-
|
|
8349
|
-
|
|
8350
|
-
|
|
8351
|
-
|
|
8352
|
-
|
|
8353
|
-
|
|
8354
|
-
|
|
8355
|
-
|
|
8356
|
-
|
|
8357
|
-
|
|
8358
|
-
|
|
8359
|
-
|
|
8360
|
-
|
|
8361
|
-
|
|
8362
|
-
|
|
8363
|
-
|
|
8364
|
-
|
|
8365
|
-
|
|
8366
|
-
const
|
|
8367
|
-
|
|
8368
|
-
|
|
8369
|
-
|
|
8370
|
-
|
|
8371
|
-
|
|
8372
|
-
|
|
8373
|
-
|
|
8374
|
-
|
|
8597
|
+
const newFrame = /* @__PURE__ */ __name((n) => ({
|
|
8598
|
+
node: n,
|
|
8599
|
+
stage: 0,
|
|
8600
|
+
leftLayout: emptyDisplayLayout,
|
|
8601
|
+
rightLayout: emptyDisplayLayout
|
|
8602
|
+
}), "newFrame");
|
|
8603
|
+
const stack = [newFrame(node)];
|
|
8604
|
+
let result = emptyDisplayLayout;
|
|
8605
|
+
const setChildResult = /* @__PURE__ */ __name((layout) => {
|
|
8606
|
+
if (stack.length === 0) {
|
|
8607
|
+
result = layout;
|
|
8608
|
+
return;
|
|
8609
|
+
}
|
|
8610
|
+
const parent = stack[stack.length - 1];
|
|
8611
|
+
if (parent.stage === 1) parent.leftLayout = layout;
|
|
8612
|
+
else parent.rightLayout = layout;
|
|
8613
|
+
}, "setChildResult");
|
|
8614
|
+
while (stack.length > 0) {
|
|
8615
|
+
const frame = stack[stack.length - 1];
|
|
8616
|
+
const cur = frame.node;
|
|
8617
|
+
if (frame.stage === 0) {
|
|
8618
|
+
if (this._isDisplayLeaf(cur, options)) {
|
|
8619
|
+
stack.pop();
|
|
8620
|
+
const layout = this._resolveDisplayLeaf(cur, options, emptyDisplayLayout);
|
|
8621
|
+
setChildResult(layout);
|
|
8622
|
+
continue;
|
|
8623
|
+
}
|
|
8624
|
+
frame.stage = 1;
|
|
8625
|
+
stack.push(newFrame(cur.left));
|
|
8626
|
+
} else if (frame.stage === 1) {
|
|
8627
|
+
frame.stage = 2;
|
|
8628
|
+
stack.push(newFrame(cur.right));
|
|
8629
|
+
} else {
|
|
8630
|
+
stack.pop();
|
|
8631
|
+
const line = this.isNIL(cur) ? "S" : String(cur.key);
|
|
8632
|
+
const layout = _BinaryTree._buildNodeDisplay(line, line.length, frame.leftLayout, frame.rightLayout);
|
|
8633
|
+
setChildResult(layout);
|
|
8375
8634
|
}
|
|
8376
|
-
return [
|
|
8377
|
-
mergedLines,
|
|
8378
|
-
leftWidth + width + rightWidth,
|
|
8379
|
-
Math.max(leftHeight, rightHeight) + 2,
|
|
8380
|
-
leftWidth + Math.floor(width / 2)
|
|
8381
|
-
];
|
|
8382
8635
|
}
|
|
8636
|
+
return result;
|
|
8637
|
+
}
|
|
8638
|
+
static _buildNodeDisplay(line, width, left, right) {
|
|
8639
|
+
const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
|
|
8640
|
+
const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
|
|
8641
|
+
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));
|
|
8642
|
+
const secondLine = (leftHeight > 0 ? " ".repeat(leftMiddle) + "/" + " ".repeat(leftWidth - leftMiddle - 1) : " ".repeat(leftWidth)) + " ".repeat(width) + (rightHeight > 0 ? " ".repeat(rightMiddle) + "\\" + " ".repeat(rightWidth - rightMiddle - 1) : " ".repeat(rightWidth));
|
|
8643
|
+
const mergedLines = [firstLine, secondLine];
|
|
8644
|
+
for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
|
|
8645
|
+
const leftLine = i < leftHeight ? leftLines[i] : " ".repeat(leftWidth);
|
|
8646
|
+
const rightLine = i < rightHeight ? rightLines[i] : " ".repeat(rightWidth);
|
|
8647
|
+
mergedLines.push(leftLine + " ".repeat(width) + rightLine);
|
|
8648
|
+
}
|
|
8649
|
+
return [
|
|
8650
|
+
mergedLines,
|
|
8651
|
+
leftWidth + width + rightWidth,
|
|
8652
|
+
Math.max(leftHeight, rightHeight) + 2,
|
|
8653
|
+
leftWidth + Math.floor(width / 2)
|
|
8654
|
+
];
|
|
8655
|
+
}
|
|
8656
|
+
/**
|
|
8657
|
+
* Check if a node is a display leaf (empty, null, undefined, NIL, or real leaf).
|
|
8658
|
+
*/
|
|
8659
|
+
_isDisplayLeaf(node, options) {
|
|
8660
|
+
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
8661
|
+
if (node === null && !isShowNull) return true;
|
|
8662
|
+
if (node === void 0 && !isShowUndefined) return true;
|
|
8663
|
+
if (this.isNIL(node) && !isShowRedBlackNIL) return true;
|
|
8664
|
+
if (node === null || node === void 0) return true;
|
|
8665
|
+
const hasDisplayableLeft = this._hasDisplayableChild(node.left, options);
|
|
8666
|
+
const hasDisplayableRight = this._hasDisplayableChild(node.right, options);
|
|
8667
|
+
return !hasDisplayableLeft && !hasDisplayableRight;
|
|
8668
|
+
}
|
|
8669
|
+
_hasDisplayableChild(child, options) {
|
|
8670
|
+
if (child === null) return !!options.isShowNull;
|
|
8671
|
+
if (child === void 0) return !!options.isShowUndefined;
|
|
8672
|
+
if (this.isNIL(child)) return !!options.isShowRedBlackNIL;
|
|
8673
|
+
return true;
|
|
8674
|
+
}
|
|
8675
|
+
/**
|
|
8676
|
+
* Resolve a display leaf node to its layout.
|
|
8677
|
+
*/
|
|
8678
|
+
_resolveDisplayLeaf(node, options, emptyDisplayLayout) {
|
|
8679
|
+
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
8680
|
+
if (node === null && !isShowNull) return emptyDisplayLayout;
|
|
8681
|
+
if (node === void 0 && !isShowUndefined) return emptyDisplayLayout;
|
|
8682
|
+
if (this.isNIL(node) && !isShowRedBlackNIL) return emptyDisplayLayout;
|
|
8683
|
+
if (node !== null && node !== void 0) {
|
|
8684
|
+
const line2 = this.isNIL(node) ? "S" : String(node.key);
|
|
8685
|
+
return _BinaryTree._buildNodeDisplay(line2, line2.length, emptyDisplayLayout, emptyDisplayLayout);
|
|
8686
|
+
}
|
|
8687
|
+
const line = node === void 0 ? "U" : "N";
|
|
8688
|
+
return _BinaryTree._buildNodeDisplay(line, line.length, [[""], 1, 0, 0], [[""], 1, 0, 0]);
|
|
8383
8689
|
}
|
|
8384
8690
|
/**
|
|
8385
8691
|
* (Protected) Swaps the key/value properties of two nodes.
|
|
@@ -9385,9 +9691,15 @@ var BST = class extends BinaryTree {
|
|
|
9385
9691
|
if (a < b) return -1;
|
|
9386
9692
|
return 0;
|
|
9387
9693
|
}
|
|
9694
|
+
if (a instanceof Date && b instanceof Date) {
|
|
9695
|
+
const ta = a.getTime();
|
|
9696
|
+
const tb = b.getTime();
|
|
9697
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("BST"));
|
|
9698
|
+
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
9699
|
+
}
|
|
9388
9700
|
if (typeof a === "object" || typeof b === "object") {
|
|
9389
|
-
throw TypeError(
|
|
9390
|
-
|
|
9701
|
+
throw new TypeError(
|
|
9702
|
+
ERR.comparatorRequired("BST")
|
|
9391
9703
|
);
|
|
9392
9704
|
}
|
|
9393
9705
|
return 0;
|
|
@@ -9899,7 +10211,7 @@ var BinaryIndexedTree = class {
|
|
|
9899
10211
|
*/
|
|
9900
10212
|
read(count) {
|
|
9901
10213
|
if (!Number.isInteger(count)) {
|
|
9902
|
-
throw new Error("
|
|
10214
|
+
throw new Error(ERR.invalidArgument("count must be an integer", "BinaryIndexedTree"));
|
|
9903
10215
|
}
|
|
9904
10216
|
return this._read(Math.max(Math.min(count, this.max), 0));
|
|
9905
10217
|
}
|
|
@@ -9911,7 +10223,7 @@ var BinaryIndexedTree = class {
|
|
|
9911
10223
|
*/
|
|
9912
10224
|
lowerBound(sum) {
|
|
9913
10225
|
if (this.negativeCount > 0) {
|
|
9914
|
-
throw new Error("Sequence is not non-descending");
|
|
10226
|
+
throw new Error(ERR.invalidOperation("Sequence is not non-descending.", "BinaryIndexedTree"));
|
|
9915
10227
|
}
|
|
9916
10228
|
return this._binarySearch(sum, (x, y) => x < y);
|
|
9917
10229
|
}
|
|
@@ -9924,7 +10236,7 @@ var BinaryIndexedTree = class {
|
|
|
9924
10236
|
*/
|
|
9925
10237
|
upperBound(sum) {
|
|
9926
10238
|
if (this.negativeCount > 0) {
|
|
9927
|
-
throw new Error("
|
|
10239
|
+
throw new Error(ERR.invalidOperation("Sequence must not be descending.", "BinaryIndexedTree"));
|
|
9928
10240
|
}
|
|
9929
10241
|
return this._binarySearch(sum, (x, y) => x <= y);
|
|
9930
10242
|
}
|
|
@@ -9975,10 +10287,10 @@ var BinaryIndexedTree = class {
|
|
|
9975
10287
|
*/
|
|
9976
10288
|
_checkIndex(index) {
|
|
9977
10289
|
if (!Number.isInteger(index)) {
|
|
9978
|
-
throw new
|
|
10290
|
+
throw new TypeError(ERR.invalidIndex("BinaryIndexedTree"));
|
|
9979
10291
|
}
|
|
9980
10292
|
if (index < 0 || index >= this.max) {
|
|
9981
|
-
throw new
|
|
10293
|
+
throw new RangeError(ERR.indexOutOfRange(index, 0, this.max - 1, "BinaryIndexedTree"));
|
|
9982
10294
|
}
|
|
9983
10295
|
}
|
|
9984
10296
|
/**
|
|
@@ -11570,6 +11882,24 @@ var RedBlackTree = class extends BST {
|
|
|
11570
11882
|
* @param [thisArg] - See parameter type for details.
|
|
11571
11883
|
* @returns A new RedBlackTree with mapped entries.
|
|
11572
11884
|
*/
|
|
11885
|
+
/**
|
|
11886
|
+
* Red-Black trees are self-balancing — `perfectlyBalance` rebuilds via
|
|
11887
|
+
* sorted bulk insert, which naturally produces a balanced RBT.
|
|
11888
|
+
* @remarks Time O(N), Space O(N)
|
|
11889
|
+
*/
|
|
11890
|
+
perfectlyBalance(iterationType) {
|
|
11891
|
+
const entries = [];
|
|
11892
|
+
for (const [key, value] of this) entries.push([key, value]);
|
|
11893
|
+
if (entries.length <= 1) return true;
|
|
11894
|
+
this.clear();
|
|
11895
|
+
this.setMany(
|
|
11896
|
+
entries.map(([k]) => k),
|
|
11897
|
+
entries.map(([, v]) => v),
|
|
11898
|
+
true
|
|
11899
|
+
// isBalanceAdd
|
|
11900
|
+
);
|
|
11901
|
+
return true;
|
|
11902
|
+
}
|
|
11573
11903
|
map(callback, options, thisArg) {
|
|
11574
11904
|
const out = this._createLike([], options);
|
|
11575
11905
|
let index = 0;
|
|
@@ -11891,7 +12221,7 @@ var TreeSet = class _TreeSet {
|
|
|
11891
12221
|
static createDefaultComparator() {
|
|
11892
12222
|
return (a, b) => {
|
|
11893
12223
|
if (typeof a === "number" && typeof b === "number") {
|
|
11894
|
-
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError("TreeSet
|
|
12224
|
+
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("TreeSet"));
|
|
11895
12225
|
const aa = Object.is(a, -0) ? 0 : a;
|
|
11896
12226
|
const bb = Object.is(b, -0) ? 0 : b;
|
|
11897
12227
|
return aa > bb ? 1 : aa < bb ? -1 : 0;
|
|
@@ -11902,10 +12232,10 @@ var TreeSet = class _TreeSet {
|
|
|
11902
12232
|
if (a instanceof Date && b instanceof Date) {
|
|
11903
12233
|
const ta = a.getTime();
|
|
11904
12234
|
const tb = b.getTime();
|
|
11905
|
-
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError("TreeSet
|
|
12235
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("TreeSet"));
|
|
11906
12236
|
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
11907
12237
|
}
|
|
11908
|
-
throw new TypeError("TreeSet
|
|
12238
|
+
throw new TypeError(ERR.comparatorRequired("TreeSet"));
|
|
11909
12239
|
};
|
|
11910
12240
|
}
|
|
11911
12241
|
/**
|
|
@@ -11923,15 +12253,15 @@ var TreeSet = class _TreeSet {
|
|
|
11923
12253
|
_validateKey(key) {
|
|
11924
12254
|
if (!this.#isDefaultComparator) return;
|
|
11925
12255
|
if (typeof key === "number") {
|
|
11926
|
-
if (Number.isNaN(key)) throw new TypeError("TreeSet
|
|
12256
|
+
if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeSet"));
|
|
11927
12257
|
return;
|
|
11928
12258
|
}
|
|
11929
12259
|
if (typeof key === "string") return;
|
|
11930
12260
|
if (key instanceof Date) {
|
|
11931
|
-
if (Number.isNaN(key.getTime())) throw new TypeError("TreeSet
|
|
12261
|
+
if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeSet"));
|
|
11932
12262
|
return;
|
|
11933
12263
|
}
|
|
11934
|
-
throw new TypeError("TreeSet
|
|
12264
|
+
throw new TypeError(ERR.comparatorRequired("TreeSet"));
|
|
11935
12265
|
}
|
|
11936
12266
|
/**
|
|
11937
12267
|
* Add a key to the set (no-op if already present).
|
|
@@ -12250,15 +12580,15 @@ var TreeMultiMap = class _TreeMultiMap {
|
|
|
12250
12580
|
_validateKey(key) {
|
|
12251
12581
|
if (!this.#isDefaultComparator) return;
|
|
12252
12582
|
if (typeof key === "number") {
|
|
12253
|
-
if (Number.isNaN(key)) throw new TypeError("TreeMultiMap
|
|
12583
|
+
if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMultiMap"));
|
|
12254
12584
|
return;
|
|
12255
12585
|
}
|
|
12256
12586
|
if (typeof key === "string") return;
|
|
12257
12587
|
if (key instanceof Date) {
|
|
12258
|
-
if (Number.isNaN(key.getTime())) throw new TypeError("TreeMultiMap
|
|
12588
|
+
if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMultiMap"));
|
|
12259
12589
|
return;
|
|
12260
12590
|
}
|
|
12261
|
-
throw new TypeError("TreeMultiMap
|
|
12591
|
+
throw new TypeError(ERR.comparatorRequired("TreeMultiMap"));
|
|
12262
12592
|
}
|
|
12263
12593
|
/**
|
|
12264
12594
|
* Number of distinct keys.
|
|
@@ -12680,7 +13010,7 @@ var TreeMap = class _TreeMap {
|
|
|
12680
13010
|
[k, v] = toEntryFn(item);
|
|
12681
13011
|
} else {
|
|
12682
13012
|
if (!Array.isArray(item) || item.length < 2) {
|
|
12683
|
-
throw new TypeError("TreeMap
|
|
13013
|
+
throw new TypeError(ERR.invalidEntry("TreeMap"));
|
|
12684
13014
|
}
|
|
12685
13015
|
k = item[0];
|
|
12686
13016
|
v = item[1];
|
|
@@ -12701,7 +13031,7 @@ var TreeMap = class _TreeMap {
|
|
|
12701
13031
|
static createDefaultComparator() {
|
|
12702
13032
|
return (a, b) => {
|
|
12703
13033
|
if (typeof a === "number" && typeof b === "number") {
|
|
12704
|
-
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError("TreeMap
|
|
13034
|
+
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("TreeMap"));
|
|
12705
13035
|
const aa = Object.is(a, -0) ? 0 : a;
|
|
12706
13036
|
const bb = Object.is(b, -0) ? 0 : b;
|
|
12707
13037
|
return aa > bb ? 1 : aa < bb ? -1 : 0;
|
|
@@ -12712,24 +13042,24 @@ var TreeMap = class _TreeMap {
|
|
|
12712
13042
|
if (a instanceof Date && b instanceof Date) {
|
|
12713
13043
|
const ta = a.getTime();
|
|
12714
13044
|
const tb = b.getTime();
|
|
12715
|
-
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError("TreeMap
|
|
13045
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("TreeMap"));
|
|
12716
13046
|
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
12717
13047
|
}
|
|
12718
|
-
throw new TypeError("TreeMap
|
|
13048
|
+
throw new TypeError(ERR.comparatorRequired("TreeMap"));
|
|
12719
13049
|
};
|
|
12720
13050
|
}
|
|
12721
13051
|
_validateKey(key) {
|
|
12722
13052
|
if (!this.#isDefaultComparator) return;
|
|
12723
13053
|
if (typeof key === "number") {
|
|
12724
|
-
if (Number.isNaN(key)) throw new TypeError("TreeMap
|
|
13054
|
+
if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMap"));
|
|
12725
13055
|
return;
|
|
12726
13056
|
}
|
|
12727
13057
|
if (typeof key === "string") return;
|
|
12728
13058
|
if (key instanceof Date) {
|
|
12729
|
-
if (Number.isNaN(key.getTime())) throw new TypeError("TreeMap
|
|
13059
|
+
if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMap"));
|
|
12730
13060
|
return;
|
|
12731
13061
|
}
|
|
12732
|
-
throw new TypeError("TreeMap
|
|
13062
|
+
throw new TypeError(ERR.comparatorRequired("TreeMap"));
|
|
12733
13063
|
}
|
|
12734
13064
|
/**
|
|
12735
13065
|
* Number of entries in the map.
|
|
@@ -13053,22 +13383,22 @@ var TreeMultiSet = class _TreeMultiSet {
|
|
|
13053
13383
|
_validateKey(key) {
|
|
13054
13384
|
if (!this.#isDefaultComparator) return;
|
|
13055
13385
|
if (typeof key === "number") {
|
|
13056
|
-
if (Number.isNaN(key)) throw new TypeError("TreeMultiSet
|
|
13386
|
+
if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMultiSet"));
|
|
13057
13387
|
return;
|
|
13058
13388
|
}
|
|
13059
13389
|
if (typeof key === "string") return;
|
|
13060
13390
|
if (key instanceof Date) {
|
|
13061
|
-
if (Number.isNaN(key.getTime())) throw new TypeError("TreeMultiSet
|
|
13391
|
+
if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMultiSet"));
|
|
13062
13392
|
return;
|
|
13063
13393
|
}
|
|
13064
|
-
throw new TypeError("TreeMultiSet
|
|
13394
|
+
throw new TypeError(ERR.comparatorRequired("TreeMultiSet"));
|
|
13065
13395
|
}
|
|
13066
13396
|
/**
|
|
13067
13397
|
* Validates that count is a non-negative safe integer.
|
|
13068
13398
|
* @remarks Time O(1), Space O(1)
|
|
13069
13399
|
*/
|
|
13070
13400
|
_validateCount(n) {
|
|
13071
|
-
if (!Number.isSafeInteger(n) || n < 0) throw new RangeError("
|
|
13401
|
+
if (!Number.isSafeInteger(n) || n < 0) throw new RangeError(ERR.invalidArgument("count must be a safe integer >= 0.", "TreeMultiSet"));
|
|
13072
13402
|
}
|
|
13073
13403
|
/**
|
|
13074
13404
|
* Total occurrences (sumCounts).
|
|
@@ -13492,9 +13822,7 @@ var MaxPriorityQueue = class extends PriorityQueue {
|
|
|
13492
13822
|
super(elements, {
|
|
13493
13823
|
comparator: /* @__PURE__ */ __name((a, b) => {
|
|
13494
13824
|
if (typeof a === "object" || typeof b === "object") {
|
|
13495
|
-
throw TypeError(
|
|
13496
|
-
`When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
|
|
13497
|
-
);
|
|
13825
|
+
throw new TypeError(ERR.comparatorRequired("MaxPriorityQueue"));
|
|
13498
13826
|
}
|
|
13499
13827
|
if (a < b) return 1;
|
|
13500
13828
|
if (a > b) return -1;
|
|
@@ -13635,7 +13963,7 @@ var Matrix = class _Matrix {
|
|
|
13635
13963
|
*/
|
|
13636
13964
|
add(matrix) {
|
|
13637
13965
|
if (!this.isMatchForCalculate(matrix)) {
|
|
13638
|
-
throw new Error("
|
|
13966
|
+
throw new Error(ERR.matrixDimensionMismatch("addition"));
|
|
13639
13967
|
}
|
|
13640
13968
|
const resultData = [];
|
|
13641
13969
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -13667,7 +13995,7 @@ var Matrix = class _Matrix {
|
|
|
13667
13995
|
*/
|
|
13668
13996
|
subtract(matrix) {
|
|
13669
13997
|
if (!this.isMatchForCalculate(matrix)) {
|
|
13670
|
-
throw new Error("
|
|
13998
|
+
throw new Error(ERR.matrixDimensionMismatch("subtraction"));
|
|
13671
13999
|
}
|
|
13672
14000
|
const resultData = [];
|
|
13673
14001
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -13698,7 +14026,7 @@ var Matrix = class _Matrix {
|
|
|
13698
14026
|
*/
|
|
13699
14027
|
multiply(matrix) {
|
|
13700
14028
|
if (this.cols !== matrix.rows) {
|
|
13701
|
-
throw new Error("
|
|
14029
|
+
throw new Error(ERR.matrixDimensionMismatch("multiplication (A.cols must equal B.rows)"));
|
|
13702
14030
|
}
|
|
13703
14031
|
const resultData = [];
|
|
13704
14032
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -13732,7 +14060,7 @@ var Matrix = class _Matrix {
|
|
|
13732
14060
|
*/
|
|
13733
14061
|
transpose() {
|
|
13734
14062
|
if (this.data.some((row) => row.length !== this.rows)) {
|
|
13735
|
-
throw new Error(
|
|
14063
|
+
throw new Error(ERR.matrixNotRectangular());
|
|
13736
14064
|
}
|
|
13737
14065
|
const resultData = [];
|
|
13738
14066
|
for (let j = 0; j < this.cols; j++) {
|
|
@@ -13756,7 +14084,7 @@ var Matrix = class _Matrix {
|
|
|
13756
14084
|
*/
|
|
13757
14085
|
inverse() {
|
|
13758
14086
|
if (this.rows !== this.cols) {
|
|
13759
|
-
throw new Error(
|
|
14087
|
+
throw new Error(ERR.matrixNotSquare());
|
|
13760
14088
|
}
|
|
13761
14089
|
const augmentedMatrixData = [];
|
|
13762
14090
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -13778,12 +14106,12 @@ var Matrix = class _Matrix {
|
|
|
13778
14106
|
pivotRow++;
|
|
13779
14107
|
}
|
|
13780
14108
|
if (pivotRow === this.rows) {
|
|
13781
|
-
throw new Error(
|
|
14109
|
+
throw new Error(ERR.matrixSingular());
|
|
13782
14110
|
}
|
|
13783
14111
|
augmentedMatrix._swapRows(i, pivotRow);
|
|
13784
14112
|
const pivotElement = augmentedMatrix.get(i, i) ?? 1;
|
|
13785
14113
|
if (pivotElement === 0) {
|
|
13786
|
-
throw new Error(
|
|
14114
|
+
throw new Error(ERR.matrixSingular());
|
|
13787
14115
|
}
|
|
13788
14116
|
augmentedMatrix._scaleRow(i, 1 / pivotElement);
|
|
13789
14117
|
for (let j = 0; j < this.rows; j++) {
|
|
@@ -13813,9 +14141,7 @@ var Matrix = class _Matrix {
|
|
|
13813
14141
|
*/
|
|
13814
14142
|
dot(matrix) {
|
|
13815
14143
|
if (this.cols !== matrix.rows) {
|
|
13816
|
-
throw new Error(
|
|
13817
|
-
"Number of columns in the first matrix must be equal to the number of rows in the second matrix for dot product."
|
|
13818
|
-
);
|
|
14144
|
+
throw new Error(ERR.matrixDimensionMismatch("dot product (A.cols must equal B.rows)"));
|
|
13819
14145
|
}
|
|
13820
14146
|
const resultData = [];
|
|
13821
14147
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -14441,7 +14767,7 @@ var Trie = class extends IterableElementBase {
|
|
|
14441
14767
|
for (const x of this) {
|
|
14442
14768
|
const v = thisArg === void 0 ? callback(x, i++, this) : callback.call(thisArg, x, i++, this);
|
|
14443
14769
|
if (typeof v !== "string") {
|
|
14444
|
-
throw new TypeError(
|
|
14770
|
+
throw new TypeError(ERR.callbackReturnType("string", typeof v, "Trie.map"));
|
|
14445
14771
|
}
|
|
14446
14772
|
newTrie.add(v);
|
|
14447
14773
|
}
|
|
@@ -14691,6 +15017,7 @@ exports.DirectedGraph = DirectedGraph;
|
|
|
14691
15017
|
exports.DirectedVertex = DirectedVertex;
|
|
14692
15018
|
exports.DoublyLinkedList = DoublyLinkedList;
|
|
14693
15019
|
exports.DoublyLinkedListNode = DoublyLinkedListNode;
|
|
15020
|
+
exports.ERR = ERR;
|
|
14694
15021
|
exports.FibonacciHeap = FibonacciHeap;
|
|
14695
15022
|
exports.FibonacciHeapNode = FibonacciHeapNode;
|
|
14696
15023
|
exports.HashMap = HashMap;
|