data-structure-typed 2.2.7 → 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 +14 -3
- package/README_CN.md +119 -275
- package/benchmark/report.html +1 -1
- package/benchmark/report.json +20 -324
- package/dist/cjs/index.cjs +689 -182
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +693 -185
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +689 -182
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +693 -185
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/leetcode/avl-tree-counter.mjs +2957 -0
- package/dist/leetcode/avl-tree-multi-map.mjs +2889 -0
- package/dist/leetcode/avl-tree.mjs +2720 -0
- package/dist/leetcode/binary-tree.mjs +1594 -0
- package/dist/leetcode/bst.mjs +2398 -0
- package/dist/leetcode/deque.mjs +683 -0
- package/dist/leetcode/directed-graph.mjs +1733 -0
- package/dist/leetcode/doubly-linked-list.mjs +709 -0
- package/dist/leetcode/hash-map.mjs +493 -0
- package/dist/leetcode/heap.mjs +542 -0
- package/dist/leetcode/max-heap.mjs +375 -0
- package/dist/leetcode/max-priority-queue.mjs +383 -0
- package/dist/leetcode/min-heap.mjs +363 -0
- package/dist/leetcode/min-priority-queue.mjs +371 -0
- package/dist/leetcode/priority-queue.mjs +363 -0
- package/dist/leetcode/queue.mjs +943 -0
- package/dist/leetcode/red-black-tree.mjs +2765 -0
- package/dist/leetcode/singly-linked-list.mjs +754 -0
- package/dist/leetcode/stack.mjs +217 -0
- package/dist/leetcode/tree-counter.mjs +3039 -0
- package/dist/leetcode/tree-multi-map.mjs +2913 -0
- package/dist/leetcode/trie.mjs +413 -0
- package/dist/leetcode/undirected-graph.mjs +1650 -0
- package/dist/types/data-structures/base/linear-base.d.ts +6 -6
- package/dist/types/data-structures/binary-tree/avl-tree-counter.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +2 -2
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +10 -10
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +25 -27
- package/dist/types/data-structures/binary-tree/bst.d.ts +13 -12
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +151 -21
- package/dist/types/data-structures/binary-tree/tree-counter.d.ts +4 -4
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +2 -2
- package/dist/types/interfaces/binary-tree.d.ts +1 -1
- package/dist/umd/data-structure-typed.js +689 -181
- 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 +50 -172
- package/src/data-structures/base/linear-base.ts +2 -12
- package/src/data-structures/binary-tree/avl-tree-counter.ts +6 -6
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +13 -13
- package/src/data-structures/binary-tree/avl-tree.ts +15 -15
- package/src/data-structures/binary-tree/binary-tree.ts +57 -60
- package/src/data-structures/binary-tree/bst.ts +100 -26
- package/src/data-structures/binary-tree/red-black-tree.ts +586 -76
- package/src/data-structures/binary-tree/tree-counter.ts +25 -13
- package/src/data-structures/binary-tree/tree-multi-map.ts +13 -13
- package/src/data-structures/queue/deque.ts +10 -0
- package/src/interfaces/binary-tree.ts +1 -1
- package/test/performance/data-structures/binary-tree/red-black-tree.test.ts +1 -2
- 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-counter.test.ts +30 -30
- 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-multi-map.test.ts +46 -46
- 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/avl-tree.test.ts +43 -43
- 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/binary-tree.test.ts +151 -151
- 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 +124 -154
- package/test/unit/data-structures/binary-tree/overall.test.ts +20 -20
- 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.test.ts +141 -141
- 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 +41 -39
- 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/binary-tree/tree-multi-map.test.ts +145 -145
- 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
- package/tsup.config.js +50 -21
- package/tsup.umd.config.js +29 -0
- package/tsup.node.config.js +0 -83
package/dist/esm/index.mjs
CHANGED
|
@@ -1402,6 +1402,12 @@ var LinearLinkedBase = class extends LinearBase {
|
|
|
1402
1402
|
}
|
|
1403
1403
|
return -1;
|
|
1404
1404
|
}
|
|
1405
|
+
/**
|
|
1406
|
+
* Concatenate lists/elements preserving order.
|
|
1407
|
+
* @param items - Elements or `LinearBase` instances.
|
|
1408
|
+
* @returns New list with combined elements (`this` type).
|
|
1409
|
+
* @remarks Time O(sum(length)), Space O(sum(length))
|
|
1410
|
+
*/
|
|
1405
1411
|
concat(...items) {
|
|
1406
1412
|
const newList = this.clone();
|
|
1407
1413
|
for (const item of items) {
|
|
@@ -4228,6 +4234,12 @@ var Deque = class extends LinearBase {
|
|
|
4228
4234
|
*/
|
|
4229
4235
|
_setBucketSize(size) {
|
|
4230
4236
|
this._bucketSize = size;
|
|
4237
|
+
if (this._length === 0) {
|
|
4238
|
+
this._buckets = [new Array(this._bucketSize)];
|
|
4239
|
+
this._bucketCount = 1;
|
|
4240
|
+
this._bucketFirst = this._bucketLast = 0;
|
|
4241
|
+
this._firstInBucket = this._lastInBucket = this._bucketSize >> 1;
|
|
4242
|
+
}
|
|
4231
4243
|
}
|
|
4232
4244
|
/**
|
|
4233
4245
|
* (Protected) Iterate elements from front to back.
|
|
@@ -6993,9 +7005,9 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
6993
7005
|
iterationType = "ITERATIVE";
|
|
6994
7006
|
/**
|
|
6995
7007
|
* Creates an instance of BinaryTree.
|
|
6996
|
-
* @remarks Time O(N * M), where N is the number of items in `keysNodesEntriesOrRaws` and M is the tree size at insertion time (due to O(M) `
|
|
7008
|
+
* @remarks Time O(N * M), where N is the number of items in `keysNodesEntriesOrRaws` and M is the tree size at insertion time (due to O(M) `set` operation). Space O(N) for storing the nodes.
|
|
6997
7009
|
*
|
|
6998
|
-
* @param [keysNodesEntriesOrRaws=[]] - An iterable of items to
|
|
7010
|
+
* @param [keysNodesEntriesOrRaws=[]] - An iterable of items to set.
|
|
6999
7011
|
* @param [options] - Configuration options for the tree.
|
|
7000
7012
|
*/
|
|
7001
7013
|
constructor(keysNodesEntriesOrRaws = [], options) {
|
|
@@ -7008,7 +7020,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
7008
7020
|
if (typeof toEntryFn === "function") this._toEntryFn = toEntryFn;
|
|
7009
7021
|
else if (toEntryFn) throw TypeError("toEntryFn must be a function type");
|
|
7010
7022
|
}
|
|
7011
|
-
if (keysNodesEntriesOrRaws) this.
|
|
7023
|
+
if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
|
|
7012
7024
|
}
|
|
7013
7025
|
_isMapMode = true;
|
|
7014
7026
|
/**
|
|
@@ -7222,10 +7234,20 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
7222
7234
|
* @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). This implementation adds the node at the first available position in a level-order (BFS) traversal. This is NOT a Binary Search Tree insertion. Time O(N), where N is the number of nodes. It must traverse level-by-level to find an empty slot. Space O(N) in the worst case for the BFS queue (e.g., a full last level).
|
|
7223
7235
|
*
|
|
7224
7236
|
* @param keyNodeOrEntry - The key, node, or entry to add.
|
|
7237
|
+
* @returns True if the addition was successful, false otherwise.
|
|
7238
|
+
*/
|
|
7239
|
+
add(keyNodeOrEntry) {
|
|
7240
|
+
return this.set(keyNodeOrEntry);
|
|
7241
|
+
}
|
|
7242
|
+
/**
|
|
7243
|
+
* Adds or updates a new node to the tree.
|
|
7244
|
+
* @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). This implementation sets the node at the first available position in a level-order (BFS) traversal. This is NOT a Binary Search Tree insertion. Time O(N), where N is the number of nodes. It must traverse level-by-level to find an empty slot. Space O(N) in the worst case for the BFS queue (e.g., a full last level).
|
|
7245
|
+
*
|
|
7246
|
+
* @param keyNodeOrEntry - The key, node, or entry to set or update.
|
|
7225
7247
|
* @param [value] - The value, if providing just a key.
|
|
7226
7248
|
* @returns True if the addition was successful, false otherwise.
|
|
7227
7249
|
*/
|
|
7228
|
-
|
|
7250
|
+
set(keyNodeOrEntry, value) {
|
|
7229
7251
|
const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
7230
7252
|
if (newNode === void 0) return false;
|
|
7231
7253
|
if (!this._root) {
|
|
@@ -7269,25 +7291,24 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
7269
7291
|
return false;
|
|
7270
7292
|
}
|
|
7271
7293
|
/**
|
|
7272
|
-
* Adds
|
|
7273
|
-
* @remarks Time O(
|
|
7294
|
+
* Adds multiple items to the tree.
|
|
7295
|
+
* @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).
|
|
7274
7296
|
*
|
|
7275
|
-
* @param
|
|
7276
|
-
* @
|
|
7277
|
-
* @returns True if the addition was successful, false otherwise.
|
|
7297
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set.
|
|
7298
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
7278
7299
|
*/
|
|
7279
|
-
|
|
7280
|
-
return this.
|
|
7300
|
+
addMany(keysNodesEntriesOrRaws) {
|
|
7301
|
+
return this.setMany(keysNodesEntriesOrRaws);
|
|
7281
7302
|
}
|
|
7282
7303
|
/**
|
|
7283
|
-
* Adds multiple items to the tree.
|
|
7284
|
-
* @remarks Time O(N * M), where N is the number of items to
|
|
7304
|
+
* Adds or updates multiple items to the tree.
|
|
7305
|
+
* @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).
|
|
7285
7306
|
*
|
|
7286
|
-
* @param keysNodesEntriesOrRaws - An iterable of items to
|
|
7307
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set or update.
|
|
7287
7308
|
* @param [values] - An optional parallel iterable of values.
|
|
7288
|
-
* @returns An array of booleans indicating the success of each individual `
|
|
7309
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
7289
7310
|
*/
|
|
7290
|
-
|
|
7311
|
+
setMany(keysNodesEntriesOrRaws, values) {
|
|
7291
7312
|
const inserted = [];
|
|
7292
7313
|
let valuesIterator;
|
|
7293
7314
|
if (values) {
|
|
@@ -7302,52 +7323,41 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
7302
7323
|
}
|
|
7303
7324
|
}
|
|
7304
7325
|
if (this.isRaw(keyNodeEntryOrRaw)) keyNodeEntryOrRaw = this._toEntryFn(keyNodeEntryOrRaw);
|
|
7305
|
-
inserted.push(this.
|
|
7326
|
+
inserted.push(this.set(keyNodeEntryOrRaw, value));
|
|
7306
7327
|
}
|
|
7307
7328
|
return inserted;
|
|
7308
7329
|
}
|
|
7309
7330
|
/**
|
|
7310
|
-
*
|
|
7311
|
-
* @remarks Time O(N * M), where N is the
|
|
7312
|
-
*
|
|
7313
|
-
* @param keysNodesEntriesOrRaws - An iterable of items to add or update.
|
|
7314
|
-
* @param [values] - An optional parallel iterable of values.
|
|
7315
|
-
* @returns An array of booleans indicating the success of each individual `add` operation.
|
|
7316
|
-
*/
|
|
7317
|
-
setMany(keysNodesEntriesOrRaws, values) {
|
|
7318
|
-
return this.addMany(keysNodesEntriesOrRaws, values);
|
|
7319
|
-
}
|
|
7320
|
-
/**
|
|
7321
|
-
* Merges another tree into this one by adding all its nodes.
|
|
7322
|
-
* @remarks Time O(N * M), same as `addMany`, where N is the size of `anotherTree` and M is the size of this tree. Space O(M) (from `add`).
|
|
7331
|
+
* Merges another tree into this one by seting all its nodes.
|
|
7332
|
+
* @remarks Time O(N * M), same as `setMany`, where N is the size of `anotherTree` and M is the size of this tree. Space O(M) (from `set`).
|
|
7323
7333
|
*
|
|
7324
7334
|
* @param anotherTree - The tree to merge.
|
|
7325
7335
|
*/
|
|
7326
7336
|
merge(anotherTree) {
|
|
7327
|
-
this.
|
|
7337
|
+
this.setMany(anotherTree, []);
|
|
7328
7338
|
}
|
|
7329
7339
|
/**
|
|
7330
7340
|
* Clears the tree and refills it with new items.
|
|
7331
|
-
* @remarks Time O(N) (for `clear`) + O(N * M) (for `
|
|
7341
|
+
* @remarks Time O(N) (for `clear`) + O(N * M) (for `setMany`) = O(N * M). Space O(M) (from `setMany`).
|
|
7332
7342
|
*
|
|
7333
|
-
* @param keysNodesEntriesOrRaws - An iterable of items to
|
|
7343
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set.
|
|
7334
7344
|
* @param [values] - An optional parallel iterable of values.
|
|
7335
7345
|
*/
|
|
7336
7346
|
refill(keysNodesEntriesOrRaws, values) {
|
|
7337
7347
|
this.clear();
|
|
7338
|
-
this.
|
|
7348
|
+
this.setMany(keysNodesEntriesOrRaws, values);
|
|
7339
7349
|
}
|
|
7340
7350
|
/**
|
|
7341
7351
|
* Deletes a node from the tree.
|
|
7342
7352
|
* @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).
|
|
7343
7353
|
*
|
|
7344
|
-
* @param
|
|
7354
|
+
* @param keyNodeEntryRawOrPredicate - The node to delete.
|
|
7345
7355
|
* @returns An array containing deletion results (for compatibility with self-balancing trees).
|
|
7346
7356
|
*/
|
|
7347
|
-
delete(
|
|
7357
|
+
delete(keyNodeEntryRawOrPredicate) {
|
|
7348
7358
|
const deletedResult = [];
|
|
7349
7359
|
if (!this._root) return deletedResult;
|
|
7350
|
-
const curr = this.getNode(
|
|
7360
|
+
const curr = this.getNode(keyNodeEntryRawOrPredicate);
|
|
7351
7361
|
if (!curr) return deletedResult;
|
|
7352
7362
|
const parent = curr?.parent;
|
|
7353
7363
|
let needBalanced;
|
|
@@ -7530,7 +7540,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
7530
7540
|
}
|
|
7531
7541
|
return true;
|
|
7532
7542
|
}, "checkBST");
|
|
7533
|
-
const isStandardBST = checkBST(
|
|
7543
|
+
const isStandardBST = checkBST();
|
|
7534
7544
|
const isInverseBST = checkBST(true);
|
|
7535
7545
|
return isStandardBST || isInverseBST;
|
|
7536
7546
|
}
|
|
@@ -8000,7 +8010,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
8000
8010
|
}
|
|
8001
8011
|
/**
|
|
8002
8012
|
* Clones the tree.
|
|
8003
|
-
* @remarks Time O(N * M), where N is the number of nodes and M is the tree size during insertion (due to `bfs` + `
|
|
8013
|
+
* @remarks Time O(N * M), where N is the number of nodes and M is the tree size during insertion (due to `bfs` + `set`, and `set` is O(M)). Space O(N) for the new tree and the BFS queue.
|
|
8004
8014
|
*
|
|
8005
8015
|
* @returns A new, cloned instance of the tree.
|
|
8006
8016
|
*/
|
|
@@ -8011,7 +8021,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
8011
8021
|
}
|
|
8012
8022
|
/**
|
|
8013
8023
|
* Creates a new tree containing only the entries that satisfy the predicate.
|
|
8014
|
-
* @remarks Time O(N * M), where N is nodes in this tree, and M is size of the new tree during insertion (O(N) iteration + O(M) `
|
|
8024
|
+
* @remarks Time O(N * M), where N is nodes in this tree, and M is size of the new tree during insertion (O(N) iteration + O(M) `set` for each item). Space O(N) for the new tree.
|
|
8015
8025
|
*
|
|
8016
8026
|
* @param predicate - A function to test each [key, value] pair.
|
|
8017
8027
|
* @param [thisArg] - `this` context for the predicate.
|
|
@@ -8020,7 +8030,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
8020
8030
|
filter(predicate, thisArg) {
|
|
8021
8031
|
const out = this._createInstance();
|
|
8022
8032
|
let i = 0;
|
|
8023
|
-
for (const [k, v] of this) if (predicate.call(thisArg, v, k, i++, this)) out.
|
|
8033
|
+
for (const [k, v] of this) if (predicate.call(thisArg, v, k, i++, this)) out.set([k, v]);
|
|
8024
8034
|
return out;
|
|
8025
8035
|
}
|
|
8026
8036
|
/**
|
|
@@ -8038,7 +8048,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
8038
8048
|
map(cb, options, thisArg) {
|
|
8039
8049
|
const out = this._createLike([], options);
|
|
8040
8050
|
let i = 0;
|
|
8041
|
-
for (const [k, v] of this) out.
|
|
8051
|
+
for (const [k, v] of this) out.set(cb.call(thisArg, v, k, i++, this));
|
|
8042
8052
|
return out;
|
|
8043
8053
|
}
|
|
8044
8054
|
/**
|
|
@@ -8290,18 +8300,18 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
8290
8300
|
return [this.createNode(keyNodeOrEntry, value), value];
|
|
8291
8301
|
}
|
|
8292
8302
|
/**
|
|
8293
|
-
* (Protected) Helper for cloning. Performs a BFS and
|
|
8294
|
-
* @remarks Time O(N * M) (O(N) BFS + O(M) `
|
|
8303
|
+
* (Protected) Helper for cloning. Performs a BFS and sets all nodes to the new tree.
|
|
8304
|
+
* @remarks Time O(N * M) (O(N) BFS + O(M) `set` for each node).
|
|
8295
8305
|
*
|
|
8296
8306
|
* @param cloned - The new, empty tree instance to populate.
|
|
8297
8307
|
*/
|
|
8298
8308
|
_clone(cloned) {
|
|
8299
8309
|
this.bfs(
|
|
8300
8310
|
(node) => {
|
|
8301
|
-
if (node === null) cloned.
|
|
8311
|
+
if (node === null) cloned.set(null);
|
|
8302
8312
|
else {
|
|
8303
|
-
if (this._isMapMode) cloned.
|
|
8304
|
-
else cloned.
|
|
8313
|
+
if (this._isMapMode) cloned.set([node.key, this._store.get(node.key)]);
|
|
8314
|
+
else cloned.set([node.key, node.value]);
|
|
8305
8315
|
}
|
|
8306
8316
|
},
|
|
8307
8317
|
this._root,
|
|
@@ -8634,7 +8644,7 @@ var BST = class extends BinaryTree {
|
|
|
8634
8644
|
* Creates an instance of BST.
|
|
8635
8645
|
* @remarks Time O(N log N) or O(N^2) depending on `isBalanceAdd` in `addMany` and input order. Space O(N).
|
|
8636
8646
|
*
|
|
8637
|
-
* @param [keysNodesEntriesOrRaws=[]] - An iterable of items to
|
|
8647
|
+
* @param [keysNodesEntriesOrRaws=[]] - An iterable of items to set.
|
|
8638
8648
|
* @param [options] - Configuration options for the BST, including comparator.
|
|
8639
8649
|
*/
|
|
8640
8650
|
constructor(keysNodesEntriesOrRaws = [], options) {
|
|
@@ -8648,7 +8658,7 @@ var BST = class extends BinaryTree {
|
|
|
8648
8658
|
} else {
|
|
8649
8659
|
this._comparator = this._createDefaultComparator();
|
|
8650
8660
|
}
|
|
8651
|
-
if (keysNodesEntriesOrRaws) this.
|
|
8661
|
+
if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
|
|
8652
8662
|
}
|
|
8653
8663
|
_root = void 0;
|
|
8654
8664
|
/**
|
|
@@ -8768,7 +8778,39 @@ var BST = class extends BinaryTree {
|
|
|
8768
8778
|
* @returns The first matching node, or undefined if not found.
|
|
8769
8779
|
*/
|
|
8770
8780
|
getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
8771
|
-
|
|
8781
|
+
if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === void 0) return void 0;
|
|
8782
|
+
if (this._isPredicate(keyNodeEntryOrPredicate)) {
|
|
8783
|
+
return this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0] ?? void 0;
|
|
8784
|
+
}
|
|
8785
|
+
if (keyNodeEntryOrPredicate instanceof Range) {
|
|
8786
|
+
return this.getNodes(
|
|
8787
|
+
keyNodeEntryOrPredicate,
|
|
8788
|
+
true,
|
|
8789
|
+
startNode,
|
|
8790
|
+
iterationType
|
|
8791
|
+
)[0] ?? void 0;
|
|
8792
|
+
}
|
|
8793
|
+
let targetKey;
|
|
8794
|
+
if (this.isNode(keyNodeEntryOrPredicate)) {
|
|
8795
|
+
targetKey = keyNodeEntryOrPredicate.key;
|
|
8796
|
+
} else if (this.isEntry(keyNodeEntryOrPredicate)) {
|
|
8797
|
+
const k = keyNodeEntryOrPredicate[0];
|
|
8798
|
+
if (k === null || k === void 0) return void 0;
|
|
8799
|
+
targetKey = k;
|
|
8800
|
+
} else {
|
|
8801
|
+
targetKey = keyNodeEntryOrPredicate;
|
|
8802
|
+
}
|
|
8803
|
+
const start = this.ensureNode(startNode);
|
|
8804
|
+
if (!start) return void 0;
|
|
8805
|
+
const NIL = this._NIL;
|
|
8806
|
+
let cur = start;
|
|
8807
|
+
const cmpFn = this._comparator;
|
|
8808
|
+
while (cur && cur !== NIL) {
|
|
8809
|
+
const c = cmpFn(targetKey, cur.key);
|
|
8810
|
+
if (c === 0) return cur;
|
|
8811
|
+
cur = c < 0 ? cur._left : cur._right;
|
|
8812
|
+
}
|
|
8813
|
+
return void 0;
|
|
8772
8814
|
}
|
|
8773
8815
|
/**
|
|
8774
8816
|
* Searches the tree for nodes matching a predicate, key, or range.
|
|
@@ -8789,8 +8831,30 @@ var BST = class extends BinaryTree {
|
|
|
8789
8831
|
if (keyNodeEntryOrPredicate === null) return [];
|
|
8790
8832
|
startNode = this.ensureNode(startNode);
|
|
8791
8833
|
if (!startNode) return [];
|
|
8792
|
-
let predicate;
|
|
8793
8834
|
const isRange = this.isRange(keyNodeEntryOrPredicate);
|
|
8835
|
+
const isPred = !isRange && this._isPredicate(keyNodeEntryOrPredicate);
|
|
8836
|
+
if (!isRange && !isPred) {
|
|
8837
|
+
let targetKey;
|
|
8838
|
+
if (this.isNode(keyNodeEntryOrPredicate)) {
|
|
8839
|
+
targetKey = keyNodeEntryOrPredicate.key;
|
|
8840
|
+
} else if (this.isEntry(keyNodeEntryOrPredicate)) {
|
|
8841
|
+
const k = keyNodeEntryOrPredicate[0];
|
|
8842
|
+
if (k !== null && k !== void 0) targetKey = k;
|
|
8843
|
+
} else {
|
|
8844
|
+
targetKey = keyNodeEntryOrPredicate;
|
|
8845
|
+
}
|
|
8846
|
+
if (targetKey === void 0) return [];
|
|
8847
|
+
const NIL = this._NIL;
|
|
8848
|
+
const cmpFn = this._comparator;
|
|
8849
|
+
let cur = startNode;
|
|
8850
|
+
while (cur && cur !== NIL) {
|
|
8851
|
+
const c = cmpFn(targetKey, cur.key);
|
|
8852
|
+
if (c === 0) return [callback(cur)];
|
|
8853
|
+
cur = c < 0 ? cur._left : cur._right;
|
|
8854
|
+
}
|
|
8855
|
+
return [];
|
|
8856
|
+
}
|
|
8857
|
+
let predicate;
|
|
8794
8858
|
if (isRange) {
|
|
8795
8859
|
predicate = /* @__PURE__ */ __name((node) => {
|
|
8796
8860
|
if (!node) return false;
|
|
@@ -8864,11 +8928,11 @@ var BST = class extends BinaryTree {
|
|
|
8864
8928
|
* Adds a new node to the BST based on key comparison.
|
|
8865
8929
|
* @remarks Time O(log N), where H is tree height. O(N) worst-case (unbalanced tree), O(log N) average. Space O(1).
|
|
8866
8930
|
*
|
|
8867
|
-
* @param keyNodeOrEntry - The key, node, or entry to
|
|
8931
|
+
* @param keyNodeOrEntry - The key, node, or entry to set.
|
|
8868
8932
|
* @param [value] - The value, if providing just a key.
|
|
8869
8933
|
* @returns True if the addition was successful, false otherwise.
|
|
8870
8934
|
*/
|
|
8871
|
-
|
|
8935
|
+
set(keyNodeOrEntry, value) {
|
|
8872
8936
|
const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
8873
8937
|
if (newNode === void 0) return false;
|
|
8874
8938
|
if (this._root === void 0) {
|
|
@@ -8905,24 +8969,24 @@ var BST = class extends BinaryTree {
|
|
|
8905
8969
|
}
|
|
8906
8970
|
/**
|
|
8907
8971
|
* Adds multiple items to the tree.
|
|
8908
|
-
* @remarks If `isBalanceAdd` is true, sorts the input and builds a balanced tree. Time O(N log N) (due to sort and balanced
|
|
8972
|
+
* @remarks If `isBalanceAdd` is true, sorts the input and builds a balanced tree. Time O(N log N) (due to sort and balanced set).
|
|
8909
8973
|
* If false, adds items one by one. Time O(N * H), which is O(N^2) worst-case.
|
|
8910
8974
|
* Space O(N) for sorting and recursion/iteration stack.
|
|
8911
8975
|
*
|
|
8912
|
-
* @param keysNodesEntriesOrRaws - An iterable of items to
|
|
8976
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set.
|
|
8913
8977
|
* @param [values] - An optional parallel iterable of values.
|
|
8914
8978
|
* @param [isBalanceAdd=true] - If true, builds a balanced tree from the items.
|
|
8915
|
-
* @param [iterationType=this.iterationType] - The traversal method for balanced
|
|
8916
|
-
* @returns An array of booleans indicating the success of each individual `
|
|
8979
|
+
* @param [iterationType=this.iterationType] - The traversal method for balanced set (recursive or iterative).
|
|
8980
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
8917
8981
|
*/
|
|
8918
|
-
|
|
8982
|
+
setMany(keysNodesEntriesOrRaws, values, isBalanceAdd = true, iterationType = this.iterationType) {
|
|
8919
8983
|
const inserted = [];
|
|
8920
8984
|
const valuesIterator = values?.[Symbol.iterator]();
|
|
8921
8985
|
if (!isBalanceAdd) {
|
|
8922
8986
|
for (let kve of keysNodesEntriesOrRaws) {
|
|
8923
8987
|
const val = valuesIterator?.next().value;
|
|
8924
8988
|
if (this.isRaw(kve)) kve = this._toEntryFn(kve);
|
|
8925
|
-
inserted.push(this.
|
|
8989
|
+
inserted.push(this.set(kve, val));
|
|
8926
8990
|
}
|
|
8927
8991
|
return inserted;
|
|
8928
8992
|
}
|
|
@@ -8950,9 +9014,9 @@ var BST = class extends BinaryTree {
|
|
|
8950
9014
|
const { key, value, orgIndex } = arr[mid];
|
|
8951
9015
|
if (this.isRaw(key)) {
|
|
8952
9016
|
const entry = this._toEntryFn(key);
|
|
8953
|
-
inserted[orgIndex] = this.
|
|
9017
|
+
inserted[orgIndex] = this.set(entry);
|
|
8954
9018
|
} else {
|
|
8955
|
-
inserted[orgIndex] = this.
|
|
9019
|
+
inserted[orgIndex] = this.set(key, value);
|
|
8956
9020
|
}
|
|
8957
9021
|
_dfs(arr.slice(0, mid));
|
|
8958
9022
|
_dfs(arr.slice(mid + 1));
|
|
@@ -8969,9 +9033,9 @@ var BST = class extends BinaryTree {
|
|
|
8969
9033
|
const { key, value, orgIndex } = sorted[m];
|
|
8970
9034
|
if (this.isRaw(key)) {
|
|
8971
9035
|
const entry = this._toEntryFn(key);
|
|
8972
|
-
inserted[orgIndex] = this.
|
|
9036
|
+
inserted[orgIndex] = this.set(entry);
|
|
8973
9037
|
} else {
|
|
8974
|
-
inserted[orgIndex] = this.
|
|
9038
|
+
inserted[orgIndex] = this.set(key, value);
|
|
8975
9039
|
}
|
|
8976
9040
|
stack.push([m + 1, r]);
|
|
8977
9041
|
stack.push([l, m - 1]);
|
|
@@ -9246,7 +9310,7 @@ var BST = class extends BinaryTree {
|
|
|
9246
9310
|
const out = this._createLike([], options);
|
|
9247
9311
|
let index = 0;
|
|
9248
9312
|
for (const [key, value] of this) {
|
|
9249
|
-
out.
|
|
9313
|
+
out.set(callback.call(thisArg, value, key, index++, this));
|
|
9250
9314
|
}
|
|
9251
9315
|
return out;
|
|
9252
9316
|
}
|
|
@@ -9712,7 +9776,7 @@ var BST = class extends BinaryTree {
|
|
|
9712
9776
|
succ.left = node.left;
|
|
9713
9777
|
if (succ.left) succ.left.parent = succ;
|
|
9714
9778
|
}
|
|
9715
|
-
this._size = Math.max(0,
|
|
9779
|
+
this._size = Math.max(0, this._size - 1);
|
|
9716
9780
|
return true;
|
|
9717
9781
|
}
|
|
9718
9782
|
};
|
|
@@ -10433,14 +10497,14 @@ var AVLTree = class extends BST {
|
|
|
10433
10497
|
}
|
|
10434
10498
|
/**
|
|
10435
10499
|
* Creates an instance of AVLTree.
|
|
10436
|
-
* @remarks Time O(N log N) (from `
|
|
10500
|
+
* @remarks Time O(N log N) (from `setMany` with balanced set). Space O(N).
|
|
10437
10501
|
*
|
|
10438
|
-
* @param [keysNodesEntriesOrRaws=[]] - An iterable of items to
|
|
10502
|
+
* @param [keysNodesEntriesOrRaws=[]] - An iterable of items to set.
|
|
10439
10503
|
* @param [options] - Configuration options for the AVL tree.
|
|
10440
10504
|
*/
|
|
10441
10505
|
constructor(keysNodesEntriesOrRaws = [], options) {
|
|
10442
10506
|
super([], options);
|
|
10443
|
-
if (keysNodesEntriesOrRaws) super.
|
|
10507
|
+
if (keysNodesEntriesOrRaws) super.setMany(keysNodesEntriesOrRaws);
|
|
10444
10508
|
}
|
|
10445
10509
|
/**
|
|
10446
10510
|
* (Protected) Creates a new AVL tree node.
|
|
@@ -10464,16 +10528,16 @@ var AVLTree = class extends BST {
|
|
|
10464
10528
|
return keyNodeOrEntry instanceof AVLTreeNode;
|
|
10465
10529
|
}
|
|
10466
10530
|
/**
|
|
10467
|
-
*
|
|
10468
|
-
* @remarks Time O(log N) (O(H) for BST
|
|
10531
|
+
* Sets a new node to the AVL tree and balances the tree path.
|
|
10532
|
+
* @remarks Time O(log N) (O(H) for BST set + O(H) for `_balancePath`). Space O(H) for path/recursion.
|
|
10469
10533
|
*
|
|
10470
|
-
* @param keyNodeOrEntry - The key, node, or entry to
|
|
10534
|
+
* @param keyNodeOrEntry - The key, node, or entry to set.
|
|
10471
10535
|
* @param [value] - The value, if providing just a key.
|
|
10472
10536
|
* @returns True if the addition was successful, false otherwise.
|
|
10473
10537
|
*/
|
|
10474
|
-
|
|
10538
|
+
set(keyNodeOrEntry, value) {
|
|
10475
10539
|
if (keyNodeOrEntry === null) return false;
|
|
10476
|
-
const inserted = super.
|
|
10540
|
+
const inserted = super.set(keyNodeOrEntry, value);
|
|
10477
10541
|
if (inserted) this._balancePath(keyNodeOrEntry);
|
|
10478
10542
|
return inserted;
|
|
10479
10543
|
}
|
|
@@ -10525,7 +10589,7 @@ var AVLTree = class extends BST {
|
|
|
10525
10589
|
}
|
|
10526
10590
|
/**
|
|
10527
10591
|
* Creates a new AVLTree by mapping each [key, value] pair.
|
|
10528
|
-
* @remarks Time O(N log N) (O(N) iteration + O(log M) `
|
|
10592
|
+
* @remarks Time O(N log N) (O(N) iteration + O(log M) `set` for each item into the new tree). Space O(N) for the new tree.
|
|
10529
10593
|
*
|
|
10530
10594
|
* @template MK - New key type.
|
|
10531
10595
|
* @template MV - New value type.
|
|
@@ -10539,7 +10603,7 @@ var AVLTree = class extends BST {
|
|
|
10539
10603
|
const out = this._createLike([], options);
|
|
10540
10604
|
let index = 0;
|
|
10541
10605
|
for (const [key, value] of this) {
|
|
10542
|
-
out.
|
|
10606
|
+
out.set(callback.call(thisArg, value, key, index++, this));
|
|
10543
10607
|
}
|
|
10544
10608
|
return out;
|
|
10545
10609
|
}
|
|
@@ -10828,12 +10892,11 @@ var RedBlackTreeNode = class {
|
|
|
10828
10892
|
value;
|
|
10829
10893
|
parent = void 0;
|
|
10830
10894
|
/**
|
|
10831
|
-
* Create a Red-Black Tree
|
|
10832
|
-
* @remarks Time O(
|
|
10833
|
-
* @param key -
|
|
10834
|
-
* @param [value]-
|
|
10835
|
-
* @param color -
|
|
10836
|
-
* @returns New RedBlackTree instance.
|
|
10895
|
+
* Create a Red-Black Tree node.
|
|
10896
|
+
* @remarks Time O(1), Space O(1)
|
|
10897
|
+
* @param key - Node key.
|
|
10898
|
+
* @param [value] - Node value (unused in map mode trees).
|
|
10899
|
+
* @param color - Node color.
|
|
10837
10900
|
*/
|
|
10838
10901
|
constructor(key, value, color = "BLACK") {
|
|
10839
10902
|
this.key = key;
|
|
@@ -10964,11 +11027,33 @@ var RedBlackTree = class extends BST {
|
|
|
10964
11027
|
constructor(keysNodesEntriesOrRaws = [], options) {
|
|
10965
11028
|
super([], options);
|
|
10966
11029
|
this._root = this.NIL;
|
|
11030
|
+
this._header = new RedBlackTreeNode(void 0, void 0, "BLACK");
|
|
11031
|
+
this._header.parent = this.NIL;
|
|
11032
|
+
this._header._left = this.NIL;
|
|
11033
|
+
this._header._right = this.NIL;
|
|
10967
11034
|
if (keysNodesEntriesOrRaws) {
|
|
10968
|
-
this.
|
|
11035
|
+
this.setMany(keysNodesEntriesOrRaws);
|
|
10969
11036
|
}
|
|
10970
11037
|
}
|
|
10971
11038
|
_root;
|
|
11039
|
+
/**
|
|
11040
|
+
* (Internal) Header sentinel:
|
|
11041
|
+
* - header.parent -> root
|
|
11042
|
+
* - header._left -> min (or NIL)
|
|
11043
|
+
* - header._right -> max (or NIL)
|
|
11044
|
+
*
|
|
11045
|
+
* IMPORTANT:
|
|
11046
|
+
* - This header is NOT part of the actual tree.
|
|
11047
|
+
* - Do NOT use `header.left` / `header.right` accessors for wiring: those setters update `NIL.parent`
|
|
11048
|
+
* and can corrupt sentinel invariants / cause hangs. Only touch `header._left/_right`.
|
|
11049
|
+
*/
|
|
11050
|
+
_header;
|
|
11051
|
+
/**
|
|
11052
|
+
* (Internal) Cache of the current minimum and maximum nodes.
|
|
11053
|
+
* Used for fast-path insert/update when keys are monotonic or near-boundary.
|
|
11054
|
+
*/
|
|
11055
|
+
_minNode;
|
|
11056
|
+
_maxNode;
|
|
10972
11057
|
/**
|
|
10973
11058
|
* Get the current root node.
|
|
10974
11059
|
* @remarks Time O(1), Space O(1)
|
|
@@ -11002,18 +11087,387 @@ var RedBlackTree = class extends BST {
|
|
|
11002
11087
|
* @remarks Time O(n), Space O(1)
|
|
11003
11088
|
* @returns void
|
|
11004
11089
|
*/
|
|
11090
|
+
/**
|
|
11091
|
+
* Remove all nodes and clear internal caches.
|
|
11092
|
+
* @remarks Time O(n) average, Space O(1)
|
|
11093
|
+
*/
|
|
11005
11094
|
clear() {
|
|
11006
11095
|
super.clear();
|
|
11007
11096
|
this._root = this.NIL;
|
|
11097
|
+
this._header.parent = this.NIL;
|
|
11098
|
+
this._setMinCache(void 0);
|
|
11099
|
+
this._setMaxCache(void 0);
|
|
11008
11100
|
}
|
|
11009
11101
|
/**
|
|
11010
|
-
*
|
|
11011
|
-
*
|
|
11012
|
-
*
|
|
11013
|
-
* @
|
|
11014
|
-
|
|
11102
|
+
* (Internal) Find a node by key using a tight BST walk (no allocations).
|
|
11103
|
+
*
|
|
11104
|
+
* NOTE: This uses `header.parent` as the canonical root pointer.
|
|
11105
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11106
|
+
*/
|
|
11107
|
+
_findNodeByKey(key) {
|
|
11108
|
+
const NIL = this.NIL;
|
|
11109
|
+
const cmp = this._compare.bind(this);
|
|
11110
|
+
let cur = this._header.parent ?? NIL;
|
|
11111
|
+
while (cur !== NIL) {
|
|
11112
|
+
const c = cmp(key, cur.key);
|
|
11113
|
+
if (c < 0) cur = cur.left ?? NIL;
|
|
11114
|
+
else if (c > 0) cur = cur.right ?? NIL;
|
|
11115
|
+
else return cur;
|
|
11116
|
+
}
|
|
11117
|
+
return void 0;
|
|
11118
|
+
}
|
|
11119
|
+
/**
|
|
11120
|
+
* (Internal) In-order predecessor of a node in a BST.
|
|
11121
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11122
|
+
*/
|
|
11123
|
+
_predecessorOf(node) {
|
|
11124
|
+
const NIL = this.NIL;
|
|
11125
|
+
if (node.left && node.left !== NIL) {
|
|
11126
|
+
let cur2 = node.left;
|
|
11127
|
+
while (cur2.right && cur2.right !== NIL) cur2 = cur2.right;
|
|
11128
|
+
return cur2;
|
|
11129
|
+
}
|
|
11130
|
+
let cur = node;
|
|
11131
|
+
let p = node.parent;
|
|
11132
|
+
while (p && cur === p.left) {
|
|
11133
|
+
cur = p;
|
|
11134
|
+
p = p.parent;
|
|
11135
|
+
}
|
|
11136
|
+
return p;
|
|
11137
|
+
}
|
|
11138
|
+
/**
|
|
11139
|
+
* (Internal) In-order successor of a node in a BST.
|
|
11140
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11141
|
+
*/
|
|
11142
|
+
_successorOf(node) {
|
|
11143
|
+
const NIL = this.NIL;
|
|
11144
|
+
if (node.right && node.right !== NIL) {
|
|
11145
|
+
let cur2 = node.right;
|
|
11146
|
+
while (cur2.left && cur2.left !== NIL) cur2 = cur2.left;
|
|
11147
|
+
return cur2;
|
|
11148
|
+
}
|
|
11149
|
+
let cur = node;
|
|
11150
|
+
let p = node.parent;
|
|
11151
|
+
while (p && cur === p.right) {
|
|
11152
|
+
cur = p;
|
|
11153
|
+
p = p.parent;
|
|
11154
|
+
}
|
|
11155
|
+
return p;
|
|
11156
|
+
}
|
|
11157
|
+
/**
|
|
11158
|
+
* (Internal) Attach a new node directly under a known parent/side (no search).
|
|
11159
|
+
*
|
|
11160
|
+
* This is a performance-oriented helper used by boundary fast paths and hinted insertion.
|
|
11161
|
+
* It will:
|
|
11162
|
+
* - wire parent/child pointers (using accessors, so parent pointers are updated)
|
|
11163
|
+
* - initialize children to NIL
|
|
11164
|
+
* - mark the new node RED, then run insert fix-up
|
|
11165
|
+
*
|
|
11166
|
+
* Precondition: the chosen slot (parent.left/parent.right) is empty (NIL/null/undefined).
|
|
11167
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11168
|
+
*/
|
|
11169
|
+
_attachNewNode(parent, side, node) {
|
|
11170
|
+
const NIL = this.NIL;
|
|
11171
|
+
node.parent = parent;
|
|
11172
|
+
if (side === "left") parent.left = node;
|
|
11173
|
+
else parent.right = node;
|
|
11174
|
+
node.left = NIL;
|
|
11175
|
+
node.right = NIL;
|
|
11176
|
+
node.color = "RED";
|
|
11177
|
+
this._insertFixup(node);
|
|
11178
|
+
if (this.isRealNode(this._root)) this._root.color = "BLACK";
|
|
11179
|
+
}
|
|
11180
|
+
/**
|
|
11181
|
+
* (Internal) a single source of truth for min/max is header._left/_right.
|
|
11182
|
+
* Keep legacy _minNode/_maxNode mirrored for compatibility.
|
|
11183
|
+
* @remarks Time O(1), Space O(1)
|
|
11184
|
+
*/
|
|
11185
|
+
/**
|
|
11186
|
+
* (Internal) Update min cache pointers (header._left is the canonical min pointer).
|
|
11187
|
+
* @remarks Time O(1), Space O(1)
|
|
11188
|
+
*/
|
|
11189
|
+
_setMinCache(node) {
|
|
11190
|
+
this._minNode = node;
|
|
11191
|
+
this._header._left = node ?? this.NIL;
|
|
11192
|
+
}
|
|
11193
|
+
/**
|
|
11194
|
+
* (Internal) Update max cache pointers (header._right is the canonical max pointer).
|
|
11195
|
+
* @remarks Time O(1), Space O(1)
|
|
11196
|
+
*/
|
|
11197
|
+
_setMaxCache(node) {
|
|
11198
|
+
this._maxNode = node;
|
|
11199
|
+
this._header._right = node ?? this.NIL;
|
|
11200
|
+
}
|
|
11201
|
+
/**
|
|
11202
|
+
* (Internal) Core set implementation returning the affected node.
|
|
11203
|
+
*
|
|
11204
|
+
* Hot path goals:
|
|
11205
|
+
* - Avoid double walks (search+insert): do a single traversal that either updates or inserts.
|
|
11206
|
+
* - Use header min/max caches to fast-path boundary inserts.
|
|
11207
|
+
* - Keep header._left/_right as canonical min/max pointers.
|
|
11208
|
+
*
|
|
11209
|
+
* Return value:
|
|
11210
|
+
* - `{ node, created:false }` when an existing key is updated
|
|
11211
|
+
* - `{ node, created:true }` when a new node is inserted
|
|
11212
|
+
* - `undefined` only on unexpected internal failure.
|
|
11213
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11214
|
+
*/
|
|
11215
|
+
_setKVNode(key, nextValue) {
|
|
11216
|
+
const NIL = this.NIL;
|
|
11217
|
+
const comparator = this._comparator;
|
|
11218
|
+
const header = this._header;
|
|
11219
|
+
const minN = header._left ?? NIL;
|
|
11220
|
+
if (minN !== NIL) {
|
|
11221
|
+
const cMin = comparator(key, minN.key);
|
|
11222
|
+
if (cMin === 0) {
|
|
11223
|
+
if (this._isMapMode) {
|
|
11224
|
+
if (nextValue !== void 0) this._store.set(key, nextValue);
|
|
11225
|
+
else this._setValue(key, nextValue);
|
|
11226
|
+
} else minN.value = nextValue;
|
|
11227
|
+
return { node: minN, created: false };
|
|
11228
|
+
}
|
|
11229
|
+
const minL = minN.left;
|
|
11230
|
+
if (cMin < 0 && (minL === NIL || minL === null || minL === void 0)) {
|
|
11231
|
+
const newNode2 = this.createNode(key, nextValue);
|
|
11232
|
+
this._attachNewNode(minN, "left", newNode2);
|
|
11233
|
+
if (this._isMapMode) {
|
|
11234
|
+
if (nextValue !== void 0) this._store.set(newNode2.key, nextValue);
|
|
11235
|
+
else this._setValue(newNode2.key, nextValue);
|
|
11236
|
+
}
|
|
11237
|
+
this._size++;
|
|
11238
|
+
this._setMinCache(newNode2);
|
|
11239
|
+
if (header._right === NIL) this._setMaxCache(newNode2);
|
|
11240
|
+
return { node: newNode2, created: true };
|
|
11241
|
+
}
|
|
11242
|
+
if (cMin > 0) {
|
|
11243
|
+
const maxN = header._right ?? NIL;
|
|
11244
|
+
const cMax = comparator(key, maxN.key);
|
|
11245
|
+
if (cMax === 0) {
|
|
11246
|
+
if (this._isMapMode) {
|
|
11247
|
+
if (nextValue !== void 0) this._store.set(key, nextValue);
|
|
11248
|
+
else this._setValue(key, nextValue);
|
|
11249
|
+
} else maxN.value = nextValue;
|
|
11250
|
+
return { node: maxN, created: false };
|
|
11251
|
+
}
|
|
11252
|
+
const maxR = maxN.right;
|
|
11253
|
+
if (cMax > 0 && (maxR === NIL || maxR === null || maxR === void 0)) {
|
|
11254
|
+
const newNode2 = this.createNode(key, nextValue);
|
|
11255
|
+
this._attachNewNode(maxN, "right", newNode2);
|
|
11256
|
+
if (this._isMapMode) {
|
|
11257
|
+
if (nextValue !== void 0) this._store.set(newNode2.key, nextValue);
|
|
11258
|
+
else this._setValue(newNode2.key, nextValue);
|
|
11259
|
+
}
|
|
11260
|
+
this._size++;
|
|
11261
|
+
this._setMaxCache(newNode2);
|
|
11262
|
+
if (header._left === NIL) this._setMinCache(newNode2);
|
|
11263
|
+
return { node: newNode2, created: true };
|
|
11264
|
+
}
|
|
11265
|
+
}
|
|
11266
|
+
}
|
|
11267
|
+
const cmp = comparator;
|
|
11268
|
+
const isMapMode = this._isMapMode;
|
|
11269
|
+
const store = this._store;
|
|
11270
|
+
let current = this._header.parent ?? NIL;
|
|
11271
|
+
let parent;
|
|
11272
|
+
let lastCompared = 0;
|
|
11273
|
+
while (current !== NIL) {
|
|
11274
|
+
parent = current;
|
|
11275
|
+
lastCompared = cmp(key, current.key);
|
|
11276
|
+
if (lastCompared < 0) current = current.left ?? NIL;
|
|
11277
|
+
else if (lastCompared > 0) current = current.right ?? NIL;
|
|
11278
|
+
else {
|
|
11279
|
+
if (isMapMode) {
|
|
11280
|
+
if (nextValue !== void 0) store.set(key, nextValue);
|
|
11281
|
+
else this._setValue(key, nextValue);
|
|
11282
|
+
} else {
|
|
11283
|
+
current.value = nextValue;
|
|
11284
|
+
}
|
|
11285
|
+
return { node: current, created: false };
|
|
11286
|
+
}
|
|
11287
|
+
}
|
|
11288
|
+
const newNode = this.createNode(key, nextValue);
|
|
11289
|
+
newNode.parent = parent;
|
|
11290
|
+
if (!parent) {
|
|
11291
|
+
this._setRoot(newNode);
|
|
11292
|
+
} else if (lastCompared < 0) {
|
|
11293
|
+
parent.left = newNode;
|
|
11294
|
+
} else {
|
|
11295
|
+
parent.right = newNode;
|
|
11296
|
+
}
|
|
11297
|
+
newNode.left = NIL;
|
|
11298
|
+
newNode.right = NIL;
|
|
11299
|
+
newNode.color = "RED";
|
|
11300
|
+
this._insertFixup(newNode);
|
|
11301
|
+
if (this.isRealNode(this._root)) this._root.color = "BLACK";
|
|
11302
|
+
else return void 0;
|
|
11303
|
+
if (isMapMode) {
|
|
11304
|
+
if (nextValue !== void 0) store.set(newNode.key, nextValue);
|
|
11305
|
+
else this._setValue(newNode.key, nextValue);
|
|
11306
|
+
}
|
|
11307
|
+
this._size++;
|
|
11308
|
+
const hMin = this._header._left ?? NIL;
|
|
11309
|
+
const hMax = this._header._right ?? NIL;
|
|
11310
|
+
if (hMin === NIL || hMax === NIL) {
|
|
11311
|
+
this._setMinCache(newNode);
|
|
11312
|
+
this._setMaxCache(newNode);
|
|
11313
|
+
} else if (parent === hMax && lastCompared > 0) {
|
|
11314
|
+
this._setMaxCache(newNode);
|
|
11315
|
+
} else if (parent === hMin && lastCompared < 0) {
|
|
11316
|
+
this._setMinCache(newNode);
|
|
11317
|
+
} else {
|
|
11318
|
+
if (cmp(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
|
|
11319
|
+
if (cmp(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
|
|
11320
|
+
}
|
|
11321
|
+
return { node: newNode, created: true };
|
|
11322
|
+
}
|
|
11323
|
+
/**
|
|
11324
|
+
* (Internal) Boolean wrapper around `_setKVNode`.
|
|
11325
|
+
*
|
|
11326
|
+
* Includes a map-mode update fast-path:
|
|
11327
|
+
* - If `isMapMode=true` and the key already exists in `_store`, then updating the value does not
|
|
11328
|
+
* require any tree search/rotation (tree shape depends only on key).
|
|
11329
|
+
* - This path is intentionally limited to `nextValue !== undefined` to preserve existing
|
|
11330
|
+
* semantics for `undefined` values.
|
|
11331
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11332
|
+
*/
|
|
11333
|
+
_setKV(key, nextValue) {
|
|
11334
|
+
if (this._isMapMode && nextValue !== void 0) {
|
|
11335
|
+
const store = this._store;
|
|
11336
|
+
if (store.has(key)) {
|
|
11337
|
+
store.set(key, nextValue);
|
|
11338
|
+
return true;
|
|
11339
|
+
}
|
|
11340
|
+
}
|
|
11341
|
+
return this._setKVNode(key, nextValue) !== void 0;
|
|
11342
|
+
}
|
|
11343
|
+
/**
|
|
11344
|
+
* Insert/update using a hint node to speed up nearby insertions.
|
|
11345
|
+
*
|
|
11346
|
+
* close to the expected insertion position (often the previously returned node in a loop).
|
|
11347
|
+
*
|
|
11348
|
+
* When the hint is a good fit (sorted / nearly-sorted insertion), this can avoid most of the
|
|
11349
|
+
* normal root-to-leaf search and reduce constant factors.
|
|
11350
|
+
*
|
|
11351
|
+
* When the hint does not match (random workloads), this will fall back to the normal set path.
|
|
11352
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11015
11353
|
*/
|
|
11016
|
-
|
|
11354
|
+
setWithHintNode(key, value, hint) {
|
|
11355
|
+
if (!hint || !this.isRealNode(hint)) {
|
|
11356
|
+
return this._setKVNode(key, value)?.node;
|
|
11357
|
+
}
|
|
11358
|
+
const cmp = this._compare.bind(this);
|
|
11359
|
+
const c0 = cmp(key, hint.key);
|
|
11360
|
+
if (c0 === 0) {
|
|
11361
|
+
if (this._isMapMode) {
|
|
11362
|
+
if (value !== void 0) this._store.set(key, value);
|
|
11363
|
+
else this._setValue(key, value);
|
|
11364
|
+
} else hint.value = value;
|
|
11365
|
+
return hint;
|
|
11366
|
+
}
|
|
11367
|
+
if (c0 < 0) {
|
|
11368
|
+
if (!this.isRealNode(hint.left)) {
|
|
11369
|
+
const newNode = this.createNode(key, value);
|
|
11370
|
+
if (!this.isRealNode(newNode)) return void 0;
|
|
11371
|
+
this._attachNewNode(hint, "left", newNode);
|
|
11372
|
+
if (this._isMapMode) {
|
|
11373
|
+
if (value !== void 0) this._store.set(key, value);
|
|
11374
|
+
else this._setValue(key, value);
|
|
11375
|
+
}
|
|
11376
|
+
this._size++;
|
|
11377
|
+
const NIL = this.NIL;
|
|
11378
|
+
const hMin = this._header._left ?? NIL;
|
|
11379
|
+
if (hMin === NIL || this._compare(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
|
|
11380
|
+
const hMax = this._header._right ?? NIL;
|
|
11381
|
+
if (hMax === NIL || this._compare(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
|
|
11382
|
+
return newNode;
|
|
11383
|
+
}
|
|
11384
|
+
const pred = this._predecessorOf(hint);
|
|
11385
|
+
if (pred && cmp(pred.key, key) >= 0) {
|
|
11386
|
+
return this._setKVNode(key, value)?.node;
|
|
11387
|
+
}
|
|
11388
|
+
if (pred && !this.isRealNode(pred.right)) {
|
|
11389
|
+
const newNode = this.createNode(key, value);
|
|
11390
|
+
if (!this.isRealNode(newNode)) return void 0;
|
|
11391
|
+
this._attachNewNode(pred, "right", newNode);
|
|
11392
|
+
if (this._isMapMode) {
|
|
11393
|
+
if (value !== void 0) this._store.set(key, value);
|
|
11394
|
+
else this._setValue(key, value);
|
|
11395
|
+
}
|
|
11396
|
+
this._size++;
|
|
11397
|
+
const NIL = this.NIL;
|
|
11398
|
+
const hMin = this._header._left ?? NIL;
|
|
11399
|
+
if (hMin === NIL || this._compare(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
|
|
11400
|
+
const hMax = this._header._right ?? NIL;
|
|
11401
|
+
if (hMax === NIL || this._compare(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
|
|
11402
|
+
return newNode;
|
|
11403
|
+
}
|
|
11404
|
+
return this._setKVNode(key, value)?.node;
|
|
11405
|
+
}
|
|
11406
|
+
if (!this.isRealNode(hint.right)) {
|
|
11407
|
+
const newNode = this.createNode(key, value);
|
|
11408
|
+
if (!this.isRealNode(newNode)) return void 0;
|
|
11409
|
+
this._attachNewNode(hint, "right", newNode);
|
|
11410
|
+
if (this._isMapMode) {
|
|
11411
|
+
if (value !== void 0) this._store.set(key, value);
|
|
11412
|
+
else this._setValue(key, value);
|
|
11413
|
+
}
|
|
11414
|
+
this._size++;
|
|
11415
|
+
const NIL = this.NIL;
|
|
11416
|
+
const hMin = this._header._left ?? NIL;
|
|
11417
|
+
if (hMin === NIL || this._compare(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
|
|
11418
|
+
const hMax = this._header._right ?? NIL;
|
|
11419
|
+
if (hMax === NIL || this._compare(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
|
|
11420
|
+
return newNode;
|
|
11421
|
+
}
|
|
11422
|
+
const succ = this._successorOf(hint);
|
|
11423
|
+
if (succ && cmp(succ.key, key) <= 0) {
|
|
11424
|
+
return this._setKVNode(key, value)?.node;
|
|
11425
|
+
}
|
|
11426
|
+
if (succ && !this.isRealNode(succ.left)) {
|
|
11427
|
+
const newNode = this.createNode(key, value);
|
|
11428
|
+
if (!this.isRealNode(newNode)) return void 0;
|
|
11429
|
+
this._attachNewNode(succ, "left", newNode);
|
|
11430
|
+
if (this._isMapMode) {
|
|
11431
|
+
if (value !== void 0) this._store.set(key, value);
|
|
11432
|
+
else this._setValue(key, value);
|
|
11433
|
+
}
|
|
11434
|
+
this._size++;
|
|
11435
|
+
const NIL = this.NIL;
|
|
11436
|
+
const hMin = this._header._left ?? NIL;
|
|
11437
|
+
if (hMin === NIL || this._compare(newNode.key, hMin.key) < 0) this._setMinCache(newNode);
|
|
11438
|
+
const hMax = this._header._right ?? NIL;
|
|
11439
|
+
if (hMax === NIL || this._compare(newNode.key, hMax.key) > 0) this._setMaxCache(newNode);
|
|
11440
|
+
return newNode;
|
|
11441
|
+
}
|
|
11442
|
+
return this._setKVNode(key, value)?.node;
|
|
11443
|
+
}
|
|
11444
|
+
/**
|
|
11445
|
+
* Boolean wrapper for setWithHintNode.
|
|
11446
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11447
|
+
*/
|
|
11448
|
+
setWithHint(key, value, hint) {
|
|
11449
|
+
return this.setWithHintNode(key, value, hint) !== void 0;
|
|
11450
|
+
}
|
|
11451
|
+
/**
|
|
11452
|
+
* Insert or update a key/value (map mode) or key-only (set mode).
|
|
11453
|
+
*
|
|
11454
|
+
* This method is optimized for:
|
|
11455
|
+
* - monotonic inserts via min/max boundary fast paths
|
|
11456
|
+
* - updates via a single-pass search (no double walk)
|
|
11457
|
+
*
|
|
11458
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11459
|
+
*/
|
|
11460
|
+
set(keyNodeOrEntry, value) {
|
|
11461
|
+
if (!this.isNode(keyNodeOrEntry)) {
|
|
11462
|
+
if (keyNodeOrEntry === null || keyNodeOrEntry === void 0) return false;
|
|
11463
|
+
if (this.isEntry(keyNodeOrEntry)) {
|
|
11464
|
+
const key = keyNodeOrEntry[0];
|
|
11465
|
+
if (key === null || key === void 0) return false;
|
|
11466
|
+
const nextValue = value ?? keyNodeOrEntry[1];
|
|
11467
|
+
return this._setKV(key, nextValue);
|
|
11468
|
+
}
|
|
11469
|
+
return this._setKV(keyNodeOrEntry, value);
|
|
11470
|
+
}
|
|
11017
11471
|
const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
11018
11472
|
if (!this.isRealNode(newNode)) return false;
|
|
11019
11473
|
const insertStatus = this._insert(newNode);
|
|
@@ -11035,19 +11489,23 @@ var RedBlackTree = class extends BST {
|
|
|
11035
11489
|
}
|
|
11036
11490
|
/**
|
|
11037
11491
|
* Delete a node by key/node/entry and rebalance as needed.
|
|
11038
|
-
* @remarks Time O(log n), Space O(1)
|
|
11039
|
-
* @param
|
|
11492
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11493
|
+
* @param keyNodeEntryRawOrPredicate - Key, node, or [key, value] entry identifying the node to delete.
|
|
11040
11494
|
* @returns Array with deletion metadata (removed node, rebalancing hint if any).
|
|
11041
11495
|
*/
|
|
11042
|
-
delete(
|
|
11043
|
-
if (
|
|
11496
|
+
delete(keyNodeEntryRawOrPredicate) {
|
|
11497
|
+
if (keyNodeEntryRawOrPredicate === null) return [];
|
|
11044
11498
|
const results = [];
|
|
11045
11499
|
let nodeToDelete;
|
|
11046
|
-
if (this._isPredicate(
|
|
11047
|
-
else nodeToDelete = this.isRealNode(
|
|
11500
|
+
if (this._isPredicate(keyNodeEntryRawOrPredicate)) nodeToDelete = this.getNode(keyNodeEntryRawOrPredicate);
|
|
11501
|
+
else nodeToDelete = this.isRealNode(keyNodeEntryRawOrPredicate) ? keyNodeEntryRawOrPredicate : this.getNode(keyNodeEntryRawOrPredicate);
|
|
11048
11502
|
if (!nodeToDelete) {
|
|
11049
11503
|
return results;
|
|
11050
11504
|
}
|
|
11505
|
+
const willDeleteMin = nodeToDelete === this._minNode;
|
|
11506
|
+
const willDeleteMax = nodeToDelete === this._maxNode;
|
|
11507
|
+
const nextMin = willDeleteMin ? this._successorOf(nodeToDelete) : void 0;
|
|
11508
|
+
const nextMax = willDeleteMax ? this._predecessorOf(nodeToDelete) : void 0;
|
|
11051
11509
|
let originalColor = nodeToDelete.color;
|
|
11052
11510
|
let replacementNode;
|
|
11053
11511
|
if (!this.isRealNode(nodeToDelete.left)) {
|
|
@@ -11086,6 +11544,19 @@ var RedBlackTree = class extends BST {
|
|
|
11086
11544
|
}
|
|
11087
11545
|
if (this._isMapMode) this._store.delete(nodeToDelete.key);
|
|
11088
11546
|
this._size--;
|
|
11547
|
+
if (this._size <= 0) {
|
|
11548
|
+
this._setMinCache(void 0);
|
|
11549
|
+
this._setMaxCache(void 0);
|
|
11550
|
+
} else {
|
|
11551
|
+
if (willDeleteMin) this._setMinCache(nextMin);
|
|
11552
|
+
if (willDeleteMax) this._setMaxCache(nextMax);
|
|
11553
|
+
if (!this._minNode || !this.isRealNode(this._minNode)) {
|
|
11554
|
+
this._setMinCache(this.isRealNode(this._root) ? this.getLeftMost((n) => n, this._root) : void 0);
|
|
11555
|
+
}
|
|
11556
|
+
if (!this._maxNode || !this.isRealNode(this._maxNode)) {
|
|
11557
|
+
this._setMaxCache(this.isRealNode(this._root) ? this.getRightMost((n) => n, this._root) : void 0);
|
|
11558
|
+
}
|
|
11559
|
+
}
|
|
11089
11560
|
if (originalColor === "BLACK") {
|
|
11090
11561
|
this._deleteFixup(replacementNode);
|
|
11091
11562
|
}
|
|
@@ -11094,7 +11565,7 @@ var RedBlackTree = class extends BST {
|
|
|
11094
11565
|
}
|
|
11095
11566
|
/**
|
|
11096
11567
|
* Transform entries into a like-kind red-black tree with possibly different key/value types.
|
|
11097
|
-
* @remarks Time O(n), Space O(n)
|
|
11568
|
+
* @remarks Time O(n) average, Space O(n)
|
|
11098
11569
|
* @template MK
|
|
11099
11570
|
* @template MV
|
|
11100
11571
|
* @template MR
|
|
@@ -11107,44 +11578,65 @@ var RedBlackTree = class extends BST {
|
|
|
11107
11578
|
const out = this._createLike([], options);
|
|
11108
11579
|
let index = 0;
|
|
11109
11580
|
for (const [key, value] of this) {
|
|
11110
|
-
out.
|
|
11581
|
+
out.set(callback.call(thisArg, value, key, index++, this));
|
|
11111
11582
|
}
|
|
11112
11583
|
return out;
|
|
11113
11584
|
}
|
|
11585
|
+
/**
|
|
11586
|
+
* (Internal) Create an empty instance of the same concrete tree type.
|
|
11587
|
+
* @remarks Time O(1) average, Space O(1)
|
|
11588
|
+
*/
|
|
11114
11589
|
_createInstance(options) {
|
|
11115
11590
|
const Ctor = this.constructor;
|
|
11116
11591
|
return new Ctor([], { ...this._snapshotOptions(), ...options ?? {} });
|
|
11117
11592
|
}
|
|
11593
|
+
/**
|
|
11594
|
+
* (Internal) Create a like-kind tree (same concrete class) populated from an iterable.
|
|
11595
|
+
* @remarks Time O(m log m) average (m = iterable length), Space O(m)
|
|
11596
|
+
*/
|
|
11118
11597
|
_createLike(iter = [], options) {
|
|
11119
11598
|
const Ctor = this.constructor;
|
|
11120
11599
|
return new Ctor(iter, { ...this._snapshotOptions(), ...options ?? {} });
|
|
11121
11600
|
}
|
|
11601
|
+
/**
|
|
11602
|
+
* (Internal) Set the root pointer and keep header.parent in sync.
|
|
11603
|
+
* @remarks Time O(1), Space O(1)
|
|
11604
|
+
*/
|
|
11122
11605
|
_setRoot(v) {
|
|
11606
|
+
const NIL = this.NIL;
|
|
11123
11607
|
if (v) {
|
|
11124
11608
|
v.parent = void 0;
|
|
11125
11609
|
}
|
|
11126
11610
|
this._root = v;
|
|
11611
|
+
this._header.parent = v ?? NIL;
|
|
11127
11612
|
}
|
|
11613
|
+
/**
|
|
11614
|
+
* (Internal) Replace a node in place while preserving its color.
|
|
11615
|
+
* @remarks Time O(1) average, Space O(1)
|
|
11616
|
+
*/
|
|
11128
11617
|
_replaceNode(oldNode, newNode) {
|
|
11129
11618
|
newNode.color = oldNode.color;
|
|
11130
11619
|
return super._replaceNode(oldNode, newNode);
|
|
11131
11620
|
}
|
|
11132
11621
|
/**
|
|
11133
11622
|
* (Protected) Standard BST insert followed by red-black fix-up.
|
|
11134
|
-
* @remarks Time O(log n), Space O(1)
|
|
11623
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11135
11624
|
* @param node - Node to insert.
|
|
11136
11625
|
* @returns Status string: 'CREATED' or 'UPDATED'.
|
|
11137
11626
|
*/
|
|
11138
11627
|
_insert(node) {
|
|
11139
|
-
|
|
11140
|
-
|
|
11141
|
-
|
|
11628
|
+
const NIL = this.NIL;
|
|
11629
|
+
const cmp = this._compare.bind(this);
|
|
11630
|
+
let current = this._header.parent ?? NIL;
|
|
11631
|
+
let parent;
|
|
11632
|
+
let lastCompared = 0;
|
|
11633
|
+
while (current !== NIL) {
|
|
11142
11634
|
parent = current;
|
|
11143
|
-
|
|
11144
|
-
if (
|
|
11145
|
-
current = current.left ??
|
|
11146
|
-
} else if (
|
|
11147
|
-
current = current.right ??
|
|
11635
|
+
lastCompared = cmp(node.key, current.key);
|
|
11636
|
+
if (lastCompared < 0) {
|
|
11637
|
+
current = current.left ?? NIL;
|
|
11638
|
+
} else if (lastCompared > 0) {
|
|
11639
|
+
current = current.right ?? NIL;
|
|
11148
11640
|
} else {
|
|
11149
11641
|
this._replaceNode(current, node);
|
|
11150
11642
|
return "UPDATED";
|
|
@@ -11153,13 +11645,13 @@ var RedBlackTree = class extends BST {
|
|
|
11153
11645
|
node.parent = parent;
|
|
11154
11646
|
if (!parent) {
|
|
11155
11647
|
this._setRoot(node);
|
|
11156
|
-
} else if (
|
|
11648
|
+
} else if (lastCompared < 0) {
|
|
11157
11649
|
parent.left = node;
|
|
11158
11650
|
} else {
|
|
11159
11651
|
parent.right = node;
|
|
11160
11652
|
}
|
|
11161
|
-
node.left =
|
|
11162
|
-
node.right =
|
|
11653
|
+
node.left = NIL;
|
|
11654
|
+
node.right = NIL;
|
|
11163
11655
|
node.color = "RED";
|
|
11164
11656
|
this._insertFixup(node);
|
|
11165
11657
|
return "CREATED";
|
|
@@ -11185,55 +11677,66 @@ var RedBlackTree = class extends BST {
|
|
|
11185
11677
|
}
|
|
11186
11678
|
/**
|
|
11187
11679
|
* (Protected) Restore red-black properties after insertion (recolor/rotate).
|
|
11188
|
-
* @remarks Time O(log n), Space O(1)
|
|
11680
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11189
11681
|
* @param z - Recently inserted node.
|
|
11190
11682
|
* @returns void
|
|
11191
11683
|
*/
|
|
11192
11684
|
_insertFixup(z) {
|
|
11193
|
-
|
|
11194
|
-
|
|
11195
|
-
|
|
11685
|
+
const leftRotate = this._leftRotate.bind(this);
|
|
11686
|
+
const rightRotate = this._rightRotate.bind(this);
|
|
11687
|
+
while (z) {
|
|
11688
|
+
const p = z.parent;
|
|
11689
|
+
if (!p || p.color !== "RED") break;
|
|
11690
|
+
const gp = p.parent;
|
|
11691
|
+
if (!gp) break;
|
|
11692
|
+
if (p === gp.left) {
|
|
11693
|
+
const y = gp.right;
|
|
11196
11694
|
if (y?.color === "RED") {
|
|
11197
|
-
|
|
11695
|
+
p.color = "BLACK";
|
|
11198
11696
|
y.color = "BLACK";
|
|
11199
|
-
|
|
11200
|
-
z =
|
|
11201
|
-
|
|
11202
|
-
|
|
11203
|
-
|
|
11204
|
-
|
|
11205
|
-
|
|
11206
|
-
|
|
11207
|
-
|
|
11208
|
-
|
|
11209
|
-
|
|
11210
|
-
|
|
11697
|
+
gp.color = "RED";
|
|
11698
|
+
z = gp;
|
|
11699
|
+
continue;
|
|
11700
|
+
}
|
|
11701
|
+
if (z === p.right) {
|
|
11702
|
+
z = p;
|
|
11703
|
+
leftRotate(z);
|
|
11704
|
+
}
|
|
11705
|
+
const p2 = z?.parent;
|
|
11706
|
+
const gp2 = p2?.parent;
|
|
11707
|
+
if (p2 && gp2) {
|
|
11708
|
+
p2.color = "BLACK";
|
|
11709
|
+
gp2.color = "RED";
|
|
11710
|
+
rightRotate(gp2);
|
|
11211
11711
|
}
|
|
11212
11712
|
} else {
|
|
11213
|
-
const y =
|
|
11713
|
+
const y = gp.left;
|
|
11214
11714
|
if (y?.color === "RED") {
|
|
11215
|
-
|
|
11715
|
+
p.color = "BLACK";
|
|
11216
11716
|
y.color = "BLACK";
|
|
11217
|
-
|
|
11218
|
-
z =
|
|
11219
|
-
|
|
11220
|
-
|
|
11221
|
-
|
|
11222
|
-
|
|
11223
|
-
|
|
11224
|
-
|
|
11225
|
-
|
|
11226
|
-
|
|
11227
|
-
|
|
11228
|
-
|
|
11717
|
+
gp.color = "RED";
|
|
11718
|
+
z = gp;
|
|
11719
|
+
continue;
|
|
11720
|
+
}
|
|
11721
|
+
if (z === p.left) {
|
|
11722
|
+
z = p;
|
|
11723
|
+
rightRotate(z);
|
|
11724
|
+
}
|
|
11725
|
+
const p2 = z?.parent;
|
|
11726
|
+
const gp2 = p2?.parent;
|
|
11727
|
+
if (p2 && gp2) {
|
|
11728
|
+
p2.color = "BLACK";
|
|
11729
|
+
gp2.color = "RED";
|
|
11730
|
+
leftRotate(gp2);
|
|
11229
11731
|
}
|
|
11230
11732
|
}
|
|
11733
|
+
break;
|
|
11231
11734
|
}
|
|
11232
11735
|
if (this.isRealNode(this._root)) this._root.color = "BLACK";
|
|
11233
11736
|
}
|
|
11234
11737
|
/**
|
|
11235
11738
|
* (Protected) Restore red-black properties after deletion (recolor/rotate).
|
|
11236
|
-
* @remarks Time O(log n), Space O(1)
|
|
11739
|
+
* @remarks Time O(log n) average, Space O(1)
|
|
11237
11740
|
* @param node - Child that replaced the deleted node (may be undefined).
|
|
11238
11741
|
* @returns void
|
|
11239
11742
|
*/
|
|
@@ -11495,7 +11998,7 @@ var AVLTreeMultiMap = class extends AVLTree {
|
|
|
11495
11998
|
constructor(keysNodesEntriesOrRaws = [], options) {
|
|
11496
11999
|
super([], { ...options, isMapMode: true });
|
|
11497
12000
|
if (keysNodesEntriesOrRaws) {
|
|
11498
|
-
this.
|
|
12001
|
+
this.setMany(keysNodesEntriesOrRaws);
|
|
11499
12002
|
}
|
|
11500
12003
|
}
|
|
11501
12004
|
createNode(key, value = []) {
|
|
@@ -11515,27 +12018,27 @@ var AVLTreeMultiMap = class extends AVLTree {
|
|
|
11515
12018
|
* Insert a value or a list of values into the multimap. If the key exists, values are appended.
|
|
11516
12019
|
* @remarks Time O(log N + M), Space O(1)
|
|
11517
12020
|
* @param keyNodeOrEntry - Key, node, or [key, values] entry.
|
|
11518
|
-
* @param [value] - Single value to
|
|
12021
|
+
* @param [value] - Single value to set when a bare key is provided.
|
|
11519
12022
|
* @returns True if inserted or appended; false if ignored.
|
|
11520
12023
|
*/
|
|
11521
|
-
|
|
11522
|
-
if (this.isRealNode(keyNodeOrEntry)) return super.
|
|
12024
|
+
set(keyNodeOrEntry, value) {
|
|
12025
|
+
if (this.isRealNode(keyNodeOrEntry)) return super.set(keyNodeOrEntry);
|
|
11523
12026
|
const _commonAdd = /* @__PURE__ */ __name((key, values) => {
|
|
11524
12027
|
if (key === void 0 || key === null) return false;
|
|
11525
|
-
const
|
|
12028
|
+
const _setToValues = /* @__PURE__ */ __name(() => {
|
|
11526
12029
|
const existingValues = this.get(key);
|
|
11527
12030
|
if (existingValues !== void 0 && values !== void 0) {
|
|
11528
12031
|
for (const value2 of values) existingValues.push(value2);
|
|
11529
12032
|
return true;
|
|
11530
12033
|
}
|
|
11531
12034
|
return false;
|
|
11532
|
-
}, "
|
|
11533
|
-
const
|
|
12035
|
+
}, "_setToValues");
|
|
12036
|
+
const _setByNode = /* @__PURE__ */ __name(() => {
|
|
11534
12037
|
const existingNode = this.getNode(key);
|
|
11535
12038
|
if (this.isRealNode(existingNode)) {
|
|
11536
12039
|
const existingValues = this.get(existingNode);
|
|
11537
12040
|
if (existingValues === void 0) {
|
|
11538
|
-
super.
|
|
12041
|
+
super.set(key, values);
|
|
11539
12042
|
return true;
|
|
11540
12043
|
}
|
|
11541
12044
|
if (values !== void 0) {
|
|
@@ -11545,13 +12048,13 @@ var AVLTreeMultiMap = class extends AVLTree {
|
|
|
11545
12048
|
return false;
|
|
11546
12049
|
}
|
|
11547
12050
|
} else {
|
|
11548
|
-
return super.
|
|
12051
|
+
return super.set(key, values);
|
|
11549
12052
|
}
|
|
11550
|
-
}, "
|
|
12053
|
+
}, "_setByNode");
|
|
11551
12054
|
if (this._isMapMode) {
|
|
11552
|
-
return
|
|
12055
|
+
return _setByNode() || _setToValues();
|
|
11553
12056
|
}
|
|
11554
|
-
return
|
|
12057
|
+
return _setToValues() || _setByNode();
|
|
11555
12058
|
}, "_commonAdd");
|
|
11556
12059
|
if (this.isEntry(keyNodeOrEntry)) {
|
|
11557
12060
|
const [key, values] = keyNodeOrEntry;
|
|
@@ -11619,7 +12122,7 @@ var AVLTreeMultiMap = class extends AVLTree {
|
|
|
11619
12122
|
map(callback, options, thisArg) {
|
|
11620
12123
|
const out = this._createLike([], options);
|
|
11621
12124
|
let i = 0;
|
|
11622
|
-
for (const [k, v] of this) out.
|
|
12125
|
+
for (const [k, v] of this) out.set(callback.call(thisArg, v, k, i++, this));
|
|
11623
12126
|
return out;
|
|
11624
12127
|
}
|
|
11625
12128
|
/**
|
|
@@ -11802,7 +12305,7 @@ var TreeMultiMap = class extends RedBlackTree {
|
|
|
11802
12305
|
constructor(keysNodesEntriesOrRaws = [], options) {
|
|
11803
12306
|
super([], { ...options });
|
|
11804
12307
|
if (keysNodesEntriesOrRaws) {
|
|
11805
|
-
this.
|
|
12308
|
+
this.setMany(keysNodesEntriesOrRaws);
|
|
11806
12309
|
}
|
|
11807
12310
|
}
|
|
11808
12311
|
createNode(key, value = []) {
|
|
@@ -11822,27 +12325,27 @@ var TreeMultiMap = class extends RedBlackTree {
|
|
|
11822
12325
|
* Insert a value or a list of values into the multimap. If the key exists, values are appended.
|
|
11823
12326
|
* @remarks Time O(log N + M), Space O(1)
|
|
11824
12327
|
* @param keyNodeOrEntry - Key, node, or [key, values] entry.
|
|
11825
|
-
* @param [value] - Single value to
|
|
12328
|
+
* @param [value] - Single value to set when a bare key is provided.
|
|
11826
12329
|
* @returns True if inserted or appended; false if ignored.
|
|
11827
12330
|
*/
|
|
11828
|
-
|
|
11829
|
-
if (this.isRealNode(keyNodeOrEntry)) return super.
|
|
12331
|
+
set(keyNodeOrEntry, value) {
|
|
12332
|
+
if (this.isRealNode(keyNodeOrEntry)) return super.set(keyNodeOrEntry);
|
|
11830
12333
|
const _commonAdd = /* @__PURE__ */ __name((key, values) => {
|
|
11831
12334
|
if (key === void 0 || key === null) return false;
|
|
11832
|
-
const
|
|
12335
|
+
const _setToValues = /* @__PURE__ */ __name(() => {
|
|
11833
12336
|
const existingValues = this.get(key);
|
|
11834
12337
|
if (existingValues !== void 0 && values !== void 0) {
|
|
11835
12338
|
for (const value2 of values) existingValues.push(value2);
|
|
11836
12339
|
return true;
|
|
11837
12340
|
}
|
|
11838
12341
|
return false;
|
|
11839
|
-
}, "
|
|
11840
|
-
const
|
|
12342
|
+
}, "_setToValues");
|
|
12343
|
+
const _setByNode = /* @__PURE__ */ __name(() => {
|
|
11841
12344
|
const existingNode = this.getNode(key);
|
|
11842
12345
|
if (this.isRealNode(existingNode)) {
|
|
11843
12346
|
const existingValues = this.get(existingNode);
|
|
11844
12347
|
if (existingValues === void 0) {
|
|
11845
|
-
super.
|
|
12348
|
+
super.set(key, values);
|
|
11846
12349
|
return true;
|
|
11847
12350
|
}
|
|
11848
12351
|
if (values !== void 0) {
|
|
@@ -11852,13 +12355,13 @@ var TreeMultiMap = class extends RedBlackTree {
|
|
|
11852
12355
|
return false;
|
|
11853
12356
|
}
|
|
11854
12357
|
} else {
|
|
11855
|
-
return super.
|
|
12358
|
+
return super.set(key, values);
|
|
11856
12359
|
}
|
|
11857
|
-
}, "
|
|
12360
|
+
}, "_setByNode");
|
|
11858
12361
|
if (this._isMapMode) {
|
|
11859
|
-
return
|
|
12362
|
+
return _setByNode() || _setToValues();
|
|
11860
12363
|
}
|
|
11861
|
-
return
|
|
12364
|
+
return _setToValues() || _setByNode();
|
|
11862
12365
|
}, "_commonAdd");
|
|
11863
12366
|
if (this.isEntry(keyNodeOrEntry)) {
|
|
11864
12367
|
const [key, values] = keyNodeOrEntry;
|
|
@@ -11898,7 +12401,7 @@ var TreeMultiMap = class extends RedBlackTree {
|
|
|
11898
12401
|
map(callback, options, thisArg) {
|
|
11899
12402
|
const out = this._createLike([], options);
|
|
11900
12403
|
let i = 0;
|
|
11901
|
-
for (const [k, v] of this) out.
|
|
12404
|
+
for (const [k, v] of this) out.set(callback.call(thisArg, v, k, i++, this));
|
|
11902
12405
|
return out;
|
|
11903
12406
|
}
|
|
11904
12407
|
/**
|
|
@@ -12083,7 +12586,7 @@ var TreeCounter = class extends RedBlackTree {
|
|
|
12083
12586
|
*/
|
|
12084
12587
|
constructor(keysNodesEntriesOrRaws = [], options) {
|
|
12085
12588
|
super([], options);
|
|
12086
|
-
if (keysNodesEntriesOrRaws) this.
|
|
12589
|
+
if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
|
|
12087
12590
|
}
|
|
12088
12591
|
_count = 0;
|
|
12089
12592
|
/**
|
|
@@ -12123,10 +12626,10 @@ var TreeCounter = class extends RedBlackTree {
|
|
|
12123
12626
|
* @param [count] - How much to increase the node's count (default 1).
|
|
12124
12627
|
* @returns True if inserted/updated; false if ignored.
|
|
12125
12628
|
*/
|
|
12126
|
-
|
|
12629
|
+
set(keyNodeOrEntry, value, count = 1) {
|
|
12127
12630
|
const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value, count);
|
|
12128
12631
|
const orgCount = newNode?.count || 0;
|
|
12129
|
-
const isSuccessAdded = super.
|
|
12632
|
+
const isSuccessAdded = super.set(newNode, newValue);
|
|
12130
12633
|
if (isSuccessAdded) {
|
|
12131
12634
|
this._count += orgCount;
|
|
12132
12635
|
return true;
|
|
@@ -12137,16 +12640,16 @@ var TreeCounter = class extends RedBlackTree {
|
|
|
12137
12640
|
/**
|
|
12138
12641
|
* Delete a node (or decrement its count) and rebalance if needed.
|
|
12139
12642
|
* @remarks Time O(log N), Space O(1)
|
|
12140
|
-
* @param
|
|
12643
|
+
* @param keyNodeEntryRawOrPredicate - Key, node, or [key, value] entry identifying the node.
|
|
12141
12644
|
* @param [ignoreCount] - If true, remove the node regardless of its count.
|
|
12142
12645
|
* @returns Array of deletion results including deleted node and a rebalance hint when present.
|
|
12143
12646
|
*/
|
|
12144
|
-
delete(
|
|
12145
|
-
if (
|
|
12647
|
+
delete(keyNodeEntryRawOrPredicate, ignoreCount = false) {
|
|
12648
|
+
if (keyNodeEntryRawOrPredicate === null) return [];
|
|
12146
12649
|
const results = [];
|
|
12147
12650
|
let nodeToDelete;
|
|
12148
|
-
if (this._isPredicate(
|
|
12149
|
-
else nodeToDelete = this.isRealNode(
|
|
12651
|
+
if (this._isPredicate(keyNodeEntryRawOrPredicate)) nodeToDelete = this.getNode(keyNodeEntryRawOrPredicate);
|
|
12652
|
+
else nodeToDelete = this.isRealNode(keyNodeEntryRawOrPredicate) ? keyNodeEntryRawOrPredicate : this.getNode(keyNodeEntryRawOrPredicate);
|
|
12150
12653
|
if (!nodeToDelete) {
|
|
12151
12654
|
return results;
|
|
12152
12655
|
}
|
|
@@ -12189,7 +12692,6 @@ var TreeCounter = class extends RedBlackTree {
|
|
|
12189
12692
|
if (ignoreCount || nodeToDelete.count <= 1) {
|
|
12190
12693
|
if (successor.right !== null) {
|
|
12191
12694
|
this._transplant(successor, successor.right);
|
|
12192
|
-
this._count -= nodeToDelete.count;
|
|
12193
12695
|
}
|
|
12194
12696
|
} else {
|
|
12195
12697
|
nodeToDelete.count--;
|
|
@@ -12279,7 +12781,7 @@ var TreeCounter = class extends RedBlackTree {
|
|
|
12279
12781
|
const out = this._createLike([], options);
|
|
12280
12782
|
let index = 0;
|
|
12281
12783
|
for (const [key, value] of this) {
|
|
12282
|
-
out.
|
|
12784
|
+
out.set(callback.call(thisArg, value, key, index++, this));
|
|
12283
12785
|
}
|
|
12284
12786
|
return out;
|
|
12285
12787
|
}
|
|
@@ -12292,6 +12794,11 @@ var TreeCounter = class extends RedBlackTree {
|
|
|
12292
12794
|
const out = this._createInstance();
|
|
12293
12795
|
this._clone(out);
|
|
12294
12796
|
out._count = this._count;
|
|
12797
|
+
for (const node of this.dfs((n) => n, "IN")) {
|
|
12798
|
+
if (!node) continue;
|
|
12799
|
+
const outNode = out.getNode(node.key);
|
|
12800
|
+
if (outNode) outNode.count = node.count;
|
|
12801
|
+
}
|
|
12295
12802
|
return out;
|
|
12296
12803
|
}
|
|
12297
12804
|
/**
|
|
@@ -12535,7 +13042,7 @@ var AVLTreeCounter = class extends AVLTree {
|
|
|
12535
13042
|
*/
|
|
12536
13043
|
constructor(keysNodesEntriesOrRaws = [], options) {
|
|
12537
13044
|
super([], options);
|
|
12538
|
-
if (keysNodesEntriesOrRaws) this.
|
|
13045
|
+
if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
|
|
12539
13046
|
}
|
|
12540
13047
|
_count = 0;
|
|
12541
13048
|
get count() {
|
|
@@ -12570,11 +13077,11 @@ var AVLTreeCounter = class extends AVLTree {
|
|
|
12570
13077
|
* @param [count] - How much to increase the node's count (default 1).
|
|
12571
13078
|
* @returns True if inserted/updated; false if ignored.
|
|
12572
13079
|
*/
|
|
12573
|
-
|
|
13080
|
+
set(keyNodeOrEntry, value, count = 1) {
|
|
12574
13081
|
const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value, count);
|
|
12575
13082
|
if (newNode === void 0) return false;
|
|
12576
13083
|
const orgNodeCount = newNode?.count || 0;
|
|
12577
|
-
const inserted = super.
|
|
13084
|
+
const inserted = super.set(newNode, newValue);
|
|
12578
13085
|
if (inserted) {
|
|
12579
13086
|
this._count += orgNodeCount;
|
|
12580
13087
|
}
|
|
@@ -12682,9 +13189,9 @@ var AVLTreeCounter = class extends AVLTree {
|
|
|
12682
13189
|
clone() {
|
|
12683
13190
|
const out = this._createInstance();
|
|
12684
13191
|
if (this._isMapMode) {
|
|
12685
|
-
this.bfs((node) => out.
|
|
13192
|
+
this.bfs((node) => out.set(node.key, void 0, node.count));
|
|
12686
13193
|
} else {
|
|
12687
|
-
this.bfs((node) => out.
|
|
13194
|
+
this.bfs((node) => out.set(node.key, node.value, node.count));
|
|
12688
13195
|
}
|
|
12689
13196
|
if (this._isMapMode) out._store = this._store;
|
|
12690
13197
|
return out;
|
|
@@ -12704,7 +13211,7 @@ var AVLTreeCounter = class extends AVLTree {
|
|
|
12704
13211
|
const out = this._createLike([], options);
|
|
12705
13212
|
let index = 0;
|
|
12706
13213
|
for (const [key, value] of this) {
|
|
12707
|
-
out.
|
|
13214
|
+
out.set(callback.call(thisArg, value, key, index++, this));
|
|
12708
13215
|
}
|
|
12709
13216
|
return out;
|
|
12710
13217
|
}
|