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
|
@@ -193,6 +193,54 @@ var _IterableEntryBase = class _IterableEntryBase {
|
|
|
193
193
|
__name(_IterableEntryBase, "IterableEntryBase");
|
|
194
194
|
var IterableEntryBase = _IterableEntryBase;
|
|
195
195
|
|
|
196
|
+
// src/common/error.ts
|
|
197
|
+
var ERR = {
|
|
198
|
+
// Range / index
|
|
199
|
+
indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
|
|
200
|
+
invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
|
|
201
|
+
// Type / argument
|
|
202
|
+
invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
|
|
203
|
+
comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
|
|
204
|
+
invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
|
|
205
|
+
notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
|
|
206
|
+
invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
|
|
207
|
+
invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
|
|
208
|
+
invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
|
|
209
|
+
reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
|
|
210
|
+
callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
|
|
211
|
+
// State / operation
|
|
212
|
+
invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
|
|
213
|
+
// Matrix
|
|
214
|
+
matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
|
|
215
|
+
matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
|
|
216
|
+
matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
|
|
217
|
+
matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
|
|
218
|
+
matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
// src/common/index.ts
|
|
222
|
+
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
223
|
+
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
224
|
+
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
225
|
+
return DFSOperation2;
|
|
226
|
+
})(DFSOperation || {});
|
|
227
|
+
var _Range = class _Range {
|
|
228
|
+
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
229
|
+
this.low = low;
|
|
230
|
+
this.high = high;
|
|
231
|
+
this.includeLow = includeLow;
|
|
232
|
+
this.includeHigh = includeHigh;
|
|
233
|
+
}
|
|
234
|
+
// Determine whether a key is within the range
|
|
235
|
+
isInRange(key, comparator) {
|
|
236
|
+
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
237
|
+
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
238
|
+
return lowCheck && highCheck;
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
__name(_Range, "Range");
|
|
242
|
+
var Range = _Range;
|
|
243
|
+
|
|
196
244
|
// src/data-structures/base/iterable-element-base.ts
|
|
197
245
|
var _IterableElementBase = class _IterableElementBase {
|
|
198
246
|
/**
|
|
@@ -215,7 +263,7 @@ var _IterableElementBase = class _IterableElementBase {
|
|
|
215
263
|
if (options) {
|
|
216
264
|
const { toElementFn } = options;
|
|
217
265
|
if (typeof toElementFn === "function") this._toElementFn = toElementFn;
|
|
218
|
-
else if (toElementFn) throw new TypeError("toElementFn
|
|
266
|
+
else if (toElementFn) throw new TypeError(ERR.notAFunction("toElementFn"));
|
|
219
267
|
}
|
|
220
268
|
}
|
|
221
269
|
/**
|
|
@@ -371,7 +419,7 @@ var _IterableElementBase = class _IterableElementBase {
|
|
|
371
419
|
acc = initialValue;
|
|
372
420
|
} else {
|
|
373
421
|
const first = iter.next();
|
|
374
|
-
if (first.done) throw new TypeError(
|
|
422
|
+
if (first.done) throw new TypeError(ERR.reduceEmpty());
|
|
375
423
|
acc = first.value;
|
|
376
424
|
index = 1;
|
|
377
425
|
}
|
|
@@ -441,8 +489,10 @@ var getMSB = /* @__PURE__ */ __name((value) => {
|
|
|
441
489
|
}
|
|
442
490
|
return 1 << 31 - Math.clz32(value);
|
|
443
491
|
}, "getMSB");
|
|
444
|
-
var rangeCheck = /* @__PURE__ */ __name((index, min, max, message
|
|
445
|
-
if (index < min || index > max)
|
|
492
|
+
var rangeCheck = /* @__PURE__ */ __name((index, min, max, message) => {
|
|
493
|
+
if (index < min || index > max) {
|
|
494
|
+
throw new RangeError(message != null ? message : `Index ${index} is out of range [${min}, ${max}].`);
|
|
495
|
+
}
|
|
446
496
|
}, "rangeCheck");
|
|
447
497
|
var throwRangeError = /* @__PURE__ */ __name((message = "The value is off-limits.") => {
|
|
448
498
|
throw new RangeError(message);
|
|
@@ -814,8 +864,8 @@ var _LinkedHashMap = class _LinkedHashMap extends IterableEntryBase {
|
|
|
814
864
|
if (this.isEntry(rawElement)) {
|
|
815
865
|
return rawElement;
|
|
816
866
|
}
|
|
817
|
-
throw new
|
|
818
|
-
"If
|
|
867
|
+
throw new TypeError(
|
|
868
|
+
ERR.invalidArgument("If elements do not adhere to [key, value], provide options.toEntryFn to transform raw records.", "HashMap")
|
|
819
869
|
);
|
|
820
870
|
}, "_toEntryFn"));
|
|
821
871
|
__publicField(this, "_size", 0);
|
|
@@ -1100,6 +1150,13 @@ var _LinkedHashMap = class _LinkedHashMap extends IterableEntryBase {
|
|
|
1100
1150
|
}
|
|
1101
1151
|
}
|
|
1102
1152
|
_deleteNode(node) {
|
|
1153
|
+
const key = node.key;
|
|
1154
|
+
if (isWeakKey(key)) {
|
|
1155
|
+
this._objMap.delete(key);
|
|
1156
|
+
} else {
|
|
1157
|
+
const hash = this._hashFn(key);
|
|
1158
|
+
delete this._noObjMap[hash];
|
|
1159
|
+
}
|
|
1103
1160
|
const { prev, next } = node;
|
|
1104
1161
|
prev.next = next;
|
|
1105
1162
|
next.prev = prev;
|
|
@@ -3607,17 +3664,16 @@ var LinkedListQueue = _LinkedListQueue;
|
|
|
3607
3664
|
|
|
3608
3665
|
// src/data-structures/queue/deque.ts
|
|
3609
3666
|
var _Deque = class _Deque extends LinearBase {
|
|
3610
|
-
/**
|
|
3611
|
-
* Create a Deque and optionally bulk-insert elements.
|
|
3612
|
-
* @remarks Time O(N), Space O(N)
|
|
3613
|
-
* @param [elements] - Iterable (or iterable-like) of elements/records to insert.
|
|
3614
|
-
* @param [options] - Options such as bucketSize, toElementFn, and maxLen.
|
|
3615
|
-
* @returns New Deque instance.
|
|
3616
|
-
*/
|
|
3617
3667
|
constructor(elements = [], options) {
|
|
3618
3668
|
super(options);
|
|
3619
3669
|
__publicField(this, "_equals", /* @__PURE__ */ __name((a, b) => Object.is(a, b), "_equals"));
|
|
3620
3670
|
__publicField(this, "_bucketSize", 1 << 12);
|
|
3671
|
+
__publicField(this, "_autoCompactRatio", 0.5);
|
|
3672
|
+
/**
|
|
3673
|
+
* Counter for shift/pop operations since last compaction check.
|
|
3674
|
+
* Only checks ratio every `_bucketSize` operations to minimize overhead.
|
|
3675
|
+
*/
|
|
3676
|
+
__publicField(this, "_compactCounter", 0);
|
|
3621
3677
|
__publicField(this, "_bucketFirst", 0);
|
|
3622
3678
|
__publicField(this, "_firstInBucket", 0);
|
|
3623
3679
|
__publicField(this, "_bucketLast", 0);
|
|
@@ -3626,8 +3682,9 @@ var _Deque = class _Deque extends LinearBase {
|
|
|
3626
3682
|
__publicField(this, "_buckets", []);
|
|
3627
3683
|
__publicField(this, "_length", 0);
|
|
3628
3684
|
if (options) {
|
|
3629
|
-
const { bucketSize } = options;
|
|
3685
|
+
const { bucketSize, autoCompactRatio } = options;
|
|
3630
3686
|
if (typeof bucketSize === "number") this._bucketSize = bucketSize;
|
|
3687
|
+
if (typeof autoCompactRatio === "number") this._autoCompactRatio = autoCompactRatio;
|
|
3631
3688
|
}
|
|
3632
3689
|
let _size;
|
|
3633
3690
|
if ("length" in elements) {
|
|
@@ -3652,6 +3709,24 @@ var _Deque = class _Deque extends LinearBase {
|
|
|
3652
3709
|
get bucketSize() {
|
|
3653
3710
|
return this._bucketSize;
|
|
3654
3711
|
}
|
|
3712
|
+
/**
|
|
3713
|
+
* Get the auto-compaction ratio.
|
|
3714
|
+
* When `elements / (bucketCount * bucketSize)` drops below this ratio after
|
|
3715
|
+
* enough shift/pop operations, the deque auto-compacts.
|
|
3716
|
+
* @remarks Time O(1), Space O(1)
|
|
3717
|
+
* @returns Current ratio threshold. 0 means auto-compact is disabled.
|
|
3718
|
+
*/
|
|
3719
|
+
get autoCompactRatio() {
|
|
3720
|
+
return this._autoCompactRatio;
|
|
3721
|
+
}
|
|
3722
|
+
/**
|
|
3723
|
+
* Set the auto-compaction ratio.
|
|
3724
|
+
* @remarks Time O(1), Space O(1)
|
|
3725
|
+
* @param value - Ratio in [0,1]. 0 disables auto-compact.
|
|
3726
|
+
*/
|
|
3727
|
+
set autoCompactRatio(value) {
|
|
3728
|
+
this._autoCompactRatio = value;
|
|
3729
|
+
}
|
|
3655
3730
|
/**
|
|
3656
3731
|
* Get the index of the first bucket in use.
|
|
3657
3732
|
* @remarks Time O(1), Space O(1)
|
|
@@ -3783,6 +3858,7 @@ var _Deque = class _Deque extends LinearBase {
|
|
|
3783
3858
|
}
|
|
3784
3859
|
}
|
|
3785
3860
|
this._length -= 1;
|
|
3861
|
+
this._autoCompact();
|
|
3786
3862
|
return element;
|
|
3787
3863
|
}
|
|
3788
3864
|
/**
|
|
@@ -3805,6 +3881,7 @@ var _Deque = class _Deque extends LinearBase {
|
|
|
3805
3881
|
}
|
|
3806
3882
|
}
|
|
3807
3883
|
this._length -= 1;
|
|
3884
|
+
this._autoCompact();
|
|
3808
3885
|
return element;
|
|
3809
3886
|
}
|
|
3810
3887
|
/**
|
|
@@ -4137,11 +4214,40 @@ var _Deque = class _Deque extends LinearBase {
|
|
|
4137
4214
|
* @remarks Time O(N), Space O(1)
|
|
4138
4215
|
* @returns void
|
|
4139
4216
|
*/
|
|
4217
|
+
/**
|
|
4218
|
+
* (Protected) Trigger auto-compaction if space utilization drops below threshold.
|
|
4219
|
+
* Only checks every `_bucketSize` operations to minimize hot-path overhead.
|
|
4220
|
+
* Uses element-based ratio: `elements / (bucketCount * bucketSize)`.
|
|
4221
|
+
*/
|
|
4222
|
+
_autoCompact() {
|
|
4223
|
+
if (this._autoCompactRatio <= 0 || this._bucketCount <= 1) return;
|
|
4224
|
+
this._compactCounter++;
|
|
4225
|
+
if (this._compactCounter < this._bucketSize) return;
|
|
4226
|
+
this._compactCounter = 0;
|
|
4227
|
+
const utilization = this._length / (this._bucketCount * this._bucketSize);
|
|
4228
|
+
if (utilization < this._autoCompactRatio) {
|
|
4229
|
+
this.shrinkToFit();
|
|
4230
|
+
}
|
|
4231
|
+
}
|
|
4232
|
+
/**
|
|
4233
|
+
* Compact the deque by removing unused buckets.
|
|
4234
|
+
* @remarks Time O(N), Space O(1)
|
|
4235
|
+
* @returns True if compaction was performed (bucket count reduced).
|
|
4236
|
+
*/
|
|
4237
|
+
/**
|
|
4238
|
+
* Compact the deque by removing unused buckets.
|
|
4239
|
+
* @remarks Time O(N), Space O(1)
|
|
4240
|
+
* @returns True if compaction was performed (bucket count reduced).
|
|
4241
|
+
*/
|
|
4242
|
+
compact() {
|
|
4243
|
+
const before = this._bucketCount;
|
|
4244
|
+
this.shrinkToFit();
|
|
4245
|
+
return this._bucketCount < before;
|
|
4246
|
+
}
|
|
4140
4247
|
shrinkToFit() {
|
|
4141
4248
|
if (this._length === 0) return;
|
|
4142
4249
|
const newBuckets = [];
|
|
4143
|
-
if (this._bucketFirst
|
|
4144
|
-
else if (this._bucketFirst < this._bucketLast) {
|
|
4250
|
+
if (this._bucketFirst <= this._bucketLast) {
|
|
4145
4251
|
for (let i = this._bucketFirst; i <= this._bucketLast; ++i) {
|
|
4146
4252
|
newBuckets.push(this._buckets[i]);
|
|
4147
4253
|
}
|
|
@@ -4156,6 +4262,8 @@ var _Deque = class _Deque extends LinearBase {
|
|
|
4156
4262
|
this._bucketFirst = 0;
|
|
4157
4263
|
this._bucketLast = newBuckets.length - 1;
|
|
4158
4264
|
this._buckets = newBuckets;
|
|
4265
|
+
this._bucketCount = newBuckets.length;
|
|
4266
|
+
this._compactCounter = 0;
|
|
4159
4267
|
}
|
|
4160
4268
|
/**
|
|
4161
4269
|
* Deep clone this deque, preserving options.
|
|
@@ -4353,7 +4461,7 @@ var _Heap = class _Heap extends IterableElementBase {
|
|
|
4353
4461
|
__publicField(this, "_elements", []);
|
|
4354
4462
|
__publicField(this, "_DEFAULT_COMPARATOR", /* @__PURE__ */ __name((a, b) => {
|
|
4355
4463
|
if (typeof a === "object" || typeof b === "object") {
|
|
4356
|
-
throw TypeError(
|
|
4464
|
+
throw new TypeError(ERR.comparatorRequired("Heap"));
|
|
4357
4465
|
}
|
|
4358
4466
|
if (a > b) return 1;
|
|
4359
4467
|
if (a < b) return -1;
|
|
@@ -4663,7 +4771,7 @@ var _Heap = class _Heap extends IterableElementBase {
|
|
|
4663
4771
|
*/
|
|
4664
4772
|
map(callback, options, thisArg) {
|
|
4665
4773
|
const { comparator, toElementFn, ...rest } = options != null ? options : {};
|
|
4666
|
-
if (!comparator) throw new TypeError("Heap.map
|
|
4774
|
+
if (!comparator) throw new TypeError(ERR.comparatorRequired("Heap.map"));
|
|
4667
4775
|
const out = this._createLike([], { ...rest, comparator, toElementFn });
|
|
4668
4776
|
let i = 0;
|
|
4669
4777
|
for (const x of this) {
|
|
@@ -4795,7 +4903,7 @@ var _FibonacciHeap = class _FibonacciHeap {
|
|
|
4795
4903
|
__publicField(this, "_comparator");
|
|
4796
4904
|
this.clear();
|
|
4797
4905
|
this._comparator = comparator || this._defaultComparator;
|
|
4798
|
-
if (typeof this.comparator !== "function") throw new
|
|
4906
|
+
if (typeof this.comparator !== "function") throw new TypeError(ERR.notAFunction("comparator", "FibonacciHeap"));
|
|
4799
4907
|
}
|
|
4800
4908
|
/**
|
|
4801
4909
|
* Get the circular root list head.
|
|
@@ -5006,9 +5114,7 @@ var _MaxHeap = class _MaxHeap extends Heap {
|
|
|
5006
5114
|
super(elements, {
|
|
5007
5115
|
comparator: /* @__PURE__ */ __name((a, b) => {
|
|
5008
5116
|
if (typeof a === "object" || typeof b === "object") {
|
|
5009
|
-
throw TypeError(
|
|
5010
|
-
`When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
|
|
5011
|
-
);
|
|
5117
|
+
throw new TypeError(ERR.comparatorRequired("MaxHeap"));
|
|
5012
5118
|
}
|
|
5013
5119
|
if (a < b) return 1;
|
|
5014
5120
|
if (a > b) return -1;
|
|
@@ -5173,7 +5279,7 @@ var _AbstractGraph = class _AbstractGraph extends IterableEntryBase {
|
|
|
5173
5279
|
const newEdge = this.createEdge(srcOrEdge, dest, weight, value);
|
|
5174
5280
|
return this._addEdge(newEdge);
|
|
5175
5281
|
} else {
|
|
5176
|
-
throw new
|
|
5282
|
+
throw new TypeError(ERR.invalidArgument("dest must be a Vertex or vertex key when srcOrEdge is an Edge.", "Graph"));
|
|
5177
5283
|
}
|
|
5178
5284
|
}
|
|
5179
5285
|
}
|
|
@@ -5857,6 +5963,94 @@ var _AbstractGraph = class _AbstractGraph extends IterableEntryBase {
|
|
|
5857
5963
|
_getVertexKey(vertexOrKey) {
|
|
5858
5964
|
return vertexOrKey instanceof AbstractVertex ? vertexOrKey.key : vertexOrKey;
|
|
5859
5965
|
}
|
|
5966
|
+
/**
|
|
5967
|
+
* The edge connector string used in visual output.
|
|
5968
|
+
* Override in subclasses (e.g., '--' for undirected, '->' for directed).
|
|
5969
|
+
*/
|
|
5970
|
+
get _edgeConnector() {
|
|
5971
|
+
return "--";
|
|
5972
|
+
}
|
|
5973
|
+
/**
|
|
5974
|
+
* Generate a text-based visual representation of the graph.
|
|
5975
|
+
*
|
|
5976
|
+
* **Adjacency list format:**
|
|
5977
|
+
* ```
|
|
5978
|
+
* Graph (5 vertices, 6 edges):
|
|
5979
|
+
* A -> B (1), C (2)
|
|
5980
|
+
* B -> D (3)
|
|
5981
|
+
* C -> (no outgoing edges)
|
|
5982
|
+
* D -> A (1)
|
|
5983
|
+
* E (isolated)
|
|
5984
|
+
* ```
|
|
5985
|
+
*
|
|
5986
|
+
* @param options - Optional display settings.
|
|
5987
|
+
* @param options.showWeight - Whether to show edge weights (default: true).
|
|
5988
|
+
* @returns The visual string.
|
|
5989
|
+
*/
|
|
5990
|
+
toVisual(options) {
|
|
5991
|
+
var _a;
|
|
5992
|
+
const showWeight = (_a = options == null ? void 0 : options.showWeight) != null ? _a : true;
|
|
5993
|
+
const vertices = [...this._vertexMap.values()];
|
|
5994
|
+
const vertexCount = vertices.length;
|
|
5995
|
+
const edgeCount = this.edgeSet().length;
|
|
5996
|
+
const lines = [`Graph (${vertexCount} vertices, ${edgeCount} edges):`];
|
|
5997
|
+
for (const vertex of vertices) {
|
|
5998
|
+
const neighbors = this.getNeighbors(vertex);
|
|
5999
|
+
if (neighbors.length === 0) {
|
|
6000
|
+
lines.push(` ${vertex.key} (isolated)`);
|
|
6001
|
+
} else {
|
|
6002
|
+
const edgeStrs = neighbors.map((neighbor) => {
|
|
6003
|
+
const edge = this.getEdge(vertex, neighbor);
|
|
6004
|
+
if (edge && showWeight && edge.weight !== void 0 && edge.weight !== 1) {
|
|
6005
|
+
return `${neighbor.key} (${edge.weight})`;
|
|
6006
|
+
}
|
|
6007
|
+
return `${neighbor.key}`;
|
|
6008
|
+
});
|
|
6009
|
+
lines.push(` ${vertex.key} ${this._edgeConnector} ${edgeStrs.join(", ")}`);
|
|
6010
|
+
}
|
|
6011
|
+
}
|
|
6012
|
+
return lines.join("\n");
|
|
6013
|
+
}
|
|
6014
|
+
/**
|
|
6015
|
+
* Generate DOT language representation for Graphviz.
|
|
6016
|
+
*
|
|
6017
|
+
* @param options - Optional display settings.
|
|
6018
|
+
* @param options.name - Graph name (default: 'G').
|
|
6019
|
+
* @param options.showWeight - Whether to label edges with weight (default: true).
|
|
6020
|
+
* @returns DOT format string.
|
|
6021
|
+
*/
|
|
6022
|
+
toDot(options) {
|
|
6023
|
+
var _a, _b;
|
|
6024
|
+
const name = (_a = options == null ? void 0 : options.name) != null ? _a : "G";
|
|
6025
|
+
const showWeight = (_b = options == null ? void 0 : options.showWeight) != null ? _b : true;
|
|
6026
|
+
const isDirected = this._edgeConnector === "->";
|
|
6027
|
+
const graphType = isDirected ? "digraph" : "graph";
|
|
6028
|
+
const edgeOp = isDirected ? "->" : "--";
|
|
6029
|
+
const lines = [`${graphType} ${name} {`];
|
|
6030
|
+
for (const vertex of this._vertexMap.values()) {
|
|
6031
|
+
lines.push(` "${vertex.key}";`);
|
|
6032
|
+
}
|
|
6033
|
+
const visited = /* @__PURE__ */ new Set();
|
|
6034
|
+
for (const vertex of this._vertexMap.values()) {
|
|
6035
|
+
for (const neighbor of this.getNeighbors(vertex)) {
|
|
6036
|
+
const edgeId = isDirected ? `${vertex.key}->${neighbor.key}` : [vertex.key, neighbor.key].sort().join("--");
|
|
6037
|
+
if (visited.has(edgeId)) continue;
|
|
6038
|
+
visited.add(edgeId);
|
|
6039
|
+
const edge = this.getEdge(vertex, neighbor);
|
|
6040
|
+
const label = edge && showWeight && edge.weight !== void 0 && edge.weight !== 1 ? ` [label="${edge.weight}"]` : "";
|
|
6041
|
+
lines.push(` "${vertex.key}" ${edgeOp} "${neighbor.key}"${label};`);
|
|
6042
|
+
}
|
|
6043
|
+
}
|
|
6044
|
+
lines.push("}");
|
|
6045
|
+
return lines.join("\n");
|
|
6046
|
+
}
|
|
6047
|
+
/**
|
|
6048
|
+
* Print the graph to console.
|
|
6049
|
+
* @param options - Display settings passed to `toVisual`.
|
|
6050
|
+
*/
|
|
6051
|
+
print(options) {
|
|
6052
|
+
console.log(this.toVisual(options));
|
|
6053
|
+
}
|
|
5860
6054
|
};
|
|
5861
6055
|
__name(_AbstractGraph, "AbstractGraph");
|
|
5862
6056
|
var AbstractGraph = _AbstractGraph;
|
|
@@ -5891,6 +6085,9 @@ var _DirectedGraph = class _DirectedGraph extends AbstractGraph {
|
|
|
5891
6085
|
__publicField(this, "_outEdgeMap", /* @__PURE__ */ new Map());
|
|
5892
6086
|
__publicField(this, "_inEdgeMap", /* @__PURE__ */ new Map());
|
|
5893
6087
|
}
|
|
6088
|
+
get _edgeConnector() {
|
|
6089
|
+
return "->";
|
|
6090
|
+
}
|
|
5894
6091
|
get outEdgeMap() {
|
|
5895
6092
|
return this._outEdgeMap;
|
|
5896
6093
|
}
|
|
@@ -6671,6 +6868,84 @@ var _UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
|
|
|
6671
6868
|
cutVertices
|
|
6672
6869
|
};
|
|
6673
6870
|
}
|
|
6871
|
+
/**
|
|
6872
|
+
* Find biconnected components using edge-stack Tarjan variant.
|
|
6873
|
+
* A biconnected component is a maximal biconnected subgraph.
|
|
6874
|
+
* @returns Array of edge arrays, each representing a biconnected component.
|
|
6875
|
+
* @remarks Time O(V + E), Space O(V + E)
|
|
6876
|
+
*/
|
|
6877
|
+
getBiconnectedComponents() {
|
|
6878
|
+
const dfn = /* @__PURE__ */ new Map();
|
|
6879
|
+
const low = /* @__PURE__ */ new Map();
|
|
6880
|
+
const edgeStack = [];
|
|
6881
|
+
const components = [];
|
|
6882
|
+
let time = 0;
|
|
6883
|
+
const dfs = /* @__PURE__ */ __name((vertex, parent) => {
|
|
6884
|
+
dfn.set(vertex, time);
|
|
6885
|
+
low.set(vertex, time);
|
|
6886
|
+
time++;
|
|
6887
|
+
const neighbors = this.getNeighbors(vertex);
|
|
6888
|
+
let childCount = 0;
|
|
6889
|
+
for (const neighbor of neighbors) {
|
|
6890
|
+
const edge = this.getEdge(vertex, neighbor);
|
|
6891
|
+
if (!edge) continue;
|
|
6892
|
+
if (!dfn.has(neighbor)) {
|
|
6893
|
+
childCount++;
|
|
6894
|
+
edgeStack.push(edge);
|
|
6895
|
+
dfs(neighbor, vertex);
|
|
6896
|
+
low.set(vertex, Math.min(low.get(vertex), low.get(neighbor)));
|
|
6897
|
+
if (parent === void 0 && childCount > 1 || parent !== void 0 && low.get(neighbor) >= dfn.get(vertex)) {
|
|
6898
|
+
const component = [];
|
|
6899
|
+
let e;
|
|
6900
|
+
do {
|
|
6901
|
+
e = edgeStack.pop();
|
|
6902
|
+
if (e) component.push(e);
|
|
6903
|
+
} while (e && e !== edge);
|
|
6904
|
+
if (component.length > 0) components.push(component);
|
|
6905
|
+
}
|
|
6906
|
+
} else if (neighbor !== parent && dfn.get(neighbor) < dfn.get(vertex)) {
|
|
6907
|
+
edgeStack.push(edge);
|
|
6908
|
+
low.set(vertex, Math.min(low.get(vertex), dfn.get(neighbor)));
|
|
6909
|
+
}
|
|
6910
|
+
}
|
|
6911
|
+
}, "dfs");
|
|
6912
|
+
for (const vertex of this.vertexMap.values()) {
|
|
6913
|
+
if (!dfn.has(vertex)) {
|
|
6914
|
+
dfs(vertex, void 0);
|
|
6915
|
+
if (edgeStack.length > 0) {
|
|
6916
|
+
components.push([...edgeStack]);
|
|
6917
|
+
edgeStack.length = 0;
|
|
6918
|
+
}
|
|
6919
|
+
}
|
|
6920
|
+
}
|
|
6921
|
+
return components;
|
|
6922
|
+
}
|
|
6923
|
+
/**
|
|
6924
|
+
* Detect whether the graph contains a cycle.
|
|
6925
|
+
* Uses DFS with parent tracking.
|
|
6926
|
+
* @returns `true` if a cycle exists, `false` otherwise.
|
|
6927
|
+
* @remarks Time O(V + E), Space O(V)
|
|
6928
|
+
*/
|
|
6929
|
+
hasCycle() {
|
|
6930
|
+
const visited = /* @__PURE__ */ new Set();
|
|
6931
|
+
const dfs = /* @__PURE__ */ __name((vertex, parent) => {
|
|
6932
|
+
visited.add(vertex);
|
|
6933
|
+
for (const neighbor of this.getNeighbors(vertex)) {
|
|
6934
|
+
if (!visited.has(neighbor)) {
|
|
6935
|
+
if (dfs(neighbor, vertex)) return true;
|
|
6936
|
+
} else if (neighbor !== parent) {
|
|
6937
|
+
return true;
|
|
6938
|
+
}
|
|
6939
|
+
}
|
|
6940
|
+
return false;
|
|
6941
|
+
}, "dfs");
|
|
6942
|
+
for (const vertex of this.vertexMap.values()) {
|
|
6943
|
+
if (!visited.has(vertex)) {
|
|
6944
|
+
if (dfs(vertex, void 0)) return true;
|
|
6945
|
+
}
|
|
6946
|
+
}
|
|
6947
|
+
return false;
|
|
6948
|
+
}
|
|
6674
6949
|
/**
|
|
6675
6950
|
* Get bridges discovered by `tarjan()`.
|
|
6676
6951
|
* @returns Array of edges that are bridges.
|
|
@@ -6823,29 +7098,6 @@ var _MapGraph = class _MapGraph extends DirectedGraph {
|
|
|
6823
7098
|
__name(_MapGraph, "MapGraph");
|
|
6824
7099
|
var MapGraph = _MapGraph;
|
|
6825
7100
|
|
|
6826
|
-
// src/common/index.ts
|
|
6827
|
-
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
6828
|
-
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
6829
|
-
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
6830
|
-
return DFSOperation2;
|
|
6831
|
-
})(DFSOperation || {});
|
|
6832
|
-
var _Range = class _Range {
|
|
6833
|
-
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
6834
|
-
this.low = low;
|
|
6835
|
-
this.high = high;
|
|
6836
|
-
this.includeLow = includeLow;
|
|
6837
|
-
this.includeHigh = includeHigh;
|
|
6838
|
-
}
|
|
6839
|
-
// Determine whether a key is within the range
|
|
6840
|
-
isInRange(key, comparator) {
|
|
6841
|
-
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
6842
|
-
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
6843
|
-
return lowCheck && highCheck;
|
|
6844
|
-
}
|
|
6845
|
-
};
|
|
6846
|
-
__name(_Range, "Range");
|
|
6847
|
-
var Range = _Range;
|
|
6848
|
-
|
|
6849
7101
|
// src/data-structures/binary-tree/binary-tree.ts
|
|
6850
7102
|
var _BinaryTreeNode = class _BinaryTreeNode {
|
|
6851
7103
|
/**
|
|
@@ -7018,7 +7270,7 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
7018
7270
|
if (isMapMode !== void 0) this._isMapMode = isMapMode;
|
|
7019
7271
|
if (isDuplicate !== void 0) this._isDuplicate = isDuplicate;
|
|
7020
7272
|
if (typeof toEntryFn === "function") this._toEntryFn = toEntryFn;
|
|
7021
|
-
else if (toEntryFn) throw TypeError("toEntryFn
|
|
7273
|
+
else if (toEntryFn) throw new TypeError(ERR.notAFunction("toEntryFn", "BinaryTree"));
|
|
7022
7274
|
}
|
|
7023
7275
|
if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
|
|
7024
7276
|
}
|
|
@@ -7246,7 +7498,7 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
7246
7498
|
if (!this._root) {
|
|
7247
7499
|
this._setRoot(newNode);
|
|
7248
7500
|
if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
|
|
7249
|
-
this._size = 1;
|
|
7501
|
+
if (newNode !== null) this._size = 1;
|
|
7250
7502
|
return true;
|
|
7251
7503
|
}
|
|
7252
7504
|
const queue = new Queue([this._root]);
|
|
@@ -7278,7 +7530,7 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
7278
7530
|
potentialParent.right = newNode;
|
|
7279
7531
|
}
|
|
7280
7532
|
if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
|
|
7281
|
-
this._size++;
|
|
7533
|
+
if (newNode !== null) this._size++;
|
|
7282
7534
|
return true;
|
|
7283
7535
|
}
|
|
7284
7536
|
return false;
|
|
@@ -7847,7 +8099,7 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
7847
8099
|
}
|
|
7848
8100
|
/**
|
|
7849
8101
|
* Finds all leaf nodes in the tree.
|
|
7850
|
-
* @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.
|
|
7851
8103
|
*
|
|
7852
8104
|
* @template C - The type of the callback function.
|
|
7853
8105
|
* @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each leaf node.
|
|
@@ -7870,15 +8122,15 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
7870
8122
|
}, "dfs");
|
|
7871
8123
|
dfs(startNode);
|
|
7872
8124
|
} else {
|
|
7873
|
-
const
|
|
7874
|
-
while (
|
|
7875
|
-
const cur =
|
|
8125
|
+
const stack = [startNode];
|
|
8126
|
+
while (stack.length > 0) {
|
|
8127
|
+
const cur = stack.pop();
|
|
7876
8128
|
if (this.isRealNode(cur)) {
|
|
7877
8129
|
if (this.isLeaf(cur)) {
|
|
7878
8130
|
leaves.push(callback(cur));
|
|
7879
8131
|
}
|
|
7880
|
-
if (this.isRealNode(cur.
|
|
7881
|
-
if (this.isRealNode(cur.
|
|
8132
|
+
if (this.isRealNode(cur.right)) stack.push(cur.right);
|
|
8133
|
+
if (this.isRealNode(cur.left)) stack.push(cur.left);
|
|
7882
8134
|
}
|
|
7883
8135
|
}
|
|
7884
8136
|
}
|
|
@@ -8334,42 +8586,98 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
8334
8586
|
_displayAux(node, options) {
|
|
8335
8587
|
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
8336
8588
|
const emptyDisplayLayout = [["\u2500"], 1, 0, 0];
|
|
8337
|
-
|
|
8338
|
-
|
|
8339
|
-
|
|
8340
|
-
|
|
8341
|
-
|
|
8342
|
-
|
|
8343
|
-
|
|
8344
|
-
|
|
8345
|
-
|
|
8346
|
-
|
|
8347
|
-
|
|
8348
|
-
|
|
8349
|
-
|
|
8350
|
-
|
|
8351
|
-
|
|
8352
|
-
|
|
8353
|
-
|
|
8354
|
-
|
|
8355
|
-
|
|
8356
|
-
const
|
|
8357
|
-
|
|
8358
|
-
|
|
8359
|
-
|
|
8360
|
-
|
|
8361
|
-
|
|
8362
|
-
|
|
8363
|
-
|
|
8364
|
-
|
|
8589
|
+
const newFrame = /* @__PURE__ */ __name((n) => ({
|
|
8590
|
+
node: n,
|
|
8591
|
+
stage: 0,
|
|
8592
|
+
leftLayout: emptyDisplayLayout,
|
|
8593
|
+
rightLayout: emptyDisplayLayout
|
|
8594
|
+
}), "newFrame");
|
|
8595
|
+
const stack = [newFrame(node)];
|
|
8596
|
+
let result = emptyDisplayLayout;
|
|
8597
|
+
const setChildResult = /* @__PURE__ */ __name((layout) => {
|
|
8598
|
+
if (stack.length === 0) {
|
|
8599
|
+
result = layout;
|
|
8600
|
+
return;
|
|
8601
|
+
}
|
|
8602
|
+
const parent = stack[stack.length - 1];
|
|
8603
|
+
if (parent.stage === 1) parent.leftLayout = layout;
|
|
8604
|
+
else parent.rightLayout = layout;
|
|
8605
|
+
}, "setChildResult");
|
|
8606
|
+
while (stack.length > 0) {
|
|
8607
|
+
const frame = stack[stack.length - 1];
|
|
8608
|
+
const cur = frame.node;
|
|
8609
|
+
if (frame.stage === 0) {
|
|
8610
|
+
if (this._isDisplayLeaf(cur, options)) {
|
|
8611
|
+
stack.pop();
|
|
8612
|
+
const layout = this._resolveDisplayLeaf(cur, options, emptyDisplayLayout);
|
|
8613
|
+
setChildResult(layout);
|
|
8614
|
+
continue;
|
|
8615
|
+
}
|
|
8616
|
+
frame.stage = 1;
|
|
8617
|
+
stack.push(newFrame(cur.left));
|
|
8618
|
+
} else if (frame.stage === 1) {
|
|
8619
|
+
frame.stage = 2;
|
|
8620
|
+
stack.push(newFrame(cur.right));
|
|
8621
|
+
} else {
|
|
8622
|
+
stack.pop();
|
|
8623
|
+
const line = this.isNIL(cur) ? "S" : String(cur.key);
|
|
8624
|
+
const layout = _BinaryTree._buildNodeDisplay(line, line.length, frame.leftLayout, frame.rightLayout);
|
|
8625
|
+
setChildResult(layout);
|
|
8365
8626
|
}
|
|
8366
|
-
return [
|
|
8367
|
-
mergedLines,
|
|
8368
|
-
leftWidth + width + rightWidth,
|
|
8369
|
-
Math.max(leftHeight, rightHeight) + 2,
|
|
8370
|
-
leftWidth + Math.floor(width / 2)
|
|
8371
|
-
];
|
|
8372
8627
|
}
|
|
8628
|
+
return result;
|
|
8629
|
+
}
|
|
8630
|
+
static _buildNodeDisplay(line, width, left, right) {
|
|
8631
|
+
const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
|
|
8632
|
+
const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
|
|
8633
|
+
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));
|
|
8634
|
+
const secondLine = (leftHeight > 0 ? " ".repeat(leftMiddle) + "/" + " ".repeat(leftWidth - leftMiddle - 1) : " ".repeat(leftWidth)) + " ".repeat(width) + (rightHeight > 0 ? " ".repeat(rightMiddle) + "\\" + " ".repeat(rightWidth - rightMiddle - 1) : " ".repeat(rightWidth));
|
|
8635
|
+
const mergedLines = [firstLine, secondLine];
|
|
8636
|
+
for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
|
|
8637
|
+
const leftLine = i < leftHeight ? leftLines[i] : " ".repeat(leftWidth);
|
|
8638
|
+
const rightLine = i < rightHeight ? rightLines[i] : " ".repeat(rightWidth);
|
|
8639
|
+
mergedLines.push(leftLine + " ".repeat(width) + rightLine);
|
|
8640
|
+
}
|
|
8641
|
+
return [
|
|
8642
|
+
mergedLines,
|
|
8643
|
+
leftWidth + width + rightWidth,
|
|
8644
|
+
Math.max(leftHeight, rightHeight) + 2,
|
|
8645
|
+
leftWidth + Math.floor(width / 2)
|
|
8646
|
+
];
|
|
8647
|
+
}
|
|
8648
|
+
/**
|
|
8649
|
+
* Check if a node is a display leaf (empty, null, undefined, NIL, or real leaf).
|
|
8650
|
+
*/
|
|
8651
|
+
_isDisplayLeaf(node, options) {
|
|
8652
|
+
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
8653
|
+
if (node === null && !isShowNull) return true;
|
|
8654
|
+
if (node === void 0 && !isShowUndefined) return true;
|
|
8655
|
+
if (this.isNIL(node) && !isShowRedBlackNIL) return true;
|
|
8656
|
+
if (node === null || node === void 0) return true;
|
|
8657
|
+
const hasDisplayableLeft = this._hasDisplayableChild(node.left, options);
|
|
8658
|
+
const hasDisplayableRight = this._hasDisplayableChild(node.right, options);
|
|
8659
|
+
return !hasDisplayableLeft && !hasDisplayableRight;
|
|
8660
|
+
}
|
|
8661
|
+
_hasDisplayableChild(child, options) {
|
|
8662
|
+
if (child === null) return !!options.isShowNull;
|
|
8663
|
+
if (child === void 0) return !!options.isShowUndefined;
|
|
8664
|
+
if (this.isNIL(child)) return !!options.isShowRedBlackNIL;
|
|
8665
|
+
return true;
|
|
8666
|
+
}
|
|
8667
|
+
/**
|
|
8668
|
+
* Resolve a display leaf node to its layout.
|
|
8669
|
+
*/
|
|
8670
|
+
_resolveDisplayLeaf(node, options, emptyDisplayLayout) {
|
|
8671
|
+
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
8672
|
+
if (node === null && !isShowNull) return emptyDisplayLayout;
|
|
8673
|
+
if (node === void 0 && !isShowUndefined) return emptyDisplayLayout;
|
|
8674
|
+
if (this.isNIL(node) && !isShowRedBlackNIL) return emptyDisplayLayout;
|
|
8675
|
+
if (node !== null && node !== void 0) {
|
|
8676
|
+
const line2 = this.isNIL(node) ? "S" : String(node.key);
|
|
8677
|
+
return _BinaryTree._buildNodeDisplay(line2, line2.length, emptyDisplayLayout, emptyDisplayLayout);
|
|
8678
|
+
}
|
|
8679
|
+
const line = node === void 0 ? "U" : "N";
|
|
8680
|
+
return _BinaryTree._buildNodeDisplay(line, line.length, [[""], 1, 0, 0], [[""], 1, 0, 0]);
|
|
8373
8681
|
}
|
|
8374
8682
|
/**
|
|
8375
8683
|
* (Protected) Swaps the key/value properties of two nodes.
|
|
@@ -9375,9 +9683,15 @@ var _BST = class _BST extends BinaryTree {
|
|
|
9375
9683
|
if (a < b) return -1;
|
|
9376
9684
|
return 0;
|
|
9377
9685
|
}
|
|
9686
|
+
if (a instanceof Date && b instanceof Date) {
|
|
9687
|
+
const ta = a.getTime();
|
|
9688
|
+
const tb = b.getTime();
|
|
9689
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("BST"));
|
|
9690
|
+
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
9691
|
+
}
|
|
9378
9692
|
if (typeof a === "object" || typeof b === "object") {
|
|
9379
|
-
throw TypeError(
|
|
9380
|
-
|
|
9693
|
+
throw new TypeError(
|
|
9694
|
+
ERR.comparatorRequired("BST")
|
|
9381
9695
|
);
|
|
9382
9696
|
}
|
|
9383
9697
|
return 0;
|
|
@@ -9891,7 +10205,7 @@ var _BinaryIndexedTree = class _BinaryIndexedTree {
|
|
|
9891
10205
|
*/
|
|
9892
10206
|
read(count) {
|
|
9893
10207
|
if (!Number.isInteger(count)) {
|
|
9894
|
-
throw new Error("
|
|
10208
|
+
throw new Error(ERR.invalidArgument("count must be an integer", "BinaryIndexedTree"));
|
|
9895
10209
|
}
|
|
9896
10210
|
return this._read(Math.max(Math.min(count, this.max), 0));
|
|
9897
10211
|
}
|
|
@@ -9903,7 +10217,7 @@ var _BinaryIndexedTree = class _BinaryIndexedTree {
|
|
|
9903
10217
|
*/
|
|
9904
10218
|
lowerBound(sum) {
|
|
9905
10219
|
if (this.negativeCount > 0) {
|
|
9906
|
-
throw new Error("Sequence is not non-descending");
|
|
10220
|
+
throw new Error(ERR.invalidOperation("Sequence is not non-descending.", "BinaryIndexedTree"));
|
|
9907
10221
|
}
|
|
9908
10222
|
return this._binarySearch(sum, (x, y) => x < y);
|
|
9909
10223
|
}
|
|
@@ -9916,7 +10230,7 @@ var _BinaryIndexedTree = class _BinaryIndexedTree {
|
|
|
9916
10230
|
*/
|
|
9917
10231
|
upperBound(sum) {
|
|
9918
10232
|
if (this.negativeCount > 0) {
|
|
9919
|
-
throw new Error("
|
|
10233
|
+
throw new Error(ERR.invalidOperation("Sequence must not be descending.", "BinaryIndexedTree"));
|
|
9920
10234
|
}
|
|
9921
10235
|
return this._binarySearch(sum, (x, y) => x <= y);
|
|
9922
10236
|
}
|
|
@@ -9967,10 +10281,10 @@ var _BinaryIndexedTree = class _BinaryIndexedTree {
|
|
|
9967
10281
|
*/
|
|
9968
10282
|
_checkIndex(index) {
|
|
9969
10283
|
if (!Number.isInteger(index)) {
|
|
9970
|
-
throw new
|
|
10284
|
+
throw new TypeError(ERR.invalidIndex("BinaryIndexedTree"));
|
|
9971
10285
|
}
|
|
9972
10286
|
if (index < 0 || index >= this.max) {
|
|
9973
|
-
throw new
|
|
10287
|
+
throw new RangeError(ERR.indexOutOfRange(index, 0, this.max - 1, "BinaryIndexedTree"));
|
|
9974
10288
|
}
|
|
9975
10289
|
}
|
|
9976
10290
|
/**
|
|
@@ -11559,6 +11873,24 @@ var _RedBlackTree = class _RedBlackTree extends BST {
|
|
|
11559
11873
|
* @param [thisArg] - See parameter type for details.
|
|
11560
11874
|
* @returns A new RedBlackTree with mapped entries.
|
|
11561
11875
|
*/
|
|
11876
|
+
/**
|
|
11877
|
+
* Red-Black trees are self-balancing — `perfectlyBalance` rebuilds via
|
|
11878
|
+
* sorted bulk insert, which naturally produces a balanced RBT.
|
|
11879
|
+
* @remarks Time O(N), Space O(N)
|
|
11880
|
+
*/
|
|
11881
|
+
perfectlyBalance(iterationType) {
|
|
11882
|
+
const entries = [];
|
|
11883
|
+
for (const [key, value] of this) entries.push([key, value]);
|
|
11884
|
+
if (entries.length <= 1) return true;
|
|
11885
|
+
this.clear();
|
|
11886
|
+
this.setMany(
|
|
11887
|
+
entries.map(([k]) => k),
|
|
11888
|
+
entries.map(([, v]) => v),
|
|
11889
|
+
true
|
|
11890
|
+
// isBalanceAdd
|
|
11891
|
+
);
|
|
11892
|
+
return true;
|
|
11893
|
+
}
|
|
11562
11894
|
map(callback, options, thisArg) {
|
|
11563
11895
|
const out = this._createLike([], options);
|
|
11564
11896
|
let index = 0;
|
|
@@ -11883,7 +12215,7 @@ var _TreeSet = class _TreeSet {
|
|
|
11883
12215
|
static createDefaultComparator() {
|
|
11884
12216
|
return (a, b) => {
|
|
11885
12217
|
if (typeof a === "number" && typeof b === "number") {
|
|
11886
|
-
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError("TreeSet
|
|
12218
|
+
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("TreeSet"));
|
|
11887
12219
|
const aa = Object.is(a, -0) ? 0 : a;
|
|
11888
12220
|
const bb = Object.is(b, -0) ? 0 : b;
|
|
11889
12221
|
return aa > bb ? 1 : aa < bb ? -1 : 0;
|
|
@@ -11894,10 +12226,10 @@ var _TreeSet = class _TreeSet {
|
|
|
11894
12226
|
if (a instanceof Date && b instanceof Date) {
|
|
11895
12227
|
const ta = a.getTime();
|
|
11896
12228
|
const tb = b.getTime();
|
|
11897
|
-
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError("TreeSet
|
|
12229
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("TreeSet"));
|
|
11898
12230
|
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
11899
12231
|
}
|
|
11900
|
-
throw new TypeError("TreeSet
|
|
12232
|
+
throw new TypeError(ERR.comparatorRequired("TreeSet"));
|
|
11901
12233
|
};
|
|
11902
12234
|
}
|
|
11903
12235
|
/**
|
|
@@ -11915,15 +12247,15 @@ var _TreeSet = class _TreeSet {
|
|
|
11915
12247
|
_validateKey(key) {
|
|
11916
12248
|
if (!__privateGet(this, _isDefaultComparator)) return;
|
|
11917
12249
|
if (typeof key === "number") {
|
|
11918
|
-
if (Number.isNaN(key)) throw new TypeError("TreeSet
|
|
12250
|
+
if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeSet"));
|
|
11919
12251
|
return;
|
|
11920
12252
|
}
|
|
11921
12253
|
if (typeof key === "string") return;
|
|
11922
12254
|
if (key instanceof Date) {
|
|
11923
|
-
if (Number.isNaN(key.getTime())) throw new TypeError("TreeSet
|
|
12255
|
+
if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeSet"));
|
|
11924
12256
|
return;
|
|
11925
12257
|
}
|
|
11926
|
-
throw new TypeError("TreeSet
|
|
12258
|
+
throw new TypeError(ERR.comparatorRequired("TreeSet"));
|
|
11927
12259
|
}
|
|
11928
12260
|
/**
|
|
11929
12261
|
* Add a key to the set (no-op if already present).
|
|
@@ -12246,15 +12578,15 @@ var _TreeMultiMap = class _TreeMultiMap {
|
|
|
12246
12578
|
_validateKey(key) {
|
|
12247
12579
|
if (!__privateGet(this, _isDefaultComparator2)) return;
|
|
12248
12580
|
if (typeof key === "number") {
|
|
12249
|
-
if (Number.isNaN(key)) throw new TypeError("TreeMultiMap
|
|
12581
|
+
if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMultiMap"));
|
|
12250
12582
|
return;
|
|
12251
12583
|
}
|
|
12252
12584
|
if (typeof key === "string") return;
|
|
12253
12585
|
if (key instanceof Date) {
|
|
12254
|
-
if (Number.isNaN(key.getTime())) throw new TypeError("TreeMultiMap
|
|
12586
|
+
if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMultiMap"));
|
|
12255
12587
|
return;
|
|
12256
12588
|
}
|
|
12257
|
-
throw new TypeError("TreeMultiMap
|
|
12589
|
+
throw new TypeError(ERR.comparatorRequired("TreeMultiMap"));
|
|
12258
12590
|
}
|
|
12259
12591
|
/**
|
|
12260
12592
|
* Number of distinct keys.
|
|
@@ -12679,7 +13011,7 @@ var _TreeMap = class _TreeMap {
|
|
|
12679
13011
|
[k, v] = toEntryFn(item);
|
|
12680
13012
|
} else {
|
|
12681
13013
|
if (!Array.isArray(item) || item.length < 2) {
|
|
12682
|
-
throw new TypeError("TreeMap
|
|
13014
|
+
throw new TypeError(ERR.invalidEntry("TreeMap"));
|
|
12683
13015
|
}
|
|
12684
13016
|
k = item[0];
|
|
12685
13017
|
v = item[1];
|
|
@@ -12700,7 +13032,7 @@ var _TreeMap = class _TreeMap {
|
|
|
12700
13032
|
static createDefaultComparator() {
|
|
12701
13033
|
return (a, b) => {
|
|
12702
13034
|
if (typeof a === "number" && typeof b === "number") {
|
|
12703
|
-
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError("TreeMap
|
|
13035
|
+
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("TreeMap"));
|
|
12704
13036
|
const aa = Object.is(a, -0) ? 0 : a;
|
|
12705
13037
|
const bb = Object.is(b, -0) ? 0 : b;
|
|
12706
13038
|
return aa > bb ? 1 : aa < bb ? -1 : 0;
|
|
@@ -12711,24 +13043,24 @@ var _TreeMap = class _TreeMap {
|
|
|
12711
13043
|
if (a instanceof Date && b instanceof Date) {
|
|
12712
13044
|
const ta = a.getTime();
|
|
12713
13045
|
const tb = b.getTime();
|
|
12714
|
-
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError("TreeMap
|
|
13046
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("TreeMap"));
|
|
12715
13047
|
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
12716
13048
|
}
|
|
12717
|
-
throw new TypeError("TreeMap
|
|
13049
|
+
throw new TypeError(ERR.comparatorRequired("TreeMap"));
|
|
12718
13050
|
};
|
|
12719
13051
|
}
|
|
12720
13052
|
_validateKey(key) {
|
|
12721
13053
|
if (!__privateGet(this, _isDefaultComparator3)) return;
|
|
12722
13054
|
if (typeof key === "number") {
|
|
12723
|
-
if (Number.isNaN(key)) throw new TypeError("TreeMap
|
|
13055
|
+
if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMap"));
|
|
12724
13056
|
return;
|
|
12725
13057
|
}
|
|
12726
13058
|
if (typeof key === "string") return;
|
|
12727
13059
|
if (key instanceof Date) {
|
|
12728
|
-
if (Number.isNaN(key.getTime())) throw new TypeError("TreeMap
|
|
13060
|
+
if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMap"));
|
|
12729
13061
|
return;
|
|
12730
13062
|
}
|
|
12731
|
-
throw new TypeError("TreeMap
|
|
13063
|
+
throw new TypeError(ERR.comparatorRequired("TreeMap"));
|
|
12732
13064
|
}
|
|
12733
13065
|
/**
|
|
12734
13066
|
* Number of entries in the map.
|
|
@@ -13057,22 +13389,22 @@ var _TreeMultiSet = class _TreeMultiSet {
|
|
|
13057
13389
|
_validateKey(key) {
|
|
13058
13390
|
if (!__privateGet(this, _isDefaultComparator4)) return;
|
|
13059
13391
|
if (typeof key === "number") {
|
|
13060
|
-
if (Number.isNaN(key)) throw new TypeError("TreeMultiSet
|
|
13392
|
+
if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMultiSet"));
|
|
13061
13393
|
return;
|
|
13062
13394
|
}
|
|
13063
13395
|
if (typeof key === "string") return;
|
|
13064
13396
|
if (key instanceof Date) {
|
|
13065
|
-
if (Number.isNaN(key.getTime())) throw new TypeError("TreeMultiSet
|
|
13397
|
+
if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMultiSet"));
|
|
13066
13398
|
return;
|
|
13067
13399
|
}
|
|
13068
|
-
throw new TypeError("TreeMultiSet
|
|
13400
|
+
throw new TypeError(ERR.comparatorRequired("TreeMultiSet"));
|
|
13069
13401
|
}
|
|
13070
13402
|
/**
|
|
13071
13403
|
* Validates that count is a non-negative safe integer.
|
|
13072
13404
|
* @remarks Time O(1), Space O(1)
|
|
13073
13405
|
*/
|
|
13074
13406
|
_validateCount(n) {
|
|
13075
|
-
if (!Number.isSafeInteger(n) || n < 0) throw new RangeError("
|
|
13407
|
+
if (!Number.isSafeInteger(n) || n < 0) throw new RangeError(ERR.invalidArgument("count must be a safe integer >= 0.", "TreeMultiSet"));
|
|
13076
13408
|
}
|
|
13077
13409
|
/**
|
|
13078
13410
|
* Total occurrences (sumCounts).
|
|
@@ -13500,9 +13832,7 @@ var _MaxPriorityQueue = class _MaxPriorityQueue extends PriorityQueue {
|
|
|
13500
13832
|
super(elements, {
|
|
13501
13833
|
comparator: /* @__PURE__ */ __name((a, b) => {
|
|
13502
13834
|
if (typeof a === "object" || typeof b === "object") {
|
|
13503
|
-
throw TypeError(
|
|
13504
|
-
`When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
|
|
13505
|
-
);
|
|
13835
|
+
throw new TypeError(ERR.comparatorRequired("MaxPriorityQueue"));
|
|
13506
13836
|
}
|
|
13507
13837
|
if (a < b) return 1;
|
|
13508
13838
|
if (a > b) return -1;
|
|
@@ -13643,7 +13973,7 @@ var _Matrix = class _Matrix {
|
|
|
13643
13973
|
*/
|
|
13644
13974
|
add(matrix) {
|
|
13645
13975
|
if (!this.isMatchForCalculate(matrix)) {
|
|
13646
|
-
throw new Error("
|
|
13976
|
+
throw new Error(ERR.matrixDimensionMismatch("addition"));
|
|
13647
13977
|
}
|
|
13648
13978
|
const resultData = [];
|
|
13649
13979
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -13675,7 +14005,7 @@ var _Matrix = class _Matrix {
|
|
|
13675
14005
|
*/
|
|
13676
14006
|
subtract(matrix) {
|
|
13677
14007
|
if (!this.isMatchForCalculate(matrix)) {
|
|
13678
|
-
throw new Error("
|
|
14008
|
+
throw new Error(ERR.matrixDimensionMismatch("subtraction"));
|
|
13679
14009
|
}
|
|
13680
14010
|
const resultData = [];
|
|
13681
14011
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -13706,7 +14036,7 @@ var _Matrix = class _Matrix {
|
|
|
13706
14036
|
*/
|
|
13707
14037
|
multiply(matrix) {
|
|
13708
14038
|
if (this.cols !== matrix.rows) {
|
|
13709
|
-
throw new Error("
|
|
14039
|
+
throw new Error(ERR.matrixDimensionMismatch("multiplication (A.cols must equal B.rows)"));
|
|
13710
14040
|
}
|
|
13711
14041
|
const resultData = [];
|
|
13712
14042
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -13740,7 +14070,7 @@ var _Matrix = class _Matrix {
|
|
|
13740
14070
|
*/
|
|
13741
14071
|
transpose() {
|
|
13742
14072
|
if (this.data.some((row) => row.length !== this.rows)) {
|
|
13743
|
-
throw new Error(
|
|
14073
|
+
throw new Error(ERR.matrixNotRectangular());
|
|
13744
14074
|
}
|
|
13745
14075
|
const resultData = [];
|
|
13746
14076
|
for (let j = 0; j < this.cols; j++) {
|
|
@@ -13765,7 +14095,7 @@ var _Matrix = class _Matrix {
|
|
|
13765
14095
|
inverse() {
|
|
13766
14096
|
var _a;
|
|
13767
14097
|
if (this.rows !== this.cols) {
|
|
13768
|
-
throw new Error(
|
|
14098
|
+
throw new Error(ERR.matrixNotSquare());
|
|
13769
14099
|
}
|
|
13770
14100
|
const augmentedMatrixData = [];
|
|
13771
14101
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -13787,12 +14117,12 @@ var _Matrix = class _Matrix {
|
|
|
13787
14117
|
pivotRow++;
|
|
13788
14118
|
}
|
|
13789
14119
|
if (pivotRow === this.rows) {
|
|
13790
|
-
throw new Error(
|
|
14120
|
+
throw new Error(ERR.matrixSingular());
|
|
13791
14121
|
}
|
|
13792
14122
|
augmentedMatrix._swapRows(i, pivotRow);
|
|
13793
14123
|
const pivotElement = (_a = augmentedMatrix.get(i, i)) != null ? _a : 1;
|
|
13794
14124
|
if (pivotElement === 0) {
|
|
13795
|
-
throw new Error(
|
|
14125
|
+
throw new Error(ERR.matrixSingular());
|
|
13796
14126
|
}
|
|
13797
14127
|
augmentedMatrix._scaleRow(i, 1 / pivotElement);
|
|
13798
14128
|
for (let j = 0; j < this.rows; j++) {
|
|
@@ -13822,9 +14152,7 @@ var _Matrix = class _Matrix {
|
|
|
13822
14152
|
*/
|
|
13823
14153
|
dot(matrix) {
|
|
13824
14154
|
if (this.cols !== matrix.rows) {
|
|
13825
|
-
throw new Error(
|
|
13826
|
-
"Number of columns in the first matrix must be equal to the number of rows in the second matrix for dot product."
|
|
13827
|
-
);
|
|
14155
|
+
throw new Error(ERR.matrixDimensionMismatch("dot product (A.cols must equal B.rows)"));
|
|
13828
14156
|
}
|
|
13829
14157
|
const resultData = [];
|
|
13830
14158
|
for (let i = 0; i < this.rows; i++) {
|
|
@@ -14446,7 +14774,7 @@ var _Trie = class _Trie extends IterableElementBase {
|
|
|
14446
14774
|
for (const x of this) {
|
|
14447
14775
|
const v = thisArg === void 0 ? callback(x, i++, this) : callback.call(thisArg, x, i++, this);
|
|
14448
14776
|
if (typeof v !== "string") {
|
|
14449
|
-
throw new TypeError(
|
|
14777
|
+
throw new TypeError(ERR.callbackReturnType("string", typeof v, "Trie.map"));
|
|
14450
14778
|
}
|
|
14451
14779
|
newTrie.add(v);
|
|
14452
14780
|
}
|
|
@@ -14697,6 +15025,7 @@ exports.DirectedGraph = DirectedGraph;
|
|
|
14697
15025
|
exports.DirectedVertex = DirectedVertex;
|
|
14698
15026
|
exports.DoublyLinkedList = DoublyLinkedList;
|
|
14699
15027
|
exports.DoublyLinkedListNode = DoublyLinkedListNode;
|
|
15028
|
+
exports.ERR = ERR;
|
|
14700
15029
|
exports.FibonacciHeap = FibonacciHeap;
|
|
14701
15030
|
exports.FibonacciHeapNode = FibonacciHeapNode;
|
|
14702
15031
|
exports.HashMap = HashMap;
|