doubly-linked-list-typed 1.53.6 → 1.53.8

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 (62) hide show
  1. package/README.md +6 -6
  2. package/dist/common/index.d.ts +12 -0
  3. package/dist/common/index.js +28 -0
  4. package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +1 -1
  5. package/dist/data-structures/binary-tree/avl-tree-multi-map.js +9 -12
  6. package/dist/data-structures/binary-tree/avl-tree.js +2 -2
  7. package/dist/data-structures/binary-tree/binary-tree.d.ts +55 -20
  8. package/dist/data-structures/binary-tree/binary-tree.js +102 -68
  9. package/dist/data-structures/binary-tree/bst.d.ts +131 -37
  10. package/dist/data-structures/binary-tree/bst.js +222 -69
  11. package/dist/data-structures/binary-tree/index.d.ts +1 -1
  12. package/dist/data-structures/binary-tree/index.js +1 -1
  13. package/dist/data-structures/binary-tree/{rb-tree.d.ts → red-black-tree.d.ts} +53 -0
  14. package/dist/data-structures/binary-tree/{rb-tree.js → red-black-tree.js} +56 -3
  15. package/dist/data-structures/binary-tree/tree-multi-map.d.ts +2 -2
  16. package/dist/data-structures/binary-tree/tree-multi-map.js +7 -7
  17. package/dist/data-structures/hash/hash-map.d.ts +30 -0
  18. package/dist/data-structures/hash/hash-map.js +30 -0
  19. package/dist/data-structures/heap/heap.d.ts +26 -9
  20. package/dist/data-structures/heap/heap.js +37 -17
  21. package/dist/data-structures/linked-list/doubly-linked-list.d.ts +54 -9
  22. package/dist/data-structures/linked-list/doubly-linked-list.js +80 -19
  23. package/dist/data-structures/linked-list/singly-linked-list.d.ts +35 -2
  24. package/dist/data-structures/linked-list/singly-linked-list.js +55 -11
  25. package/dist/data-structures/queue/deque.d.ts +37 -8
  26. package/dist/data-structures/queue/deque.js +73 -29
  27. package/dist/data-structures/queue/queue.d.ts +41 -1
  28. package/dist/data-structures/queue/queue.js +51 -9
  29. package/dist/data-structures/stack/stack.d.ts +27 -10
  30. package/dist/data-structures/stack/stack.js +39 -20
  31. package/dist/data-structures/trie/trie.d.ts +111 -6
  32. package/dist/data-structures/trie/trie.js +123 -14
  33. package/dist/index.d.ts +2 -1
  34. package/dist/index.js +2 -1
  35. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
  36. package/dist/types/data-structures/binary-tree/bst.d.ts +3 -2
  37. package/dist/types/data-structures/binary-tree/rb-tree.d.ts +1 -1
  38. package/dist/types/utils/utils.d.ts +10 -6
  39. package/dist/utils/utils.js +4 -2
  40. package/package.json +2 -2
  41. package/src/common/index.ts +25 -0
  42. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +9 -11
  43. package/src/data-structures/binary-tree/avl-tree.ts +3 -2
  44. package/src/data-structures/binary-tree/binary-tree.ts +110 -66
  45. package/src/data-structures/binary-tree/bst.ts +232 -72
  46. package/src/data-structures/binary-tree/index.ts +1 -1
  47. package/src/data-structures/binary-tree/{rb-tree.ts → red-black-tree.ts} +56 -3
  48. package/src/data-structures/binary-tree/tree-multi-map.ts +6 -6
  49. package/src/data-structures/hash/hash-map.ts +30 -0
  50. package/src/data-structures/heap/heap.ts +72 -49
  51. package/src/data-structures/linked-list/doubly-linked-list.ts +173 -105
  52. package/src/data-structures/linked-list/singly-linked-list.ts +61 -11
  53. package/src/data-structures/queue/deque.ts +72 -28
  54. package/src/data-structures/queue/queue.ts +50 -7
  55. package/src/data-structures/stack/stack.ts +39 -20
  56. package/src/data-structures/trie/trie.ts +123 -13
  57. package/src/index.ts +2 -1
  58. package/src/types/data-structures/binary-tree/binary-tree.ts +1 -1
  59. package/src/types/data-structures/binary-tree/bst.ts +3 -2
  60. package/src/types/data-structures/binary-tree/rb-tree.ts +1 -1
  61. package/src/types/utils/utils.ts +16 -10
  62. package/src/utils/utils.ts +4 -2
@@ -4,6 +4,7 @@ exports.BST = exports.BSTNode = void 0;
4
4
  const binary_tree_1 = require("./binary-tree");
5
5
  const queue_1 = require("../queue");
6
6
  const utils_1 = require("../../utils");
