data-structure-typed 1.50.5 → 1.50.6

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.
Files changed (28) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +13 -13
  3. package/benchmark/report.html +13 -13
  4. package/benchmark/report.json +168 -144
  5. package/dist/cjs/data-structures/binary-tree/binary-tree.js +19 -19
  6. package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
  7. package/dist/cjs/data-structures/binary-tree/rb-tree.d.ts +158 -135
  8. package/dist/cjs/data-structures/binary-tree/rb-tree.js +415 -386
  9. package/dist/cjs/data-structures/binary-tree/rb-tree.js.map +1 -1
  10. package/dist/cjs/data-structures/binary-tree/tree-multi-map.d.ts +1 -0
  11. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +84 -76
  12. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  13. package/dist/mjs/data-structures/binary-tree/binary-tree.js +19 -19
  14. package/dist/mjs/data-structures/binary-tree/rb-tree.d.ts +158 -135
  15. package/dist/mjs/data-structures/binary-tree/rb-tree.js +412 -386
  16. package/dist/mjs/data-structures/binary-tree/tree-multi-map.d.ts +1 -0
  17. package/dist/mjs/data-structures/binary-tree/tree-multi-map.js +84 -76
  18. package/dist/umd/data-structure-typed.js +477 -431
  19. package/dist/umd/data-structure-typed.min.js +2 -2
  20. package/dist/umd/data-structure-typed.min.js.map +1 -1
  21. package/package.json +1 -1
  22. package/src/data-structures/binary-tree/binary-tree.ts +19 -19
  23. package/src/data-structures/binary-tree/rb-tree.ts +437 -395
  24. package/src/data-structures/binary-tree/tree-multi-map.ts +85 -82
  25. package/test/performance/data-structures/binary-tree/rb-tree.test.ts +26 -16
  26. package/test/unit/data-structures/binary-tree/overall.test.ts +23 -21
  27. package/test/unit/data-structures/binary-tree/rb-tree.test.ts +168 -105
  28. package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +311 -192
@@ -51,6 +51,7 @@ export declare class TreeMultiMap<K = any, V = any, NODE extends TreeMultiMapNod
51
51
  * @returns the sum of the count property of all nodes in the tree.
52
52
  */
53
53
  get count(): number;
54
+ getMutableCount(): number;
54
55
  /**
55
56
  * The function creates a new TreeMultiMapNode object with the specified key, value, and count.
56
57
  * @param {K} key - The key parameter represents the key of the node being created. It is of type K,
@@ -54,10 +54,12 @@ export class TreeMultiMap extends RedBlackTree {
54
54
  * @returns the sum of the count property of all nodes in the tree.
55
55
  */
56
56
  get count() {
57
+ return this._count;
58
+ }
59
+ getMutableCount() {
57
60
  let sum = 0;
58
61
  this.dfs(node => (sum += node.count));
59
62
  return sum;
60
- // return this._count;
61
63
  }
62
64
  /**
63
65
  * The function creates a new TreeMultiMapNode object with the specified key, value, and count.
@@ -153,14 +155,15 @@ export class TreeMultiMap extends RedBlackTree {
153
155
  */
