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