7
+ const common_1 = require("../../common");
7
8
  class BSTNode extends binary_tree_1.BinaryTreeNode {
8
9
  constructor(key, value) {
9
10
  super(key, value);
@@ -58,6 +59,62 @@ exports.BSTNode = BSTNode;
58
59
  * 5. Logarithmic Operations: Ideal operations like insertion, deletion, and searching are O(log n) time-efficient.
59
60
  * 6. Balance Variability: Can become unbalanced; special types maintain balance.
60
61
  * 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.
62
+ * @example
63
+ * // Merge 3 sorted datasets
64
+ * const dataset1 = new BST<number, string>([
65
+ * [1, 'A'],
66
+ * [7, 'G']
67
+ * ]);
68
+ * const dataset2 = [
69
+ * [2, 'B'],
70
+ * [6, 'F']
71
+ * ];
72
+ * const dataset3 = new BST<number, string>([
73
+ * [3, 'C'],
74
+ * [5, 'E'],
75
+ * [4, 'D']
76
+ * ]);
77
+ *
78
+ * // Merge datasets into a single BinarySearchTree
79
+ * const merged = new BST<number, string>(dataset1);
80
+ * merged.addMany(dataset2);
81
+ * merged.merge(dataset3);
82
+ *
83
+ * // Verify merged dataset is in sorted order
84
+ * console.log([...merged.values()]); // ['A', 'B', 'C', 'D', 'E', 'F', 'G']
85
+ * @example
86
+ * // Find elements in a range
87
+ * const bst = new BST<number>([10, 5, 15, 3, 7, 12, 18]);
88
+ * console.log(bst.search(new Range(5, 10))); // [10, 5, 7]
89
+ * console.log(bst.rangeSearch([4, 12], node => node.key.toString())); // ['10', '12', '5', '7']
90
+ * console.log(bst.search(new Range(4, 12, true, false))); // [10, 5, 7]
91
+ * console.log(bst.rangeSearch([15, 20])); // [15, 18]
92
+ * console.log(bst.search(new Range(15, 20, false))); // [18]
93
+ * @example
94
+ * // Find lowest common ancestor
95
+ * const bst = new BST<number>([20, 10, 30, 5, 15, 25, 35, 3, 7, 12, 18]);
96
+ *
97
+ * // LCA helper function
98
+ * const findLCA = (num1: number, num2: number): number | undefined => {
99
+ * const path1 = bst.getPathToRoot(num1);
100
+ * const path2 = bst.getPathToRoot(num2);
101
+ * // Find the first common ancestor
102
+ * return findFirstCommon(path1, path2);
103
+ * };
104
+ *
105
+ * function findFirstCommon(arr1: number[], arr2: number[]): number | undefined {
106
+ * for (const num of arr1) {
107
+ * if (arr2.indexOf(num) !== -1) {
108
+ * return num;
109
+ * }
110
+ * }
111
+ * return undefined;
112
+ * }
113
+ *
114
+ * // Assertions
115
+ * console.log(findLCA(3, 10)); // 7
116
+ * console.log(findLCA(5, 35)); // 15
117
+ * console.log(findLCA(20, 30)); // 25
61
118
  */
62
119
  class BST extends binary_tree_1.BinaryTree {
63
120
  /**
@@ -71,21 +128,33 @@ class BST extends binary_tree_1.BinaryTree {
71
128
  constructor(keysNodesEntriesOrRaws = [], options) {
72
129
  super([], options);
73
130
  this._root = undefined;
74
- this._DEFAULT_COMPARATOR = (a, b) => {
131
+ this._isReverse = false;
132
+ this._comparator = (a, b) => {
133
+ if ((0, utils_1.isComparable)(a) && (0, utils_1.isComparable)(b)) {
134
+ if (a > b)
135
+ return 1;
136
+ if (a < b)
137
+ return -1;
138
+ return 0;
139
+ }
140
+ if (this._extractComparable) {
141
+ if (this._extractComparable(a) > this._extractComparable(b))
142
+ return 1;
143
+ if (this._extractComparable(a) < this._extractComparable(b))
144
+ return -1;
145
+ return 0;
146
+ }
75
147
  if (typeof a === 'object' || typeof b === 'object') {
76
- throw TypeError(`When comparing object types, a custom comparator must be defined in the constructor's options parameter.`);
148
+ throw TypeError(`When comparing object types, a custom extractComparable must be defined in the constructor's options parameter.`);
77
149
  }
78
- if (a > b)
79
- return 1;
80
- if (a < b)
81
- return -1;
82
150
  return 0;
83
151
  };
84
- this._comparator = this._DEFAULT_COMPARATOR;
85
152
  if (options) {
86
- const { comparator } = options;
87
- if (comparator)
88
- this._comparator = comparator;
153
+ const { extractComparable, isReverse } = options;
154
+ if (typeof extractComparable === 'function')
155
+ this._extractComparable = extractComparable;
156
+ if (isReverse !== undefined)
157
+ this._isReverse = isReverse;
89
158
  }
90
159
  if (keysNodesEntriesOrRaws)
91
160
  this.addMany(keysNodesEntriesOrRaws);
@@ -97,6 +166,14 @@ class BST extends binary_tree_1.BinaryTree {
97
166
  get root() {
98
167
  return this._root;
99
168
  }
169
+ /**
170
+ * The above function is a getter method in TypeScript that returns the value of the private property
171
+ * `_isReverse`.
172
+ * @returns The `isReverse` property of the object, which is a boolean value.
173
+ */
174
+ get isReverse() {
175
+ return this._isReverse;
176
+ }
100
177
  /**
101
178
  * The function creates a new BSTNode with the given key and value and returns it.
102
179
  * @param {K} key - The key parameter is of type K, which represents the type of the key for the node
@@ -116,7 +193,7 @@ class BST extends binary_tree_1.BinaryTree {
116
193
  * @returns a new instance of the BST class with the provided options.
117
194
  */
118
195
  createTree(options) {
119
- return new BST([], Object.assign({ iterationType: this.iterationType, isMapMode: this._isMapMode, comparator: this._comparator, toEntryFn: this._toEntryFn }, options));
196
+ return new BST([], Object.assign({ iterationType: this.iterationType, isMapMode: this._isMapMode, extractComparable: this._extractComparable, toEntryFn: this._toEntryFn, isReverse: this._isReverse }, options));
120
197
  }
121
198
  /**
122
199
  * The function overrides a method and converts a key, value pair or entry or raw element to a node.
@@ -127,8 +204,8 @@ class BST extends binary_tree_1.BinaryTree {
127
204
  * value associated with a key in a key-value pair.
128
205
  * @returns either a NODE object or undefined.
129
206
  */
130
- keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value) {
131
- const [node, entryValue] = super.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
207
+ _keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value) {
208
+ const [node, entryValue] = super._keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
132
209
  if (node === null)
133
210
  return [undefined, undefined];
134
211
  return [node, value !== null && value !== void 0 ? value : entryValue];
@@ -167,11 +244,11 @@ class BST extends binary_tree_1.BinaryTree {
167
244
  * @param {any} key - The `key` parameter is a value that will be checked to determine if it is of
168
245
  * type `K`.
169
246
  * @returns The `override isKey(key: any): key is K` function is returning a boolean value based on
170
- * the result of the `isComparable` function with the condition `this.comparator !==
247
+ * the result of the `isComparable` function with the condition `this._compare !==
171
248
  * this._DEFAULT_COMPARATOR`.
172
249
  */
173
250
  isKey(key) {
174
- return (0, utils_1.isComparable)(key, this.comparator !== this._DEFAULT_COMPARATOR);
251
+ return (0, utils_1.isComparable)(key, this._extractComparable !== undefined);
175
252
  }
176
253
  /**
177
254
  * Time Complexity: O(log n)
@@ -185,7 +262,7 @@ class BST extends binary_tree_1.BinaryTree {
185
262
  * @returns a boolean value.
186
263
  */
187
264
  add(keyNodeEntryOrRaw, value) {
188
- const [newNode, newValue] = this.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
265
+ const [newNode, newValue] = this._keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
189
266
  if (newNode === undefined)
190
267
  return false;
191
268
  if (this._root === undefined) {
@@ -197,13 +274,13 @@ class BST extends binary_tree_1.BinaryTree {
197
274
  }
198
275
  let current = this._root;
199
276
  while (current !== undefined) {
200
- if (this.comparator(current.key, newNode.key) === 0) {
277
+ if (this._compare(current.key, newNode.key) === 0) {
201
278
  this._replaceNode(current, newNode);
202
279
  if (this._isMapMode)
203
280
  this._setValue(current.key, newValue);
204
281
  return true;
205
282
  }
206
- else if (this.comparator(current.key, newNode.key) > 0) {
283
+ else if (this._compare(current.key, newNode.key) > 0) {
207
284
  if (current.left === undefined) {
208
285
  current.left = newNode;
209
286
  if (this._isMapMode)
@@ -290,7 +367,7 @@ class BST extends binary_tree_1.BinaryTree {
290
367
  keyB = b;
291
368
  }
292
369
  if (keyA !== undefined && keyA !== null && keyB !== undefined && keyB !== null) {
293
- return this.comparator(keyA, keyB);
370
+ return this._compare(keyA, keyB);
294
371
  }
295
372
  return 0;
296
373
  });
@@ -328,30 +405,47 @@ class BST extends binary_tree_1.BinaryTree {
328
405
  }
329
406
  return inserted;
330
407
  }
408
+ /**
409
+ * Time Complexity: O(n)
410
+ * Space Complexity: O(1)
411
+ *
412
+ * The `merge` function overrides the base class method by adding elements from another
413
+ * binary search tree.
414
+ * @param anotherTree - `anotherTree` is an instance of a Binary Search Tree (BST) with key type `K`,
415
+ * value type `V`, return type `R`, node type `NODE`, and tree type `TREE`.
416
+ */
417
+ merge(anotherTree) {
418
+ this.addMany(anotherTree, [], false);
419
+ }
331
420
  /**
332
421
  * Time Complexity: O(log n)
333
422
  * Space Complexity: O(k + log n)
334
423
  *
335
- * The function `getNodes` in TypeScript overrides the base class method to retrieve nodes based on a
336
- * given keyNodeEntryRawOrPredicate and iteration type.
337
- * @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate - The `keyNodeEntryRawOrPredicate`
338
- * parameter in the `getNodes` method is used to filter the nodes that will be returned. It can be a
339
- * key, a node, an entry, or a custom keyNodeEntryRawOrPredicate function that determines whether a node should be
340
- * included in the result.
341
- * @param [onlyOne=false] - The `onlyOne` parameter in the `getNodes` method is a boolean flag that
342
- * determines whether to return only the first node that matches the keyNodeEntryRawOrPredicate (`true`) or all nodes
343
- * that match the keyNodeEntryRawOrPredicate (`false`). If `onlyOne` is set to `true`, the method will stop iterating
344
- * and
345
- * @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
346
- * `getNodes` method is used to specify the starting point for traversing the tree when searching for
347
- * nodes that match a given keyNodeEntryRawOrPredicate. It represents the root node of the subtree where the search
348
- * should begin. If not explicitly provided, the default value for `begin
349
- * @param {IterationType} iterationType - The `iterationType` parameter in the `getNodes` method
350
- * specifies the type of iteration to be performed when traversing the nodes of a binary tree. It can
351
- * have two possible values:
352
- * @returns The `getNodes` method returns an array of nodes that satisfy the given keyNodeEntryRawOrPredicate.
424
+ * The function `search` in TypeScript overrides the search behavior in a binary tree structure based
425
+ * on specified criteria.
426
+ * @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate - The
427
+ * `keyNodeEntryRawOrPredicate` parameter in the `override search` method can accept one of the
428
+ * following types:
429
+ * @param [onlyOne=false] - The `onlyOne` parameter is a boolean flag that determines whether the
430
+ * search should stop after finding the first matching node. If `onlyOne` is set to `true`, the
431
+ * search will return as soon as a matching node is found. If `onlyOne` is set to `false`, the
432
+ * @param {C} callback - The `callback` parameter in the `override search` function is a function
433
+ * that will be called on each node that matches the search criteria. It is of type `C`, which
434
+ * extends `NodeCallback<NODE>`. The callback function should accept a node of type `NODE` as its
435
+ * argument and
436
+ * @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `override search`
437
+ * method represents the node from which the search operation will begin. It is the starting point
438
+ * for searching within the tree data structure. The method ensures that the `startNode` is a valid
439
+ * node before proceeding with the search operation. If the `
440
+ * @param {IterationType} iterationType - The `iterationType` parameter in the `override search`
441
+ * function determines the type of iteration to be used during the search operation. It can have two
442
+ * possible values:
443
+ * @returns The `override search` method returns an array of values that match the search criteria
444
+ * specified by the input parameters. The method performs a search operation on a binary tree
445
+ * structure based on the provided key, predicate, and other options. The search results are
446
+ * collected in an array and returned as the output of the method.
353
447
  */
354
- getNodes(keyNodeEntryRawOrPredicate, onlyOne = false, startNode = this._root, iterationType = this.iterationType) {
448
+ search(keyNodeEntryRawOrPredicate, onlyOne = false, callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
355
449
  if (keyNodeEntryRawOrPredicate === undefined)
356
450
  return [];
357
451
  if (keyNodeEntryRawOrPredicate === null)
@@ -359,28 +453,60 @@ class BST extends binary_tree_1.BinaryTree {
359
453
  startNode = this.ensureNode(startNode);
360
454
  if (!startNode)
361
455
  return [];
362
- const callback = this._ensurePredicate(keyNodeEntryRawOrPredicate);
456
+ let predicate;
457
+ const isRange = this.isRange(keyNodeEntryRawOrPredicate);
458
+ // Set predicate based on parameter type
459
+ if (isRange) {
460
+ predicate = node => keyNodeEntryRawOrPredicate.isInRange(node.key, this._comparator);
461
+ }
462
+ else {
463
+ predicate = this._ensurePredicate(keyNodeEntryRawOrPredicate);
464
+ }
465
+ const isToLeftByRange = (cur) => {
466
+ if (isRange) {
467
+ const range = keyNodeEntryRawOrPredicate;
468
+ const leftS = this.isReverse ? range.high : range.low;
469
+ const leftI = this.isReverse ? range.includeHigh : range.includeLow;
470
+ return (leftI && this._compare(cur.key, leftS) >= 0) || (!leftI && this._compare(cur.key, leftS) > 0);
471
+ }
472
+ return false;
473
+ };
474
+ const isToRightByRange = (cur) => {
475
+ if (isRange) {
476
+ const range = keyNodeEntryRawOrPredicate;
477
+ const rightS = this.isReverse ? range.low : range.high;
478
+ const rightI = this.isReverse ? range.includeLow : range.includeLow;
479
+ return (rightI && this._compare(cur.key, rightS) <= 0) || (!rightI && this._compare(cur.key, rightS) < 0);
480
+ }
481
+ return false;
482
+ };
363
483
  const ans = [];
364
484
  if (iterationType === 'RECURSIVE') {
365
485
  const dfs = (cur) => {
366
- if (callback(cur)) {
367
- ans.push(cur);
486
+ if (predicate(cur)) {
487
+ ans.push(callback(cur));
368
488
  if (onlyOne)
369
489
  return;
370
490
  }
371
491
  if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right))
372
492
  return;
373
- if (!this._isPredicate(keyNodeEntryRawOrPredicate)) {
374
- const benchmarkKey = this._getKey(keyNodeEntryRawOrPredicate);
493
+ if (isRange) {
494
+ if (this.isRealNode(cur.left) && isToLeftByRange(cur))
495
+ dfs(cur.left);
496
+ if (this.isRealNode(cur.right) && isToRightByRange(cur))
497
+ dfs(cur.right);
498
+ }
499
+ else if (!this._isPredicate(keyNodeEntryRawOrPredicate)) {
500
+ const benchmarkKey = this._extractKey(keyNodeEntryRawOrPredicate);
375
501
  if (this.isRealNode(cur.left) &&
376
502
  benchmarkKey !== null &&
377
503
  benchmarkKey !== undefined &&
378
- this.comparator(cur.key, benchmarkKey) > 0)
504
+ this._compare(cur.key, benchmarkKey) > 0)
379
505
  dfs(cur.left);
380
506
  if (this.isRealNode(cur.right) &&
381
507
  benchmarkKey !== null &&
382
508
  benchmarkKey !== undefined &&
383
- this.comparator(cur.key, benchmarkKey) < 0)
509
+ this._compare(cur.key, benchmarkKey) < 0)
384
510
  dfs(cur.right);
385
511
  }
386
512
  else {
@@ -396,22 +522,28 @@ class BST extends binary_tree_1.BinaryTree {
396
522
  const stack = [startNode];
397
523
  while (stack.length > 0) {
398
524
  const cur = stack.pop();
399
- if (callback(cur)) {
400
- ans.push(cur);
525
+ if (predicate(cur)) {
526
+ ans.push(callback(cur));
401
527
  if (onlyOne)
402
528
  return ans;
403
529
  }
404
- if (!this._isPredicate(keyNodeEntryRawOrPredicate)) {
405
- const benchmarkKey = this._getKey(keyNodeEntryRawOrPredicate);
530
+ if (isRange) {
531
+ if (this.isRealNode(cur.left) && isToLeftByRange(cur))
532
+ stack.push(cur.left);
533
+ if (this.isRealNode(cur.right) && isToRightByRange(cur))
534
+ stack.push(cur.right);
535
+ }
536
+ else if (!this._isPredicate(keyNodeEntryRawOrPredicate)) {
537
+ const benchmarkKey = this._extractKey(keyNodeEntryRawOrPredicate);
406
538
  if (this.isRealNode(cur.right) &&
407
539
  benchmarkKey !== null &&
408
540
  benchmarkKey !== undefined &&
409
- this.comparator(cur.key, benchmarkKey) < 0)
541
+ this._compare(cur.key, benchmarkKey) < 0)
410
542
  stack.push(cur.right);
411
543
  if (this.isRealNode(cur.left) &&
412
544
  benchmarkKey !== null &&
413
545
  benchmarkKey !== undefined &&
414
- this.comparator(cur.key, benchmarkKey) > 0)
546
+ this._compare(cur.key, benchmarkKey) > 0)
415
547
  stack.push(cur.left);
416
548
  }
417
549
  else {
@@ -424,6 +556,31 @@ class BST extends binary_tree_1.BinaryTree {
424
556
  }
425
557
  return ans;
426
558
  }
559
+ /**
560
+ * Time Complexity: O(log n)
561
+ * Space Complexity: O(n)
562
+ *
563
+ * The `rangeSearch` function searches for nodes within a specified range in a binary search tree.
564
+ * @param {Range<K> | [K, K]} range - The `range` parameter in the `rangeSearch` function can be
565
+ * either a `Range` object or an array of two elements representing the range boundaries.
566
+ * @param {C} callback - The `callback` parameter in the `rangeSearch` function is a callback
567
+ * function that is used to process each node that is found within the specified range during the
568
+ * search operation. It is of type `NodeCallback<NODE>`, where `NODE` is the type of nodes in the
569
+ * data structure.
570
+ * @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `rangeSearch`
571
+ * function represents the node from which the search for nodes within the specified range will
572
+ * begin. It is the starting point for the range search operation.
573
+ * @param {IterationType} iterationType - The `iterationType` parameter in the `rangeSearch` function
574
+ * is used to specify the type of iteration to be performed during the search operation. It has a
575
+ * default value of `this.iterationType`, which suggests that it is likely a property of the class or
576
+ * object that the `rangeSearch`
577
+ * @returns The `rangeSearch` function is returning the result of calling the `search` method with
578
+ * the specified parameters.
579
+ */
580
+ rangeSearch(range, callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
581
+ const searchRange = range instanceof common_1.Range ? range : new common_1.Range(range[0], range[1]);
582
+ return this.search(searchRange, false, callback, startNode, iterationType);
583
+ }
427
584
  /**
428
585
  * Time Complexity: O(log n)
429
586
  * Space Complexity: O(1)
@@ -448,22 +605,6 @@ class BST extends binary_tree_1.BinaryTree {
448
605
  var _a;
449
606
  return (_a = this.getNodes(keyNodeEntryRawOrPredicate, true, startNode, iterationType)[0]) !== null && _a !== void 0 ? _a : undefined;
450
607
  }
451
- /**
452
- * Time Complexity: O(log n)
453
- * Space Complexity: O(1)
454
- *
455
- * The function `getNodeByKey` returns a node with a specific key from a tree data structure.
456
- * @param {K} key - The key parameter is the value used to search for a specific node in the tree. It
457
- * is typically a unique identifier or a value that can be used to determine the position of the node
458
- * in the tree structure.
459
- * @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter is an optional
460
- * parameter that specifies the type of iteration to be used when searching for a node in the tree.
461
- * It has a default value of `'ITERATIVE'`.
462
- * @returns The method is returning a NODE object or undefined.
463
- */
464
- getNodeByKey(key, iterationType = this.iterationType) {
465
- return this.getNode(key, this._root, iterationType);
466
- }
467
608
  /**
468
609
  * Time complexity: O(n)
469
610
  * Space complexity: O(n)
@@ -559,9 +700,10 @@ class BST extends binary_tree_1.BinaryTree {
559
700
  const targetKey = targetNodeEnsured.key;
560
701
  if (iterationType === 'RECURSIVE') {
561
702
  const dfs = (cur) => {
562
- const compared = this.comparator(cur.key, targetKey);
703
+ const compared = this._compare(cur.key, targetKey);
563
704
  if (Math.sign(compared) === lesserOrGreater)
564
705
  ans.push(callback(cur));
706
+ // TODO here can be optimized to O(log n)
565
707
  if (this.isRealNode(cur.left))
566
708
  dfs(cur.left);
567
709
  if (this.isRealNode(cur.right))
@@ -575,7 +717,7 @@ class BST extends binary_tree_1.BinaryTree {
575
717
  while (queue.size > 0) {
576
718
  const cur = queue.shift();
577
719
  if (this.isRealNode(cur)) {
578
- const compared = this.comparator(cur.key, targetKey);
720
+ const compared = this._compare(cur.key, targetKey);
579
721
  if (Math.sign(compared) === lesserOrGreater)
580
722
  ans.push(callback(cur));
581
723
  if (this.isRealNode(cur.left))
@@ -705,6 +847,14 @@ class BST extends binary_tree_1.BinaryTree {
705
847
  get comparator() {
706
848
  return this._comparator;
707
849
  }
850
+ /**
851
+ * This function returns the value of the `_extractComparable` property.
852
+ * @returns The method `extractComparable()` is being returned, which is a getter method for the
853
+ * `_extractComparable` property.
854
+ */
855
+ get extractComparable() {
856
+ return this._extractComparable;
857
+ }
708
858
  /**
709
859
  * The function sets the root of a tree-like structure and updates the parent property of the new
710
860
  * root.
@@ -716,5 +866,8 @@ class BST extends binary_tree_1.BinaryTree {
716
866
  }
717
867
  this._root = v;
718
868
  }
869
+ _compare(a, b) {
870
+ return this._isReverse ? -this._comparator(a, b) : this._comparator(a, b);
871
+ }
719
872
  }
720
873
  exports.BST = BST;
@@ -3,6 +3,6 @@ export * from './bst';
3
3
  export * from './binary-indexed-tree';
4
4
  export * from './segment-tree';
5
5
  export * from './avl-tree';
6
- export * from './rb-tree';
6
+ export * from './red-black-tree';
7
7
  export * from './avl-tree-multi-map';
8
8
  export * from './tree-multi-map';
@@ -19,6 +19,6 @@ __exportStar(require("./bst"), exports);
19
19
  __exportStar(require("./binary-indexed-tree"), exports);
20
20
  __exportStar(require("./segment-tree"), exports);
21
21
  __exportStar(require("./avl-tree"), exports);
22
- __exportStar(require("./rb-tree"), exports);
22
+ __exportStar(require("./red-black-tree"), exports);
23
23
  __exportStar(require("./avl-tree-multi-map"), exports);
24
24
  __exportStar(require("./tree-multi-map"), exports);
@@ -26,6 +26,59 @@ export declare class RedBlackTreeNode<K = any, V = any, NODE extends RedBlackTre
26
26
  */
27
27
  set color(value: RBTNColor);
28
28
  }
29
+ /**
30
+ * 1. Efficient self-balancing, but not completely balanced. Compared with AVLTree, the addition and deletion efficiency is high but the query efficiency is slightly lower.
31
+ * 2. It is BST itself. Compared with Heap which is not completely ordered, RedBlackTree is completely ordered.
32
+ * @example
33
+ * // Find elements in a range
34
+ * const bst = new RedBlackTree<number>([10, 5, 15, 3, 7, 12, 18]);
35
+ * console.log(bst.search(new Range(5, 10))); // [5, 10, 7]
36
+ * console.log(bst.search(new Range(4, 12))); // [5, 10, 12, 7]
37
+ * console.log(bst.search(new Range(15, 20))); // [15, 18]
38
+ * @example
39
+ * // using Red-Black Tree as a price-based index for stock data
40
+ * // Define the structure of individual stock records
41
+ * interface StockRecord {
42
+ * price: number; // Stock price (key for indexing)
43
+ * symbol: string; // Stock ticker symbol
44
+ * volume: number; // Trade volume
45
+ * }
46
+ *
47
+ * // Simulate stock market data as it might come from an external feed
48
+ * const marketStockData: StockRecord[] = [
49
+ * { price: 142.5, symbol: 'AAPL', volume: 1000000 },
50
+ * { price: 335.2, symbol: 'MSFT', volume: 800000 },
51
+ * { price: 3285.04, symbol: 'AMZN', volume: 500000 },
52
+ * { price: 267.98, symbol: 'META', volume: 750000 },
53
+ * { price: 234.57, symbol: 'GOOGL', volume: 900000 }
54
+ * ];
55
+ *
56
+ * // Extend the stock record type to include metadata for database usage
57
+ * type StockTableRecord = StockRecord & { lastUpdated: Date };
58
+ *
59
+ * // Create a Red-Black Tree to index stock records by price
60
+ * // Simulates a database index with stock price as the key for quick lookups
61
+ * const priceIndex = new RedBlackTree<number, StockTableRecord, StockRecord>(marketStockData, {
62
+ * toEntryFn: stockRecord => [
63
+ * stockRecord.price, // Use stock price as the key
64
+ * {
65
+ * ...stockRecord,
66
+ * lastUpdated: new Date() // Add a timestamp for when the record was indexed
67
+ * }
68
+ * ]
69
+ * });
70
+ *
71
+ * // Query the stock with the highest price
72
+ * const highestPricedStock = priceIndex.getRightMost();
73
+ * console.log(priceIndex.get(highestPricedStock)?.symbol); // 'AMZN' // Amazon has the highest price
74
+ *
75
+ * // Query stocks within a specific price range (200 to 400)
76
+ * const stocksInRange = priceIndex.rangeSearch(
77
+ * [200, 400], // Price range
78
+ * node => priceIndex.get(node)?.symbol // Extract stock symbols for the result
79
+ * );
80
+ * console.log(stocksInRange); // ['GOOGL', 'MSFT', 'META']
81
+ */
29
82
  export declare class RedBlackTree<K = any, V = any, R = object, NODE extends RedBlackTreeNode<K, V, NODE> = RedBlackTreeNode<K, V, RedBlackTreeNodeNested<K, V>>, TREE extends RedBlackTree<K, V, R, NODE, TREE> = RedBlackTree<K, V, R, NODE, RedBlackTreeNested<K, V, R, NODE>>> extends BST<K, V, R, NODE, TREE> implements IBinaryTree<K, V, R, NODE, TREE> {
30
83
  /**
31
84
  * This is the constructor function for a Red-Black Tree data structure in TypeScript.
@@ -34,6 +34,59 @@ class RedBlackTreeNode extends bst_1.BSTNode {
34
34
  }
35
35
  }
36
36
  exports.RedBlackTreeNode = RedBlackTreeNode;
37
+ /**
38
+ * 1. Efficient self-balancing, but not completely balanced. Compared with AVLTree, the addition and deletion efficiency is high but the query efficiency is slightly lower.
39
+ * 2. It is BST itself. Compared with Heap which is not completely ordered, RedBlackTree is completely ordered.
40
+ * @example
41
+ * // Find elements in a range
42
+ * const bst = new RedBlackTree<number>([10, 5, 15, 3, 7, 12, 18]);
43
+ * console.log(bst.search(new Range(5, 10))); // [5, 10, 7]
44
+ * console.log(bst.search(new Range(4, 12))); // [5, 10, 12, 7]
45
+ * console.log(bst.search(new Range(15, 20))); // [15, 18]
46
+ * @example
47
+ * // using Red-Black Tree as a price-based index for stock data
48
+ * // Define the structure of individual stock records
49
+ * interface StockRecord {
50
+ * price: number; // Stock price (key for indexing)
51
+ * symbol: string; // Stock ticker symbol
52
+ * volume: number; // Trade volume
53
+ * }
54
+ *
55
+ * // Simulate stock market data as it might come from an external feed
56
+ * const marketStockData: StockRecord[] = [
57
+ * { price: 142.5, symbol: 'AAPL', volume: 1000000 },
58
+ * { price: 335.2, symbol: 'MSFT', volume: 800000 },
59
+ * { price: 3285.04, symbol: 'AMZN', volume: 500000 },
60
+ * { price: 267.98, symbol: 'META', volume: 750000 },
61
+ * { price: 234.57, symbol: 'GOOGL', volume: 900000 }
62
+ * ];
63
+ *
64
+ * // Extend the stock record type to include metadata for database usage
65
+ * type StockTableRecord = StockRecord & { lastUpdated: Date };
66
+ *
67
+ * // Create a Red-Black Tree to index stock records by price
68
+ * // Simulates a database index with stock price as the key for quick lookups
69
+ * const priceIndex = new RedBlackTree<number, StockTableRecord, StockRecord>(marketStockData, {
70
+ * toEntryFn: stockRecord => [
71
+ * stockRecord.price, // Use stock price as the key
72
+ * {
73
+ * ...stockRecord,
74
+ * lastUpdated: new Date() // Add a timestamp for when the record was indexed
75
+ * }
76
+ * ]
77
+ * });
78
+ *
79
+ * // Query the stock with the highest price
80
+ * const highestPricedStock = priceIndex.getRightMost();
81
+ * console.log(priceIndex.get(highestPricedStock)?.symbol); // 'AMZN' // Amazon has the highest price
82
+ *
83
+ * // Query stocks within a specific price range (200 to 400)
84
+ * const stocksInRange = priceIndex.rangeSearch(
85
+ * [200, 400], // Price range
86
+ * node => priceIndex.get(node)?.symbol // Extract stock symbols for the result
87
+ * );
88
+ * console.log(stocksInRange); // ['GOOGL', 'MSFT', 'META']
89
+ */
37
90
  class RedBlackTree extends bst_1.BST {
38
91
  /**
39
92
  * This is the constructor function for a Red-Black Tree data structure in TypeScript.
@@ -83,7 +136,7 @@ class RedBlackTree extends bst_1.BST {
83
136
  * @returns a new instance of a RedBlackTree object.
84
137
  */
85
138
  createTree(options) {
86
- return new RedBlackTree([], Object.assign({ iterationType: this.iterationType, isMapMode: this._isMapMode, comparator: this._comparator, toEntryFn: this._toEntryFn }, options));
139
+ return new RedBlackTree([], Object.assign({ iterationType: this.iterationType, isMapMode: this._isMapMode, extractComparable: this._extractComparable, toEntryFn: this._toEntryFn }, options));
87
140
  }
88
141
  /**
89
142
  * Time Complexity: O(1)
@@ -160,7 +213,7 @@ class RedBlackTree extends bst_1.BST {
160
213
  * returns true. If the node cannot be added or updated, the method returns false.
161
214
  */
162
215
  add(keyNodeEntryOrRaw, value) {
163
- const [newNode, newValue] = this.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
216
+ const [newNode, newValue] = this._keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
164
217
  if (!this.isRealNode(newNode))
165
218
  return false;
166
219
  const insertStatus = this._insert(newNode);
@@ -303,7 +356,7 @@ class RedBlackTree extends bst_1.BST {
303
356
  let parent = undefined;
304
357
  while (this.isRealNode(current)) {
305
358
  parent = current;
306
- const compared = this.comparator(node.key, current.key);
359
+ const compared = this._compare(node.key, current.key);
307
360
  if (compared < 0) {
308
361
  current = (_a = current.left) !== null && _a !== void 0 ? _a : this.NIL;
309
362
  }
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import type { BinaryTreeDeleteResult, BSTNOptKeyOrNode, BTNRep, IterationType, RBTNColor, TreeMultiMapNested, TreeMultiMapNodeNested, TreeMultiMapOptions } from '../../types';
9
9
  import { IBinaryTree } from '../../interfaces';
10
- import { RedBlackTree, RedBlackTreeNode } from './rb-tree';
10
+ import { RedBlackTree, RedBlackTreeNode } from './red-black-tree';
11
11
  export declare class TreeMultiMapNode<K = any, V = any, NODE extends TreeMultiMapNode<K, V, NODE> = TreeMultiMapNodeNested<K, V>> extends RedBlackTreeNode<K, V, NODE> {
12
12
  /**
13
13
  * The constructor function initializes a Red-Black Tree node with a key, value, count, and color.
@@ -96,7 +96,7 @@ export declare class TreeMultiMap<K = any, V = any, R = object, NODE extends Tre
96
96
  * times the key-value pair should be added to the data structure. If not provided, it defaults to 1.
97
97
  * @returns either a NODE object or undefined.
98
98
  */
99
- keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V, count?: number): [NODE | undefined, V | undefined];
99
+ protected _keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V, count?: number): [NODE | undefined, V | undefined];
100
100
  /**
101
101
  * The function checks if the input is an instance of the TreeMultiMapNode class.
102
102
  * @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter