data-structure-typed 2.2.8 → 2.3.0
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/.github/workflows/ci.yml +9 -0
- package/CHANGELOG.md +1 -1
- package/README.md +1 -1
- package/README_CN.md +1 -1
- package/dist/cjs/index.cjs +584 -76
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +588 -79
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +584 -76
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +588 -79
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/data-structures/base/linear-base.d.ts +6 -6
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +3 -4
- package/dist/types/data-structures/binary-tree/bst.d.ts +2 -1
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +150 -20
- package/dist/types/data-structures/binary-tree/tree-counter.d.ts +3 -3
- package/dist/types/interfaces/binary-tree.d.ts +1 -1
- package/dist/umd/data-structure-typed.js +588 -79
- package/dist/umd/data-structure-typed.js.map +1 -1
- package/dist/umd/data-structure-typed.min.js +3 -3
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +4 -3
- package/src/data-structures/base/linear-base.ts +2 -12
- package/src/data-structures/binary-tree/binary-tree.ts +5 -6
- package/src/data-structures/binary-tree/bst.ts +79 -4
- package/src/data-structures/binary-tree/red-black-tree.ts +583 -73
- package/src/data-structures/binary-tree/tree-counter.ts +21 -9
- package/src/data-structures/queue/deque.ts +10 -0
- package/src/interfaces/binary-tree.ts +1 -1
- package/test/unit/data-structures/base/iterable-element-base.coverage.test.ts +106 -0
- package/test/unit/data-structures/base/iterable-element-base.more-branches.coverage.test.ts +61 -0
- package/test/unit/data-structures/base/linear-base.array.coverage.test.ts +168 -0
- package/test/unit/data-structures/base/linear-base.concat-else.coverage.test.ts +82 -0
- package/test/unit/data-structures/base/linear-base.coverage.test.ts +72 -0
- package/test/unit/data-structures/base/linear-base.more-branches.coverage.test.ts +417 -0
- package/test/unit/data-structures/binary-tree/avl-tree-counter.more-branches-3.coverage.test.ts +146 -0
- package/test/unit/data-structures/binary-tree/avl-tree-counter.more-branches.coverage.test.ts +93 -0
- package/test/unit/data-structures/binary-tree/avl-tree-multi-map.coverage.test.ts +108 -0
- package/test/unit/data-structures/binary-tree/avl-tree-multi-map.more-branches-2.coverage.test.ts +85 -0
- package/test/unit/data-structures/binary-tree/avl-tree-node.familyPosition-root-left.coverage.test.ts +17 -0
- package/test/unit/data-structures/binary-tree/avl-tree.more-branches-2.coverage.test.ts +99 -0
- package/test/unit/data-structures/binary-tree/binary-indexed-tree.more-branches.coverage.test.ts +18 -0
- package/test/unit/data-structures/binary-tree/binary-tree.more-branches.coverage.test.ts +56 -0
- package/test/unit/data-structures/binary-tree/binary-tree.remaining-branches.coverage.test.ts +229 -0
- package/test/unit/data-structures/binary-tree/bst.bound-by-predicate.coverage.test.ts +33 -0
- package/test/unit/data-structures/binary-tree/bst.coverage.test.ts +94 -0
- package/test/unit/data-structures/binary-tree/bst.deletebykey.coverage.test.ts +70 -0
- package/test/unit/data-structures/binary-tree/bst.deletewhere.coverage.test.ts +37 -0
- package/test/unit/data-structures/binary-tree/bst.floor-lower-predicate.coverage.test.ts +29 -0
- package/test/unit/data-structures/binary-tree/bst.floor-setmany.coverage.test.ts +72 -0
- package/test/unit/data-structures/binary-tree/bst.getnode.range-ensure.coverage.test.ts +22 -0
- package/test/unit/data-structures/binary-tree/bst.misc-branches.coverage.test.ts +100 -0
- package/test/unit/data-structures/binary-tree/bst.more-branches-2.coverage.test.ts +133 -0
- package/test/unit/data-structures/binary-tree/bst.more-branches-3.coverage.test.ts +45 -0
- package/test/unit/data-structures/binary-tree/bst.more-branches-4.coverage.test.ts +36 -0
- package/test/unit/data-structures/binary-tree/bst.more-branches-5.coverage.test.ts +40 -0
- package/test/unit/data-structures/binary-tree/bst.more.coverage.test.ts +39 -0
- package/test/unit/data-structures/binary-tree/bst.node-family.coverage.test.ts +29 -0
- package/test/unit/data-structures/binary-tree/bst.range-pruning.coverage.test.ts +43 -0
- package/test/unit/data-structures/binary-tree/bst.search-fastpath.coverage.test.ts +30 -0
- package/test/unit/data-structures/binary-tree/bst.test.ts +25 -55
- package/test/unit/data-structures/binary-tree/red-black-tree.boundary-corruption-repair.coverage.test.ts +66 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.boundary-max-update.coverage.test.ts +18 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.boundary-null.coverage.test.ts +53 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.boundary-stale-cache.coverage.test.ts +25 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.boundary-update.coverage.test.ts +23 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.cache-delete.coverage.test.ts +49 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.cache-edge.coverage.test.ts +37 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.cache-stale-insert.coverage.test.ts +39 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.coverage.test.ts +334 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.delete-fixup.coverage.test.ts +68 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.delete-successor.coverage.test.ts +75 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.factories.coverage.test.ts +26 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-compare-update.coverage.test.ts +74 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-no-update.coverage.test.ts +44 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-nullish.coverage.test.ts +61 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-mapmode-defined.coverage.test.ts +35 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-mapmode-undefined.coverage.test.ts +43 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-more.coverage.test.ts +99 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint.coverage.test.ts +60 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.insert-cache-nullish.coverage.test.ts +29 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.insert-header-parent-nullish.coverage.test.ts +17 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.internal-walk.coverage.test.ts +57 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.minmax-cache.test.ts +65 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.misc-inputs.coverage.test.ts +17 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-2.coverage.test.ts +121 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-3.coverage.test.ts +55 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-4.coverage.test.ts +44 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.predsucc.coverage.test.ts +40 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.remaining-branches.coverage.test.ts +123 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.set-inputs.coverage.test.ts +64 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-parent-cache.coverage.test.ts +79 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-remaining.coverage.test.ts +44 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-uncovered.coverage.test.ts +74 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.update-branches.coverage.test.ts +30 -0
- package/test/unit/data-structures/binary-tree/segment-tree.more-branches.coverage.test.ts +31 -0
- package/test/unit/data-structures/binary-tree/tree-counter.coverage.test.ts +115 -0
- package/test/unit/data-structures/binary-tree/tree-counter.more-branches.coverage.test.ts +244 -0
- package/test/unit/data-structures/binary-tree/tree-counter.test.ts +4 -2
- package/test/unit/data-structures/binary-tree/tree-multi-map.coverage.test.ts +104 -0
- package/test/unit/data-structures/binary-tree/tree-multi-map.more-branches-2.coverage.test.ts +59 -0
- package/test/unit/data-structures/graph/abstract-graph.more-branches-2.coverage.test.ts +40 -0
- package/test/unit/data-structures/graph/abstract-graph.more-branches-3.coverage.test.ts +65 -0
- package/test/unit/data-structures/graph/abstract-graph.more-branches-4.coverage.test.ts +98 -0
- package/test/unit/data-structures/graph/abstract-graph.more-branches-5.coverage.test.ts +51 -0
- package/test/unit/data-structures/graph/abstract-graph.more-branches.coverage.test.ts +62 -0
- package/test/unit/data-structures/graph/directed-graph.more-branches-2.coverage.test.ts +38 -0
- package/test/unit/data-structures/graph/directed-graph.more-branches-3.coverage.test.ts +25 -0
- package/test/unit/data-structures/graph/directed-graph.more-branches.coverage.test.ts +82 -0
- package/test/unit/data-structures/graph/map-graph.more-branches.coverage.test.ts +22 -0
- package/test/unit/data-structures/graph/undirected-graph.more-branches-2.coverage.test.ts +35 -0
- package/test/unit/data-structures/graph/undirected-graph.more-branches.coverage.test.ts +87 -0
- package/test/unit/data-structures/hash/hash-map.more-branches.coverage.test.ts +64 -0
- package/test/unit/data-structures/hash/hash-map.toEntryFn-branch.coverage.test.ts +9 -0
- package/test/unit/data-structures/heap/heap.misc-branches.coverage.test.ts +110 -0
- package/test/unit/data-structures/heap/heap.remaining-branches.coverage.test.ts +22 -0
- package/test/unit/data-structures/heap/max-heap.coverage.test.ts +29 -0
- package/test/unit/data-structures/linked-list/doubly-linked-list.more-branches.coverage.test.ts +72 -0
- package/test/unit/data-structures/linked-list/linked-list.unshiftMany-else.coverage.test.ts +15 -0
- package/test/unit/data-structures/linked-list/singly-linked-list.coverage.test.ts +221 -0
- package/test/unit/data-structures/linked-list/singly-linked-list.more-branches.coverage.test.ts +86 -0
- package/test/unit/data-structures/linked-list/skip-linked-list.more-branches.coverage.test.ts +31 -0
- package/test/unit/data-structures/matrix/matrix.more-branches.coverage.test.ts +81 -0
- package/test/unit/data-structures/matrix/matrix.pivotElement-nullish.coverage.test.ts +28 -0
- package/test/unit/data-structures/priority-queue/max-priority-queue.more-branches.coverage.test.ts +10 -0
- package/test/unit/data-structures/priority-queue/priority-queue.coverage.test.ts +21 -0
- package/test/unit/data-structures/queue/deque.coverage.test.ts +173 -0
- package/test/unit/data-structures/queue/deque.more-branches-2.coverage.test.ts +39 -0
- package/test/unit/data-structures/queue/deque.more-branches-3.coverage.test.ts +9 -0
- package/test/unit/data-structures/queue/deque.more-branches.coverage.test.ts +95 -0
- package/test/unit/data-structures/queue/queue.coverage.test.ts +138 -0
- package/test/unit/data-structures/queue/queue.more-branches-2.coverage.test.ts +27 -0
- package/test/unit/data-structures/stack/stack.coverage.test.ts +112 -0
- package/test/unit/data-structures/tree/tree.more-branches.coverage.test.ts +9 -0
- package/test/unit/data-structures/trie/trie.more-branches-2.coverage.test.ts +51 -0
- package/test/utils/patch.ts +33 -0
|
@@ -1475,6 +1475,12 @@ var dataStructureTyped = (() => {
|
|
|
1475
1475
|
}
|
|
1476
1476
|
return -1;
|
|
1477
1477
|
}
|
|
1478
|
+
/**
|
|
1479
|
+
* Concatenate lists/elements preserving order.
|
|
1480
|
+
* @param items - Elements or `LinearBase` instances.
|
|
1481
|
+
* @returns New list with combined elements (`this` type).
|
|
1482
|
+
* @remarks Time O(sum(length)), Space O(sum(length))
|
|
1483
|
+
*/
|
|
1478
1484
|
concat(...items) {
|
|
1479
1485
|
const newList = this.clone();
|
|
1480
1486
|
for (const item of items) {
|
|
@@ -4276,6 +4282,12 @@ var dataStructureTyped = (() => {
|
|
|
4276
4282
|
*/
|
|
4277
4283
|
_setBucketSize(size) {
|
|
4278
4284
|
this._bucketSize = size;
|
|
4285
|
+
if (this._length === 0) {
|
|
4286
|
+
this._buckets = [new Array(this._bucketSize)];
|
|
4287
|
+
this._bucketCount = 1;
|
|
4288
|
+
this._bucketFirst = this._bucketLast = 0;
|
|
4289
|
+
this._firstInBucket = this._lastInBucket = this._bucketSize >> 1;
|
|
4290
|
+
}
|
|
4279
4291
|
}
|
|
4280
4292
|
/**
|
|
4281
4293
|
* (Protected) Iterate elements from front to back.
|
|
@@ -7288,7 +7300,6 @@ var dataStructureTyped = (() => {
|
|
|
7288
7300
|
* @remarks Time O(N * M), where N is the number of items to set and M is the size of the tree at insertion (due to O(M) `set` operation). Space O(M) (from `set`) + O(N) (for the `inserted` array).
|
|
7289
7301
|
*
|
|
7290
7302
|
* @param keysNodesEntriesOrRaws - An iterable of items to set.
|
|
7291
|
-
* @param [values] - An optional parallel iterable of values.
|
|
7292
7303
|
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
7293
7304
|
*/
|
|
7294
7305
|
addMany(keysNodesEntriesOrRaws) {
|
|
@@ -7345,13 +7356,13 @@ var dataStructureTyped = (() => {
|
|
|
7345
7356
|
* Deletes a node from the tree.
|
|
7346
7357
|
* @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). This implementation finds the node, and if it has two children, swaps it with the rightmost node of its left subtree (in-order predecessor) before deleting. Time O(N) in the worst case. O(N) to find the node (`getNode`) and O(H) (which is O(N) worst-case) to find the rightmost node. Space O(1) (if `getNode` is iterative, which it is).
|
|
7347
7358
|
*
|
|
7348
|
-
* @param
|
|
7359
|
+
* @param keyNodeEntryRawOrPredicate - The node to delete.
|
|
7349
7360
|
* @returns An array containing deletion results (for compatibility with self-balancing trees).
|
|
7350
7361
|
*/
|
|
7351
|
-
delete(
|
|
7362
|
+
delete(keyNodeEntryRawOrPredicate) {
|
|
7352
7363
|
const deletedResult = [];
|
|
7353
7364
|
if (!this._root) return deletedResult;
|
|
7354
|
-
const curr = this.getNode(
|
|
7365
|
+
const curr = this.getNode(keyNodeEntryRawOrPredicate);
|
|
7355
7366
|
if (!curr) return deletedResult;
|
|
7356
7367
|
const parent = curr == null ? void 0 : curr.parent;
|
|
7357
7368
|
let needBalanced;
|
|
@@ -7535,7 +7546,7 @@ var dataStructureTyped = (() => {
|
|
|
7535
7546
|
}
|
|
7536
7547
|
return true;
|
|
7537
7548
|
};
|
|
7538
|
-
const isStandardBST = checkBST(
|
|
7549
|
+
const isStandardBST = checkBST();
|
|
7539
7550
|
const isInverseBST = checkBST(true);
|
|
7540
7551
|
return isStandardBST || isInverseBST;
|
|
7541
7552
|
}
|
|
@@ -8762,8 +8773,40 @@ var dataStructureTyped = (() => {
|
|
|
8762
8773
|
* @returns The first matching node, or undefined if not found.
|
|
8763
8774
|
*/
|
|
8764
8775
|
getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
8765
|
-
var _a;
|
|
8766
|
-
|
|
8776
|
+
var _a, _b;
|
|
8777
|
+
if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === void 0) return void 0;
|
|
8778
|
+
if (this._isPredicate(keyNodeEntryOrPredicate)) {
|
|
8779
|
+
return (_a = this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0]) != null ? _a : void 0;
|
|
8780
|
+
}
|
|
8781
|
+
if (keyNodeEntryOrPredicate instanceof Range) {
|
|
8782
|
+
return (_b = this.getNodes(
|
|
8783
|
+
keyNodeEntryOrPredicate,
|
|
8784
|
+
true,
|
|
8785
|
+
startNode,
|
|
8786
|
+
iterationType
|
|
8787
|
+
)[0]) != null ? _b : void 0;
|
|
8788
|
+
}
|
|
8789
|
+
let targetKey;
|
|
8790
|
+
if (this.isNode(keyNodeEntryOrPredicate)) {
|
|
8791
|
+
targetKey = keyNodeEntryOrPredicate.key;
|
|
8792
|
+
} else if (this.isEntry(keyNodeEntryOrPredicate)) {
|
|
8793
|
+
const k = keyNodeEntryOrPredicate[0];
|
|
8794
|
+
if (k === null || k === void 0) return void 0;
|
|
8795
|
+
targetKey = k;
|
|
8796
|
+
} else {
|
|
8797
|
+
targetKey = keyNodeEntryOrPredicate;
|
|
8798
|
+
}
|
|
8799
|
+
const start = this.ensureNode(startNode);
|
|
8800
|
+
if (!start) return void 0;
|
|
8801
|
+
const NIL = this._NIL;
|
|
8802
|
+
let cur = start;
|
|
8803
|
+
const cmpFn = this._comparator;
|
|
8804
|
+
while (cur && cur !== NIL) {
|
|
8805
|
+
const c = cmpFn(targetKey, cur.key);
|
|
8806
|
+
if (c === 0) return cur;
|
|
8807
|
+
cur = c < 0 ? cur._left : cur._right;
|
|
8808
|
+
}
|
|
8809
|
+
return void 0;
|
|
8767
8810
|
}
|
|
8768
8811
|
/**
|
|
8769
8812
|
* Searches the tree for nodes matching a predicate, key, or range.
|
|
@@ -8784,8 +8827,30 @@ var dataStructureTyped = (() => {
|
|
|
8784
8827
|
if (keyNodeEntryOrPredicate === null) return [];
|
|
8785
8828
|
startNode = this.ensureNode(startNode);
|
|
8786
8829
|
if (!startNode) return [];
|
|
8787
|
-
let predicate;
|
|
8788
8830
|
const isRange = this.isRange(keyNodeEntryOrPredicate);
|
|
8831
|
+
const isPred = !isRange && this._isPredicate(keyNodeEntryOrPredicate);
|
|
8832
|
+
if (!isRange && !isPred) {
|
|
8833
|
+
let targetKey;
|
|
8834
|
+
if (this.isNode(keyNodeEntryOrPredicate)) {
|
|
8835
|
+
targetKey = keyNodeEntryOrPredicate.key;
|
|
8836
|
+
} else if (this.isEntry(keyNodeEntryOrPredicate)) {
|
|
8837
|
+
const k = keyNodeEntryOrPredicate[0];
|
|
8838
|
+
if (k !== null && k !== void 0) targetKey = k;
|
|
8839
|
+
} else {
|
|
8840
|
+
targetKey = keyNodeEntryOrPredicate;
|
|
8841
|
+
}
|
|
8842
|
+
if (targetKey === void 0) return [];
|
|
8843
|
+
const NIL = this._NIL;
|
|
8844
|
+
const cmpFn = this._comparator;
|
|
8845
|
+
let cur = startNode;
|
|
8846
|
+
while (cur && cur !== NIL) {
|
|
8847
|
+
const c = cmpFn(targetKey, cur.key);
|
|
8848
|
+
if (c === 0) return [callback(cur)];
|
|
8849
|
+
cur = c < 0 ? cur._left : cur._right;
|
|
8850
|
+
}
|
|
8851
|
+
return [];
|
|
8852
|
+
}
|
|
8853
|
+
let predicate;
|
|
8789
8854
|
if (isRange) {
|
|
8790
8855
|
predicate = (node) => {
|
|
8791
8856
|
if (!node) return false;
|
|
@@ -9672,7 +9737,6 @@ var dataStructureTyped = (() => {
|
|
|
9672
9737
|
* @returns True if the node was found and deleted, false otherwise.
|
|
9673
9738
|
*/
|
|
9674
9739
|
_deleteByKey(key) {
|
|
9675
|
-
var _a;
|
|
9676
9740
|
let node = this._root;
|
|
9677
9741
|
while (node) {
|
|
9678
9742
|
const cmp = this._compare(node.key, key);
|
|
@@ -9711,7 +9775,7 @@ var dataStructureTyped = (() => {
|
|
|
9711
9775
|
succ.left = node.left;
|
|
9712
9776
|
if (succ.left) succ.left.parent = succ;
|
|
9713
9777
|
}
|
|
9714
|
-
this._size = Math.max(0,
|
|
9778
|
+
this._size = Math.max(0, this._size - 1);
|
|
9715
9779
|
return true;
|
|
9716
9780
|
}
|
|
9717
9781
|
};
|
|
@@ -10806,12 +10870,11 @@ var dataStructureTyped = (() => {
|
|
|
10806
10870
|
// src/data-structures/binary-tree/red-black-tree.ts
|
|
10807
10871
|
var RedBlackTreeNode = class {
|
|
10808
10872
|
/**
|
|
10809
|
-
* Create a Red-Black Tree
|
|
10810
|
-
* @remarks Time O(
|
|
10811
|
-
* @param key -
|
|
10812
|
-
* @param [value]-
|
|
10813
|
-
* @param color -
|
|
10814
|
-
* @returns New RedBlackTree instance.
|
|
10873
|
+
* Create a Red-Black Tree node.
|
|
10874
|
+
* @remarks Time O(1), Space O(1)
|
|
10875
|
+
* @param key - Node key.
|
|
10876
|
+
* @param [value] - Node value (unused in map mode trees).
|
|
10877
|
+
* @param color - Node color.
|
|
10815
10878
|
*/
|
|
10816
10879
|
constructor(key, value, color = "BLACK") {
|
|
10817
10880
|
__publicField(this, "key");
|
|
@@ -10942,7 +11005,29 @@ var dataStructureTyped = (() => {
|
|
|
10942
11005
|
constructor(keysNodesEntriesOrRaws = [], options) {
|
|
10943
11006
|
super([], options);
|
|
10944
11007
|
__publicField(this, "_root");
|
|
11008
|
+
/**
|
|
11009
|
+
* (Internal) Header sentinel:
|
|
11010
|
+
* - header.parent -> root
|
|
11011
|
+
* - header._left -> min (or NIL)
|
|
11012
|
+
* - header._right -> max (or NIL)
|
|
11013
|
+
*
|
|
11014
|
+
* IMPORTANT:
|
|
11015
|
+
* - This header is NOT part of the actual tree.
|
|
11016
|
+
* - Do NOT use `header.left` / `header.right` accessors for wiring: those setters update `NIL.parent`
|
|
11017
|
+
* and can corrupt sentinel invariants / cause hangs. Only touch `header._left/_right`.
|
|
11018
|
+
*/
|
|
11019
|
+
__publicField(this, "_header");
|
|
11020
|
+
/**
|
|
11021
|
+
* (Internal) Cache of the current minimum and maximum nodes.
|
|
11022
|
+
* Used for fast-path insert/update when keys are monotonic or near-boundary.
|
|
11023
|
+
*/
|
|
11024
|
+
__publicField(this, "_minNode");
|
|
11025
|
+
__publicField(this, "_maxNode");
|
|
10945
11026
|
this._root = this.NIL;
|
|
11027
|
+
this._header = new RedBlackTreeNode(void 0, void 0, "BLACK");
|
|
11028
|
+
this._header.parent = this.NIL;
|
|
11029
|
+
this._header._left = this.NIL;
|
|
11030
|
+
this._header._right = this.NIL;
|
|
10946
11031
|
if (keysNodesEntriesOrRaws) {
|
|
10947
11032
|
this.setMany(keysNodesEntriesOrRaws);
|
|
10948
11033
|
}
|
|
@@ -10980,18 +11065,390 @@ var dataStructureTyped = (() => {
|
|
|
10980
11065
|
* @remarks Time O(n), Space O(1)
|
|
10981
11066
|
* @returns void
|
|
10982
11067
|
*/
|
|
11068
|
+
/**
|
|
11069
|
+
* Remove all nodes and clear internal caches.
|
|
11070
|
+
* @remarks Time O(n) average, Space O(1)
|
|
11071
|
+
*/
|
|
10983
11072
|
clear() {
|
|
10984
11073
|
super.clear();
|
|
10985
11074
|
this._root = this.NIL;
|
|
11075
|
+
this._header.parent = this.NIL;
|
|
11076
|
+
this._setMinCache(void 0);
|
|
11077
|
+
this._setMaxCache(void 0);
|
|
10986
11078
|
}
|
|
10987
11079
|
/**
|
|
10988
|
-
*
|
|
10989
|
-
*
|
|
10990
|
-
*
|
|
10991
|
-
* @
|
|
10992
|
-
|
|
11080
|
+
* (Internal) Find a node by key using a tight BST walk (no allocations).
|
|
11081
|
+
*
|
|
11082
|
+
* NOTE: This uses `header.parent` as the canonical root pointer.
|
|
11083
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11084
|
+
*/
|
|
11085
|
+
_findNodeByKey(key) {
|
|
11086
|
+
var _a, _b, _c;
|
|
11087
|
+
const NIL = this.NIL;
|
|
11088
|
+
const cmp = this._compare.bind(this);
|
|
11089
|
+
let cur = (_a = this._header.parent) != null ? _a : NIL;
|
|
11090
|
+
while (cur !== NIL) {
|
|
11091
|
+
const c = cmp(key, cur.key);
|
|
11092
|
+
if (c < 0) cur = (_b = cur.left) != null ? _b : NIL;
|
|
11093
|
+
else if (c > 0) cur = (_c = cur.right) != null ? _c : NIL;
|
|
11094
|
+
else return cur;
|
|
11095
|
+
}
|
|
11096
|
+
return void 0;
|
|
11097
|
+
}
|
|
11098
|
+
/**
|
|
11099
|
+
* (Internal) In-order predecessor of a node in a BST.
|
|
11100
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11101
|
+
*/
|
|
11102
|
+
_predecessorOf(node) {
|
|
11103
|
+
const NIL = this.NIL;
|
|
11104
|
+
if (node.left && node.left !== NIL) {
|
|
11105
|
+
let cur2 = node.left;
|
|
11106
|
+
while (cur2.right && cur2.right !== NIL) cur2 = cur2.right;
|
|
11107
|
+
return cur2;
|
|
11108
|
+
}
|
|
11109
|
+
let cur = node;
|
|
11110
|
+
let p = node.parent;
|
|
11111
|
+
while (p && cur === p.left) {
|
|
11112
|
+
cur = p;
|
|
11113
|
+
p = p.parent;
|
|
11114
|
+
}
|
|
11115
|
+
return p;
|
|
11116
|
+
}
|
|
11117
|
+
/**
|
|
11118
|
+
* (Internal) In-order successor of a node in a BST.
|
|
11119
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11120
|
+
*/
|
|
11121
|
+
_successorOf(node) {
|
|
11122
|
+
const NIL = this.NIL;
|
|
11123
|
+
if (node.right && node.right !== NIL) {
|
|
11124
|
+
let cur2 = node.right;
|
|
11125
|
+
while (cur2.left && cur2.left !== NIL) cur2 = cur2.left;
|
|
11126
|
+
return cur2;
|
|
11127
|
+
}
|
|
11128
|
+
let cur = node;
|
|
11129
|
+
let p = node.parent;
|
|
11130
|
+
while (p && cur === p.right) {
|
|
11131
|
+
cur = p;
|
|
11132
|
+
p = p.parent;
|
|
11133
|
+
}
|
|
11134
|
+
return p;
|
|
11135
|
+
}
|
|
11136
|
+
/**
|
|
11137
|
+
* (Internal) Attach a new node directly under a known parent/side (no search).
|
|
11138
|
+
*
|
|
11139
|
+
* This is a performance-oriented helper used by boundary fast paths and hinted insertion.
|
|
11140
|
+
* It will:
|
|
11141
|
+
* - wire parent/child pointers (using accessors, so parent pointers are updated)
|
|
11142
|
+
* - initialize children to NIL
|
|
11143
|
+
* - mark the new node RED, then run insert fix-up
|
|
11144
|
+
*
|
|
11145
|
+
* Precondition: the chosen slot (parent.left/parent.right) is empty (NIL/null/undefined).
|
|
11146
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11147
|
+
*/
|
|
11148
|
+
_attachNewNode(parent, side, node) {
|
|
11149
|
+
const NIL = this.NIL;
|
|
11150
|
+
node.parent = parent;
|
|
11151
|
+
if (side === "left") parent.left = node;
|
|
11152
|
+
else parent.right = node;
|
|
11153
|
+
node.left = NIL;
|
|
11154
|
+
node.right = NIL;
|
|
11155
|
+
node.color = "RED";
|
|
11156
|
+
this._insertFixup(node);
|
|
11157
|
+
if (this.isRealNode(this._root)) this._root.color = "BLACK";
|
|
11158
|
+
}
|
|
11159
|
+
/**
|
|
11160
|
+
* (Internal) a single source of truth for min/max is header._left/_right.
|
|
11161
|
+
* Keep legacy _minNode/_maxNode mirrored for compatibility.
|
|
11162
|
+
* @remarks Time O(1), Space O(1)
|
|
11163
|
+
*/
|
|
11164
|
+
/**
|
|
11165
|
+
* (Internal) Update min cache pointers (header._left is the canonical min pointer).
|
|
11166
|
+
* @remarks Time O(1), Space O(1)
|
|
11167
|
+
*/
|
|
11168
|
+
_setMinCache(node) {
|
|
11169
|
+
this._minNode = node;
|
|
11170
|
+
this._header._left = node != null ? node : this.NIL;
|
|
11171
|
+
}
|
|
11172
|
+
/**
|
|
11173
|
+
* (Internal) Update max cache pointers (header._right is the canonical max pointer).
|
|
11174
|
+
* @remarks Time O(1), Space O(1)
|
|
11175
|
+
*/
|
|
11176
|
+
_setMaxCache(node) {
|
|
11177
|
+
this._maxNode = node;
|
|
11178
|
+
this._header._right = node != null ? node : this.NIL;
|
|
11179
|
+
}
|
|
11180
|
+
/**
|
|
11181
|
+
* (Internal) Core set implementation returning the affected node.
|
|
11182
|
+
*
|
|
11183
|
+
* Hot path goals:
|
|
11184
|
+
* - Avoid double walks (search+insert): do a single traversal that either updates or inserts.
|
|
11185
|
+
* - Use header min/max caches to fast-path boundary inserts.
|
|
11186
|
+
* - Keep header._left/_right as canonical min/max pointers.
|
|
11187
|
+
*
|
|
11188
|
+
* Return value:
|
|
11189
|
+
* - `{ node, created:false }` when an existing key is updated
|
|
11190
|
+
* - `{ node, created:true }` when a new node is inserted
|
|
11191
|
+
* - `undefined` only on unexpected internal failure.
|
|
11192
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11193
|
+
*/
|
|
11194
|
+
_setKVNode(key, nextValue) {
|
|
11195
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
11196
|
+
const NIL = this.NIL;
|
|
11197
|
+
const comparator = this._comparator;
|
|
11198
|
+
const header = this._header;
|
|
11199
|
+
const minN = (_a = header._left) != null ? _a : NIL;
|
|
11200
|
+
if (minN !== NIL) {
|
|
11201
|
+
const cMin = comparator(key, minN.key);
|
|
11202
|
+
if (cMin === 0) {
|
|
11203
|
+
if (this._isMapMode) {
|
|
11204
|
+
if (nextValue !== void 0) this._store.set(key, nextValue);
|
|
11205
|
+
else this._setValue(key, nextValue);
|
|
11206
|
+
} else minN.value = nextValue;
|
|
11207
|
+
return { node: minN, created: false };
|
|
11208
|
+
}
|
|
11209
|
+
const minL = minN.left;
|
|
11210
|
+
if (cMin < 0 && (minL === NIL || minL === null || minL === void 0)) {
|
|
11211
|
+
const newNode2 = this.createNode(key, nextValue);
|
|
11212
|
+
this._attachNewNode(minN, "left", newNode2);
|
|
11213
|
+
if (this._isMapMode) {
|
|
11214
|
+
if (nextValue !== void 0) this._store.set(newNode2.key, nextValue);
|
|
11215
|
+
else this._setValue(newNode2.key, nextValue);
|
|
11216
|
+
}
|
|
11217
|
+
this._size++;
|
|
11218
|
+
this._setMinCache(newNode2);
|
|
11219
|
+
if (header._right === NIL) this._setMaxCache(newNode2);
|
|
11220
|
+
return { node: newNode2, created: true };
|
|
11221
|
+
}
|
|
11222
|
+
if (cMin > 0) {
|
|
11223
|
+
const maxN = (_b = header._right) != null ? _b : NIL;
|
|
11224
|
+
const cMax = comparator(key, maxN.key);
|
|
11225
|
+
if (cMax === 0) {
|
|
11226
|
+
if (this._isMapMode) {
|
|
11227
|
+
if (nextValue !== void 0) this._store.set(key, nextValue);
|
|
11228
|
+
else this._setValue(key, nextValue);
|
|
11229
|
+
} else maxN.value = nextValue;
|
|
11230
|
+
return { node: maxN, created: false };
|
|
11231
|
+
}
|
|
11232
|
+
const maxR = maxN.right;
|
|
11233
|
+
if (cMax > 0 && (maxR === NIL || maxR === null || maxR === void 0)) {
|
|
11234
|
+
const newNode2 = this.createNode(key, nextValue);
|
|
11235
|
+
this._attachNewNode(maxN, "right", newNode2);
|
|
11236
|
+
if (this._isMapMode) {
|
|
11237
|
+
if (nextValue !== void 0) this._store.set(newNode2.key, nextValue);
|
|
11238
|
+
else this._setValue(newNode2.key, nextValue);
|
|
11239
|
+
}
|
|
11240
|
+
this._size++;
|
|
11241
|
+
this._setMaxCache(newNode2);
|
|
11242
|
+
if (header._left === NIL) this._setMinCache(newNode2);
|
|
11243
|
+
return { node: newNode2, created: true };
|
|
11244
|
+
}
|
|
11245
|
+
}
|
|
11246
|
+
}
|
|
11247
|
+
const cmp = comparator;
|
|
11248
|
+
const isMapMode = this._isMapMode;
|
|
11249
|
+
const store = this._store;
|
|
11250
|
+
let current = (_c = this._header.parent) != null ? _c : NIL;
|
|
11251
|
+
let parent;
|
|
11252
|
+
let lastCompared = 0;
|
|
11253
|
+
while (current !== NIL) {
|
|
11254
|
+
parent = current;
|
|
11255
|
+
lastCompared = cmp(key, current.key);
|
|
11256
|
+
if (lastCompared < 0) current = (_d = current.left) != null ? _d : NIL;
|
|
11257
|
+
else if (lastCompared > 0) current = (_e = current.right) != null ? _e : NIL;
|
|
11258
|
+
else {
|
|
11259
|
+
if (isMapMode) {
|
|
11260
|
+
if (nextValue !== void 0) store.set(key, nextValue);
|
|
11261
|
+
else this._setValue(key, nextValue);
|
|
11262
|
+
} else {
|
|
11263
|
+
current.value = nextValue;
|
|
11264
|
+
}
|
|
11265
|
+
return { node: current, created: false };
|
|
11266
|
+
}
|
|
11267
|
+
}
|
|
11268
|
+
const newNode = this.createNode(key, nextValue);
|
|
11269
|
+
newNode.parent = parent;
|
|
11270
|
+
if (!parent) {
|
|
11271
|
+
this._setRoot(newNode);
|
|
11272
|
+
} else if (lastCompared < 0) {
|
|
11273
|
+
parent.left = newNode;
|
|
11274
|
+
} else {
|
|
11275
|
+
parent.right = newNode;
|
|
11276
|
+
}
|
|
11277
|
+
newNode.left = NIL;
|
|
11278
|
+
newNode.right = NIL;
|
|
11279
|
+
newNode.color = "RED";
|
|
11280
|
+
this._insertFixup(newNode);
|
|
11281
|
+
if (this.isRealNode(this._root)) this._root.color = "BLACK";
|
|
11282
|
+
else return void 0;
|
|
11283
|
+
if (isMapMode) {
|
|
11284
|
+
if (nextValue !== void 0) store.set(newNode.key, nextValue);
|
|
11285
|
+
else this._setValue(newNode.key, nextValue);
|
|
11286
|
+
}
|
|
11287
|
+
this._size++;
|
|
11288
|
+
const hMin = (_f = this._header._left) != null ? _f : NIL;
|
|
11289
|
+
const hMax = (_g = this._header._right) != null ? _g : NIL;
|
|
11290
|
+
if (hMin === NIL || hMax === NIL) {
|
|
11291
|
+
this._setMinCache(newNode);
|
|
11292
|
+
this._setMaxCache(newNode);
|
|
11293
|
+
} else if (parent === hMax && lastCompared > 0) {
|
|
11294
|
+
this._setMaxCache(newNode);
|
|
11295
|
+
} else if (parent === hMin && lastCompared < 0) {
|
|
11296
|
+
this._setMinCache(newNode);
|
|
11297
|
+
} else {
|
|
11298
|
+
if (cmp(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
|
|
11299
|
+
if (cmp(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
|
|
11300
|
+
}
|
|
11301
|
+
return { node: newNode, created: true };
|
|
11302
|
+
}
|
|
11303
|
+
/**
|
|
11304
|
+
* (Internal) Boolean wrapper around `_setKVNode`.
|
|
11305
|
+
*
|
|
11306
|
+
* Includes a map-mode update fast-path:
|
|
11307
|
+
* - If `isMapMode=true` and the key already exists in `_store`, then updating the value does not
|
|
11308
|
+
* require any tree search/rotation (tree shape depends only on key).
|
|
11309
|
+
* - This path is intentionally limited to `nextValue !== undefined` to preserve existing
|
|
11310
|
+
* semantics for `undefined` values.
|
|
11311
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11312
|
+
*/
|
|
11313
|
+
_setKV(key, nextValue) {
|
|
11314
|
+
if (this._isMapMode && nextValue !== void 0) {
|
|
11315
|
+
const store = this._store;
|
|
11316
|
+
if (store.has(key)) {
|
|
11317
|
+
store.set(key, nextValue);
|
|
11318
|
+
return true;
|
|
11319
|
+
}
|
|
11320
|
+
}
|
|
11321
|
+
return this._setKVNode(key, nextValue) !== void 0;
|
|
11322
|
+
}
|
|
11323
|
+
/**
|
|
11324
|
+
* Insert/update using a hint node to speed up nearby insertions.
|
|
11325
|
+
*
|
|
11326
|
+
* close to the expected insertion position (often the previously returned node in a loop).
|
|
11327
|
+
*
|
|
11328
|
+
* When the hint is a good fit (sorted / nearly-sorted insertion), this can avoid most of the
|
|
11329
|
+
* normal root-to-leaf search and reduce constant factors.
|
|
11330
|
+
*
|
|
11331
|
+
* When the hint does not match (random workloads), this will fall back to the normal set path.
|
|
11332
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11333
|
+
*/
|
|
11334
|
+
setWithHintNode(key, value, hint) {
|
|
11335
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
11336
|
+
if (!hint || !this.isRealNode(hint)) {
|
|
11337
|
+
return (_a = this._setKVNode(key, value)) == null ? void 0 : _a.node;
|
|
11338
|
+
}
|
|
11339
|
+
const cmp = this._compare.bind(this);
|
|
11340
|
+
const c0 = cmp(key, hint.key);
|
|
11341
|
+
if (c0 === 0) {
|
|
11342
|
+
if (this._isMapMode) {
|
|
11343
|
+
if (value !== void 0) this._store.set(key, value);
|
|
11344
|
+
else this._setValue(key, value);
|
|
11345
|
+
} else hint.value = value;
|
|
11346
|
+
return hint;
|
|
11347
|
+
}
|
|
11348
|
+
if (c0 < 0) {
|
|
11349
|
+
if (!this.isRealNode(hint.left)) {
|
|
11350
|
+
const newNode = this.createNode(key, value);
|
|
11351
|
+
if (!this.isRealNode(newNode)) return void 0;
|
|
11352
|
+
this._attachNewNode(hint, "left", newNode);
|
|
11353
|
+
if (this._isMapMode) {
|
|
11354
|
+
if (value !== void 0) this._store.set(key, value);
|
|
11355
|
+
else this._setValue(key, value);
|
|
11356
|
+
}
|
|
11357
|
+
this._size++;
|
|
11358
|
+
const NIL = this.NIL;
|
|
11359
|
+
const hMin = (_b = this._header._left) != null ? _b : NIL;
|
|
11360
|
+
if (hMin === NIL || this._compare(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
|
|
11361
|
+
const hMax = (_c = this._header._right) != null ? _c : NIL;
|
|
11362
|
+
if (hMax === NIL || this._compare(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
|
|
11363
|
+
return newNode;
|
|
11364
|
+
}
|
|
11365
|
+
const pred = this._predecessorOf(hint);
|
|
11366
|
+
if (pred && cmp(pred.key, key) >= 0) {
|
|
11367
|
+
return (_d = this._setKVNode(key, value)) == null ? void 0 : _d.node;
|
|
11368
|
+
}
|
|
11369
|
+
if (pred && !this.isRealNode(pred.right)) {
|
|
11370
|
+
const newNode = this.createNode(key, value);
|
|
11371
|
+
if (!this.isRealNode(newNode)) return void 0;
|
|
11372
|
+
this._attachNewNode(pred, "right", newNode);
|
|
11373
|
+
if (this._isMapMode) {
|
|
11374
|
+
if (value !== void 0) this._store.set(key, value);
|
|
11375
|
+
else this._setValue(key, value);
|
|
11376
|
+
}
|
|
11377
|
+
this._size++;
|
|
11378
|
+
const NIL = this.NIL;
|
|
11379
|
+
const hMin = (_e = this._header._left) != null ? _e : NIL;
|
|
11380
|
+
if (hMin === NIL || this._compare(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
|
|
11381
|
+
const hMax = (_f = this._header._right) != null ? _f : NIL;
|
|
11382
|
+
if (hMax === NIL || this._compare(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
|
|
11383
|
+
return newNode;
|
|
11384
|
+
}
|
|
11385
|
+
return (_g = this._setKVNode(key, value)) == null ? void 0 : _g.node;
|
|
11386
|
+
}
|
|
11387
|
+
if (!this.isRealNode(hint.right)) {
|
|
11388
|
+
const newNode = this.createNode(key, value);
|
|
11389
|
+
if (!this.isRealNode(newNode)) return void 0;
|
|
11390
|
+
this._attachNewNode(hint, "right", newNode);
|
|
11391
|
+
if (this._isMapMode) {
|
|
11392
|
+
if (value !== void 0) this._store.set(key, value);
|
|
11393
|
+
else this._setValue(key, value);
|
|
11394
|
+
}
|
|
11395
|
+
this._size++;
|
|
11396
|
+
const NIL = this.NIL;
|
|
11397
|
+
const hMin = (_h = this._header._left) != null ? _h : NIL;
|
|
11398
|
+
if (hMin === NIL || this._compare(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
|
|
11399
|
+
const hMax = (_i = this._header._right) != null ? _i : NIL;
|
|
11400
|
+
if (hMax === NIL || this._compare(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
|
|
11401
|
+
return newNode;
|
|
11402
|
+
}
|
|
11403
|
+
const succ = this._successorOf(hint);
|
|
11404
|
+
if (succ && cmp(succ.key, key) <= 0) {
|
|
11405
|
+
return (_j = this._setKVNode(key, value)) == null ? void 0 : _j.node;
|
|
11406
|
+
}
|
|
11407
|
+
if (succ && !this.isRealNode(succ.left)) {
|
|
11408
|
+
const newNode = this.createNode(key, value);
|
|
11409
|
+
if (!this.isRealNode(newNode)) return void 0;
|
|
11410
|
+
this._attachNewNode(succ, "left", newNode);
|
|
11411
|
+
if (this._isMapMode) {
|
|
11412
|
+
if (value !== void 0) this._store.set(key, value);
|
|
11413
|
+
else this._setValue(key, value);
|
|
11414
|
+
}
|
|
11415
|
+
this._size++;
|
|
11416
|
+
const NIL = this.NIL;
|
|
11417
|
+
const hMin = (_k = this._header._left) != null ? _k : NIL;
|
|
11418
|
+
if (hMin === NIL || this._compare(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
|
|
11419
|
+
const hMax = (_l = this._header._right) != null ? _l : NIL;
|
|
11420
|
+
if (hMax === NIL || this._compare(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
|
|
11421
|
+
return newNode;
|
|
11422
|
+
}
|
|
11423
|
+
return (_m = this._setKVNode(key, value)) == null ? void 0 : _m.node;
|
|
11424
|
+
}
|
|
11425
|
+
/**
|
|
11426
|
+
* Boolean wrapper for setWithHintNode.
|
|
11427
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11428
|
+
*/
|
|
11429
|
+
setWithHint(key, value, hint) {
|
|
11430
|
+
return this.setWithHintNode(key, value, hint) !== void 0;
|
|
11431
|
+
}
|
|
11432
|
+
/**
|
|
11433
|
+
* Insert or update a key/value (map mode) or key-only (set mode).
|
|
11434
|
+
*
|
|
11435
|
+
* This method is optimized for:
|
|
11436
|
+
* - monotonic inserts via min/max boundary fast paths
|
|
11437
|
+
* - updates via a single-pass search (no double walk)
|
|
11438
|
+
*
|
|
11439
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
10993
11440
|
*/
|
|
10994
11441
|
set(keyNodeOrEntry, value) {
|
|
11442
|
+
if (!this.isNode(keyNodeOrEntry)) {
|
|
11443
|
+
if (keyNodeOrEntry === null || keyNodeOrEntry === void 0) return false;
|
|
11444
|
+
if (this.isEntry(keyNodeOrEntry)) {
|
|
11445
|
+
const key = keyNodeOrEntry[0];
|
|
11446
|
+
if (key === null || key === void 0) return false;
|
|
11447
|
+
const nextValue = value != null ? value : keyNodeOrEntry[1];
|
|
11448
|
+
return this._setKV(key, nextValue);
|
|
11449
|
+
}
|
|
11450
|
+
return this._setKV(keyNodeOrEntry, value);
|
|
11451
|
+
}
|
|
10995
11452
|
const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
10996
11453
|
if (!this.isRealNode(newNode)) return false;
|
|
10997
11454
|
const insertStatus = this._insert(newNode);
|
|
@@ -11013,19 +11470,23 @@ var dataStructureTyped = (() => {
|
|
|
11013
11470
|
}
|
|
11014
11471
|
/**
|
|
11015
11472
|
* Delete a node by key/node/entry and rebalance as needed.
|
|
11016
|
-
* @remarks Time O(log n), Space O(1)
|
|
11017
|
-
* @param
|
|
11473
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11474
|
+
* @param keyNodeEntryRawOrPredicate - Key, node, or [key, value] entry identifying the node to delete.
|
|
11018
11475
|
* @returns Array with deletion metadata (removed node, rebalancing hint if any).
|
|
11019
11476
|
*/
|
|
11020
|
-
delete(
|
|
11021
|
-
if (
|
|
11477
|
+
delete(keyNodeEntryRawOrPredicate) {
|
|
11478
|
+
if (keyNodeEntryRawOrPredicate === null) return [];
|
|
11022
11479
|
const results = [];
|
|
11023
11480
|
let nodeToDelete;
|
|
11024
|
-
if (this._isPredicate(
|
|
11025
|
-
else nodeToDelete = this.isRealNode(
|
|
11481
|
+
if (this._isPredicate(keyNodeEntryRawOrPredicate)) nodeToDelete = this.getNode(keyNodeEntryRawOrPredicate);
|
|
11482
|
+
else nodeToDelete = this.isRealNode(keyNodeEntryRawOrPredicate) ? keyNodeEntryRawOrPredicate : this.getNode(keyNodeEntryRawOrPredicate);
|
|
11026
11483
|
if (!nodeToDelete) {
|
|
11027
11484
|
return results;
|
|
11028
11485
|
}
|
|
11486
|
+
const willDeleteMin = nodeToDelete === this._minNode;
|
|
11487
|
+
const willDeleteMax = nodeToDelete === this._maxNode;
|
|
11488
|
+
const nextMin = willDeleteMin ? this._successorOf(nodeToDelete) : void 0;
|
|
11489
|
+
const nextMax = willDeleteMax ? this._predecessorOf(nodeToDelete) : void 0;
|
|
11029
11490
|
let originalColor = nodeToDelete.color;
|
|
11030
11491
|
let replacementNode;
|
|
11031
11492
|
if (!this.isRealNode(nodeToDelete.left)) {
|
|
@@ -11064,6 +11525,19 @@ var dataStructureTyped = (() => {
|
|
|
11064
11525
|
}
|
|
11065
11526
|
if (this._isMapMode) this._store.delete(nodeToDelete.key);
|
|
11066
11527
|
this._size--;
|
|
11528
|
+
if (this._size <= 0) {
|
|
11529
|
+
this._setMinCache(void 0);
|
|
11530
|
+
this._setMaxCache(void 0);
|
|
11531
|
+
} else {
|
|
11532
|
+
if (willDeleteMin) this._setMinCache(nextMin);
|
|
11533
|
+
if (willDeleteMax) this._setMaxCache(nextMax);
|
|
11534
|
+
if (!this._minNode || !this.isRealNode(this._minNode)) {
|
|
11535
|
+
this._setMinCache(this.isRealNode(this._root) ? this.getLeftMost((n) => n, this._root) : void 0);
|
|
11536
|
+
}
|
|
11537
|
+
if (!this._maxNode || !this.isRealNode(this._maxNode)) {
|
|
11538
|
+
this._setMaxCache(this.isRealNode(this._root) ? this.getRightMost((n) => n, this._root) : void 0);
|
|
11539
|
+
}
|
|
11540
|
+
}
|
|
11067
11541
|
if (originalColor === "BLACK") {
|
|
11068
11542
|
this._deleteFixup(replacementNode);
|
|
11069
11543
|
}
|
|
@@ -11072,7 +11546,7 @@ var dataStructureTyped = (() => {
|
|
|
11072
11546
|
}
|
|
11073
11547
|
/**
|
|
11074
11548
|
* Transform entries into a like-kind red-black tree with possibly different key/value types.
|
|
11075
|
-
* @remarks Time O(n), Space O(n)
|
|
11549
|
+
* @remarks Time O(n) average, Space O(n)
|
|
11076
11550
|
* @template MK
|
|
11077
11551
|
* @template MV
|
|
11078
11552
|
* @template MR
|
|
@@ -11089,41 +11563,62 @@ var dataStructureTyped = (() => {
|
|
|
11089
11563
|
}
|
|
11090
11564
|
return out;
|
|
11091
11565
|
}
|
|
11566
|
+
/**
|
|
11567
|
+
* (Internal) Create an empty instance of the same concrete tree type.
|
|
11568
|
+
* @remarks Time O(1) average, Space O(1)
|
|
11569
|
+
*/
|
|
11092
11570
|
_createInstance(options) {
|
|
11093
11571
|
const Ctor = this.constructor;
|
|
11094
11572
|
return new Ctor([], { ...this._snapshotOptions(), ...options != null ? options : {} });
|
|
11095
11573
|
}
|
|
11574
|
+
/**
|
|
11575
|
+
* (Internal) Create a like-kind tree (same concrete class) populated from an iterable.
|
|
11576
|
+
* @remarks Time O(m log m) average (m = iterable length), Space O(m)
|
|
11577
|
+
*/
|
|
11096
11578
|
_createLike(iter = [], options) {
|
|
11097
11579
|
const Ctor = this.constructor;
|
|
11098
11580
|
return new Ctor(iter, { ...this._snapshotOptions(), ...options != null ? options : {} });
|
|
11099
11581
|
}
|
|
11582
|
+
/**
|
|
11583
|
+
* (Internal) Set the root pointer and keep header.parent in sync.
|
|
11584
|
+
* @remarks Time O(1), Space O(1)
|
|
11585
|
+
*/
|
|
11100
11586
|
_setRoot(v) {
|
|
11587
|
+
const NIL = this.NIL;
|
|
11101
11588
|
if (v) {
|
|
11102
11589
|
v.parent = void 0;
|
|
11103
11590
|
}
|
|
11104
11591
|
this._root = v;
|
|
11592
|
+
this._header.parent = v != null ? v : NIL;
|
|
11105
11593
|
}
|
|
11594
|
+
/**
|
|
11595
|
+
* (Internal) Replace a node in place while preserving its color.
|
|
11596
|
+
* @remarks Time O(1) average, Space O(1)
|
|
11597
|
+
*/
|
|
11106
11598
|
_replaceNode(oldNode, newNode) {
|
|
11107
11599
|
newNode.color = oldNode.color;
|
|
11108
11600
|
return super._replaceNode(oldNode, newNode);
|
|
11109
11601
|
}
|
|
11110
11602
|
/**
|
|
11111
11603
|
* (Protected) Standard BST insert followed by red-black fix-up.
|
|
11112
|
-
* @remarks Time O(log n), Space O(1)
|
|
11604
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11113
11605
|
* @param node - Node to insert.
|
|
11114
11606
|
* @returns Status string: 'CREATED' or 'UPDATED'.
|
|
11115
11607
|
*/
|
|
11116
11608
|
_insert(node) {
|
|
11117
11609
|
var _a, _b, _c;
|
|
11118
|
-
|
|
11119
|
-
|
|
11120
|
-
|
|
11610
|
+
const NIL = this.NIL;
|
|
11611
|
+
const cmp = this._compare.bind(this);
|
|
11612
|
+
let current = (_a = this._header.parent) != null ? _a : NIL;
|
|
11613
|
+
let parent;
|
|
11614
|
+
let lastCompared = 0;
|
|
11615
|
+
while (current !== NIL) {
|
|
11121
11616
|
parent = current;
|
|
11122
|
-
|
|
11123
|
-
if (
|
|
11124
|
-
current = (_b = current.left) != null ? _b :
|
|
11125
|
-
} else if (
|
|
11126
|
-
current = (_c = current.right) != null ? _c :
|
|
11617
|
+
lastCompared = cmp(node.key, current.key);
|
|
11618
|
+
if (lastCompared < 0) {
|
|
11619
|
+
current = (_b = current.left) != null ? _b : NIL;
|
|
11620
|
+
} else if (lastCompared > 0) {
|
|
11621
|
+
current = (_c = current.right) != null ? _c : NIL;
|
|
11127
11622
|
} else {
|
|
11128
11623
|
this._replaceNode(current, node);
|
|
11129
11624
|
return "UPDATED";
|
|
@@ -11132,13 +11627,13 @@ var dataStructureTyped = (() => {
|
|
|
11132
11627
|
node.parent = parent;
|
|
11133
11628
|
if (!parent) {
|
|
11134
11629
|
this._setRoot(node);
|
|
11135
|
-
} else if (
|
|
11630
|
+
} else if (lastCompared < 0) {
|
|
11136
11631
|
parent.left = node;
|
|
11137
11632
|
} else {
|
|
11138
11633
|
parent.right = node;
|
|
11139
11634
|
}
|
|
11140
|
-
node.left =
|
|
11141
|
-
node.right =
|
|
11635
|
+
node.left = NIL;
|
|
11636
|
+
node.right = NIL;
|
|
11142
11637
|
node.color = "RED";
|
|
11143
11638
|
this._insertFixup(node);
|
|
11144
11639
|
return "CREATED";
|
|
@@ -11164,56 +11659,66 @@ var dataStructureTyped = (() => {
|
|
|
11164
11659
|
}
|
|
11165
11660
|
/**
|
|
11166
11661
|
* (Protected) Restore red-black properties after insertion (recolor/rotate).
|
|
11167
|
-
* @remarks Time O(log n), Space O(1)
|
|
11662
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11168
11663
|
* @param z - Recently inserted node.
|
|
11169
11664
|
* @returns void
|
|
11170
11665
|
*/
|
|
11171
11666
|
_insertFixup(z) {
|
|
11172
|
-
|
|
11173
|
-
|
|
11174
|
-
|
|
11175
|
-
|
|
11667
|
+
const leftRotate = this._leftRotate.bind(this);
|
|
11668
|
+
const rightRotate = this._rightRotate.bind(this);
|
|
11669
|
+
while (z) {
|
|
11670
|
+
const p = z.parent;
|
|
11671
|
+
if (!p || p.color !== "RED") break;
|
|
11672
|
+
const gp = p.parent;
|
|
11673
|
+
if (!gp) break;
|
|
11674
|
+
if (p === gp.left) {
|
|
11675
|
+
const y = gp.right;
|
|
11176
11676
|
if ((y == null ? void 0 : y.color) === "RED") {
|
|
11177
|
-
|
|
11677
|
+
p.color = "BLACK";
|
|
11178
11678
|
y.color = "BLACK";
|
|
11179
|
-
|
|
11180
|
-
z =
|
|
11181
|
-
|
|
11182
|
-
|
|
11183
|
-
|
|
11184
|
-
|
|
11185
|
-
|
|
11186
|
-
|
|
11187
|
-
|
|
11188
|
-
|
|
11189
|
-
|
|
11190
|
-
|
|
11679
|
+
gp.color = "RED";
|
|
11680
|
+
z = gp;
|
|
11681
|
+
continue;
|
|
11682
|
+
}
|
|
11683
|
+
if (z === p.right) {
|
|
11684
|
+
z = p;
|
|
11685
|
+
leftRotate(z);
|
|
11686
|
+
}
|
|
11687
|
+
const p2 = z == null ? void 0 : z.parent;
|
|
11688
|
+
const gp2 = p2 == null ? void 0 : p2.parent;
|
|
11689
|
+
if (p2 && gp2) {
|
|
11690
|
+
p2.color = "BLACK";
|
|
11691
|
+
gp2.color = "RED";
|
|
11692
|
+
rightRotate(gp2);
|
|
11191
11693
|
}
|
|
11192
11694
|
} else {
|
|
11193
|
-
const y =
|
|
11695
|
+
const y = gp.left;
|
|
11194
11696
|
if ((y == null ? void 0 : y.color) === "RED") {
|
|
11195
|
-
|
|
11697
|
+
p.color = "BLACK";
|
|
11196
11698
|
y.color = "BLACK";
|
|
11197
|
-
|
|
11198
|
-
z =
|
|
11199
|
-
|
|
11200
|
-
|
|
11201
|
-
|
|
11202
|
-
|
|
11203
|
-
|
|
11204
|
-
|
|
11205
|
-
|
|
11206
|
-
|
|
11207
|
-
|
|
11208
|
-
|
|
11699
|
+
gp.color = "RED";
|
|
11700
|
+
z = gp;
|
|
11701
|
+
continue;
|
|
11702
|
+
}
|
|
11703
|
+
if (z === p.left) {
|
|
11704
|
+
z = p;
|
|
11705
|
+
rightRotate(z);
|
|
11706
|
+
}
|
|
11707
|
+
const p2 = z == null ? void 0 : z.parent;
|
|
11708
|
+
const gp2 = p2 == null ? void 0 : p2.parent;
|
|
11709
|
+
if (p2 && gp2) {
|
|
11710
|
+
p2.color = "BLACK";
|
|
11711
|
+
gp2.color = "RED";
|
|
11712
|
+
leftRotate(gp2);
|
|
11209
11713
|
}
|
|
11210
11714
|
}
|
|
11715
|
+
break;
|
|
11211
11716
|
}
|
|
11212
11717
|
if (this.isRealNode(this._root)) this._root.color = "BLACK";
|
|
11213
11718
|
}
|
|
11214
11719
|
/**
|
|
11215
11720
|
* (Protected) Restore red-black properties after deletion (recolor/rotate).
|
|
11216
|
-
* @remarks Time O(log n), Space O(1)
|
|
11721
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11217
11722
|
* @param node - Child that replaced the deleted node (may be undefined).
|
|
11218
11723
|
* @returns void
|
|
11219
11724
|
*/
|
|
@@ -12104,16 +12609,16 @@ var dataStructureTyped = (() => {
|
|
|
12104
12609
|
/**
|
|
12105
12610
|
* Delete a node (or decrement its count) and rebalance if needed.
|
|
12106
12611
|
* @remarks Time O(log N), Space O(1)
|
|
12107
|
-
* @param
|
|
12612
|
+
* @param keyNodeEntryRawOrPredicate - Key, node, or [key, value] entry identifying the node.
|
|
12108
12613
|
* @param [ignoreCount] - If true, remove the node regardless of its count.
|
|
12109
12614
|
* @returns Array of deletion results including deleted node and a rebalance hint when present.
|
|
12110
12615
|
*/
|
|
12111
|
-
delete(
|
|
12112
|
-
if (
|
|
12616
|
+
delete(keyNodeEntryRawOrPredicate, ignoreCount = false) {
|
|
12617
|
+
if (keyNodeEntryRawOrPredicate === null) return [];
|
|
12113
12618
|
const results = [];
|
|
12114
12619
|
let nodeToDelete;
|
|
12115
|
-
if (this._isPredicate(
|
|
12116
|
-
else nodeToDelete = this.isRealNode(
|
|
12620
|
+
if (this._isPredicate(keyNodeEntryRawOrPredicate)) nodeToDelete = this.getNode(keyNodeEntryRawOrPredicate);
|
|
12621
|
+
else nodeToDelete = this.isRealNode(keyNodeEntryRawOrPredicate) ? keyNodeEntryRawOrPredicate : this.getNode(keyNodeEntryRawOrPredicate);
|
|
12117
12622
|
if (!nodeToDelete) {
|
|
12118
12623
|
return results;
|
|
12119
12624
|
}
|
|
@@ -12156,7 +12661,6 @@ var dataStructureTyped = (() => {
|
|
|
12156
12661
|
if (ignoreCount || nodeToDelete.count <= 1) {
|
|
12157
12662
|
if (successor.right !== null) {
|
|
12158
12663
|
this._transplant(successor, successor.right);
|
|
12159
|
-
this._count -= nodeToDelete.count;
|
|
12160
12664
|
}
|
|
12161
12665
|
} else {
|
|
12162
12666
|
nodeToDelete.count--;
|
|
@@ -12259,6 +12763,11 @@ var dataStructureTyped = (() => {
|
|
|
12259
12763
|
const out = this._createInstance();
|
|
12260
12764
|
this._clone(out);
|
|
12261
12765
|
out._count = this._count;
|
|
12766
|
+
for (const node of this.dfs((n) => n, "IN")) {
|
|
12767
|
+
if (!node) continue;
|
|
12768
|
+
const outNode = out.getNode(node.key);
|
|
12769
|
+
if (outNode) outNode.count = node.count;
|
|
12770
|
+
}
|
|
12262
12771
|
return out;
|
|
12263
12772
|
}
|
|
12264
12773
|
/**
|