154
156
  add(keyOrNodeOrEntry, value, count = 1) {
155
157
  const newNode = this.keyValueOrEntryToNode(keyOrNodeOrEntry, value, count);
156
- if (newNode === undefined)
158
+ const orgCount = newNode?.count || 0;
159
+ const isSuccessAdded = super.add(newNode);
160
+ if (isSuccessAdded) {
161
+ this._count += orgCount;
162
+ return true;
163
+ }
164
+ else {
157
165
  return false;
158
- const orgNodeCount = newNode?.count || 0;
159
- const inserted = super.add(newNode);
160
- if (inserted) {
161
- this._count += orgNodeCount;
162
166
  }
163
- return true;
164
167
  }
165
168
  /**
166
169
  * Time Complexity: O(log n)
@@ -187,86 +190,91 @@ export class TreeMultiMap extends RedBlackTree {
187
190
  * @returns an array of BinaryTreeDeleteResult<NODE> objects.
188
191
  */
189
192
  delete(identifier, callback = this._defaultOneParamCallback, ignoreCount = false) {
190
- const deleteResults = [];
191
193
  if (identifier === null)
192
- return deleteResults;
193
- // Helper function to perform deletion
194
- const deleteHelper = (node) => {
195
- // Initialize targetNode to the sentinel node
196
- let targetNode = this._Sentinel;
197
- let currentNode;
198
- // Find the node to be deleted based on the identifier
199
- while (node !== this._Sentinel) {
200
- // Update targetNode if the current node matches the identifier
201
- if (node && callback(node) === identifier) {
202
- targetNode = node;
203
- }
204
- // Move to the right or left based on the comparison with the identifier
205
- if (node && identifier && callback(node) <= identifier) {
206
- node = node.right;
207
- }
208
- else {
209
- node = node?.left;
210
- }
194
+ return [];
195
+ const results = [];
196
+ const nodeToDelete = this.isRealNode(identifier) ? identifier : this.getNode(identifier, callback);
197
+ if (!nodeToDelete) {
198
+ return results;
199
+ }
200
+ let originalColor = nodeToDelete.color;
201
+ let replacementNode;
202
+ if (!this.isRealNode(nodeToDelete.left)) {
203
+ replacementNode = nodeToDelete.right;
204
+ if (ignoreCount || nodeToDelete.count <= 1) {
205
+ this._transplant(nodeToDelete, nodeToDelete.right);
206
+ this._count -= nodeToDelete.count;
211
207
  }
212
- // If the target node is not found, decrement size and return
213
- if (targetNode === this._Sentinel) {
214
- return;
208
+ else {
209
+ nodeToDelete.count--;
210
+ this._count--;
211
+ results.push({ deleted: nodeToDelete, needBalanced: undefined });
212
+ return results;
215
213
  }
216
- if (ignoreCount || targetNode.count <= 1) {
217
- // Store the parent of the target node and its original color
218
- let parentNode = targetNode;
219
- let parentNodeOriginalColor = parentNode.color;
220
- // Handle deletion based on the number of children of the target node
221
- if (targetNode.left === this._Sentinel) {
222
- // Target node has no left child - deletion case 1
223
- currentNode = targetNode.right;
224
- this._rbTransplant(targetNode, targetNode.right);
225
- }
226
- else if (targetNode.right === this._Sentinel) {
227
- // Target node has no right child - deletion case 2
228
- currentNode = targetNode.left;
229
- this._rbTransplant(targetNode, targetNode.left);
214
+ }
215
+ else if (!this.isRealNode(nodeToDelete.right)) {
216
+ replacementNode = nodeToDelete.left;
217
+ if (ignoreCount || nodeToDelete.count <= 1) {
218
+ this._transplant(nodeToDelete, nodeToDelete.left);
219
+ this._count -= nodeToDelete.count;
220
+ }
221
+ else {
222
+ nodeToDelete.count--;
223
+ this._count--;
224
+ results.push({ deleted: nodeToDelete, needBalanced: undefined });
225
+ return results;
226
+ }
227
+ }
228
+ else {
229
+ const successor = this.getLeftMost(nodeToDelete.right);
230
+ if (successor) {
231
+ originalColor = successor.color;
232
+ replacementNode = successor.right;
233
+ if (successor.parent === nodeToDelete) {
234
+ if (this.isRealNode(replacementNode)) {
235
+ replacementNode.parent = successor;
236
+ }
230
237
  }
231
238
  else {
232
- // Target node has both left and right children - deletion case 3
233
- parentNode = this.getLeftMost(targetNode.right);
234
- parentNodeOriginalColor = parentNode.color;
235
- currentNode = parentNode.right;
236
- if (parentNode.parent === targetNode) {
237
- // Target node's right child becomes its parent's left child
238
- currentNode.parent = parentNode;
239
+ if (ignoreCount || nodeToDelete.count <= 1) {
240
+ this._transplant(successor, successor.right);
241
+ this._count -= nodeToDelete.count;
239
242
  }
240
243
  else {
241
- // Replace parentNode with its right child and update connections
242
- this._rbTransplant(parentNode, parentNode.right);
243
- parentNode.right = targetNode.right;
244
- parentNode.right.parent = parentNode;
244
+ nodeToDelete.count--;
245
+ this._count--;
246
+ results.push({ deleted: nodeToDelete, needBalanced: undefined });
247
+ return results;
248
+ }
249
+ successor.right = nodeToDelete.right;
250
+ if (this.isRealNode(successor.right)) {
251
+ successor.right.parent = successor;
245
252
  }
246
- // Replace the target node with its in-order successor
247
- this._rbTransplant(targetNode, parentNode);
248
- parentNode.left = targetNode.left;
249
- parentNode.left.parent = parentNode;
250
- parentNode.color = targetNode.color;
251
253
  }
252
- // Fix the Red-Black Tree properties after deletion
253
- if (parentNodeOriginalColor === RBTNColor.BLACK) {
254
- this._fixDelete(currentNode);
254
+ if (ignoreCount || nodeToDelete.count <= 1) {
255
+ this._transplant(nodeToDelete, successor);
256
+ this._count -= nodeToDelete.count;
255
257
  }
256
- // Decrement the size and store information about the deleted node
257
- this._size--;
258
- this._count -= targetNode.count;
259
- deleteResults.push({ deleted: targetNode, needBalanced: undefined });
260
- }
261
- else {
262
- targetNode.count--;
263
- this._count--;
258
+ else {
259
+ nodeToDelete.count--;
260
+ this._count--;
261
+ results.push({ deleted: nodeToDelete, needBalanced: undefined });
262
+ return results;
263
+ }
264
+ successor.left = nodeToDelete.left;
265
+ if (this.isRealNode(successor.left)) {
266
+ successor.left.parent = successor;
267
+ }
268
+ successor.color = nodeToDelete.color;
264
269
  }
265
- };
266
- // Call the helper function with the root of the tree
267
- deleteHelper(this.root);
268
- // Return the result array
269
- return deleteResults;
270
+ }
271
+ this._size--;
272
+ // If the original color was black, fix the tree
273
+ if (originalColor === RBTNColor.BLACK) {
274
+ this._deleteFixup(replacementNode);
275
+ }
276
+ results.push({ deleted: nodeToDelete, needBalanced: undefined });
277
+ return results;
270
278
  }
271
279
  /**
272
280
  * Time Complexity: O(1)