red-black-tree-typed 1.53.7 → 1.54.1

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 (114) hide show
  1. package/README.md +52 -0
  2. package/dist/common/index.js +5 -0
  3. package/dist/data-structures/base/iterable-entry-base.js +4 -4
  4. package/dist/data-structures/binary-tree/avl-tree-counter.d.ts +213 -0
  5. package/dist/data-structures/binary-tree/avl-tree-counter.js +407 -0
  6. package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +71 -170
  7. package/dist/data-structures/binary-tree/avl-tree-multi-map.js +133 -328
  8. package/dist/data-structures/binary-tree/avl-tree.d.ts +103 -69
  9. package/dist/data-structures/binary-tree/avl-tree.js +130 -70
  10. package/dist/data-structures/binary-tree/binary-indexed-tree.d.ts +3 -0
  11. package/dist/data-structures/binary-tree/binary-indexed-tree.js +3 -0
  12. package/dist/data-structures/binary-tree/binary-tree.d.ts +268 -202
  13. package/dist/data-structures/binary-tree/binary-tree.js +311 -263
  14. package/dist/data-structures/binary-tree/bst.d.ts +193 -139
  15. package/dist/data-structures/binary-tree/bst.js +248 -164
  16. package/dist/data-structures/binary-tree/index.d.ts +3 -1
  17. package/dist/data-structures/binary-tree/index.js +3 -1
  18. package/dist/data-structures/binary-tree/red-black-tree.d.ts +286 -0
  19. package/dist/data-structures/binary-tree/{rb-tree.js → red-black-tree.js} +176 -107
  20. package/dist/data-structures/binary-tree/tree-counter.d.ts +212 -0
  21. package/dist/data-structures/binary-tree/tree-counter.js +444 -0
  22. package/dist/data-structures/binary-tree/tree-multi-map.d.ts +78 -170
  23. package/dist/data-structures/binary-tree/tree-multi-map.js +145 -367
  24. package/dist/data-structures/graph/abstract-graph.js +2 -2
  25. package/dist/data-structures/graph/directed-graph.d.ts +3 -0
  26. package/dist/data-structures/graph/directed-graph.js +3 -0
  27. package/dist/data-structures/graph/map-graph.d.ts +3 -0
  28. package/dist/data-structures/graph/map-graph.js +3 -0
  29. package/dist/data-structures/graph/undirected-graph.d.ts +3 -0
  30. package/dist/data-structures/graph/undirected-graph.js +3 -0
  31. package/dist/data-structures/hash/hash-map.d.ts +31 -1
  32. package/dist/data-structures/hash/hash-map.js +35 -5
  33. package/dist/data-structures/heap/heap.d.ts +20 -3
  34. package/dist/data-structures/heap/heap.js +31 -11
  35. package/dist/data-structures/linked-list/doubly-linked-list.d.ts +46 -11
  36. package/dist/data-structures/linked-list/doubly-linked-list.js +68 -21
  37. package/dist/data-structures/linked-list/singly-linked-list.d.ts +47 -11
  38. package/dist/data-structures/linked-list/singly-linked-list.js +73 -26
  39. package/dist/data-structures/linked-list/skip-linked-list.d.ts +3 -0
  40. package/dist/data-structures/linked-list/skip-linked-list.js +3 -0
  41. package/dist/data-structures/matrix/matrix.d.ts +3 -0
  42. package/dist/data-structures/matrix/matrix.js +3 -0
  43. package/dist/data-structures/matrix/navigator.d.ts +3 -0
  44. package/dist/data-structures/matrix/navigator.js +3 -0
  45. package/dist/data-structures/priority-queue/max-priority-queue.d.ts +3 -0
  46. package/dist/data-structures/priority-queue/max-priority-queue.js +3 -0
  47. package/dist/data-structures/priority-queue/min-priority-queue.d.ts +3 -0
  48. package/dist/data-structures/priority-queue/min-priority-queue.js +3 -0
  49. package/dist/data-structures/queue/deque.d.ts +37 -8
  50. package/dist/data-structures/queue/deque.js +73 -29
  51. package/dist/data-structures/queue/queue.d.ts +41 -1
  52. package/dist/data-structures/queue/queue.js +51 -9
  53. package/dist/data-structures/stack/stack.d.ts +27 -10
  54. package/dist/data-structures/stack/stack.js +39 -20
  55. package/dist/data-structures/trie/trie.d.ts +8 -7
  56. package/dist/data-structures/trie/trie.js +8 -7
  57. package/dist/interfaces/binary-tree.d.ts +8 -8
  58. package/dist/types/data-structures/base/base.d.ts +1 -1
  59. package/dist/types/data-structures/binary-tree/avl-tree-counter.d.ts +2 -0
  60. package/dist/types/data-structures/binary-tree/avl-tree-counter.js +2 -0
  61. package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +1 -4
  62. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +0 -3
  63. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +0 -3
  64. package/dist/types/data-structures/binary-tree/bst.d.ts +4 -4
  65. package/dist/types/data-structures/binary-tree/index.d.ts +2 -0
  66. package/dist/types/data-structures/binary-tree/index.js +2 -0
  67. package/dist/types/data-structures/binary-tree/rb-tree.d.ts +2 -5
  68. package/dist/types/data-structures/binary-tree/tree-counter.d.ts +2 -0
  69. package/dist/types/data-structures/binary-tree/tree-counter.js +2 -0
  70. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +2 -5
  71. package/package.json +2 -2
  72. package/src/common/index.ts +7 -1
  73. package/src/data-structures/base/iterable-entry-base.ts +4 -4
  74. package/src/data-structures/binary-tree/avl-tree-counter.ts +463 -0
  75. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +151 -370
  76. package/src/data-structures/binary-tree/avl-tree.ts +162 -105
  77. package/src/data-structures/binary-tree/binary-indexed-tree.ts +3 -0
  78. package/src/data-structures/binary-tree/binary-tree.ts +488 -416
  79. package/src/data-structures/binary-tree/bst.ts +326 -251
  80. package/src/data-structures/binary-tree/index.ts +3 -1
  81. package/src/data-structures/binary-tree/{rb-tree.ts → red-black-tree.ts} +219 -145
  82. package/src/data-structures/binary-tree/tree-counter.ts +504 -0
  83. package/src/data-structures/binary-tree/tree-multi-map.ts +159 -401
  84. package/src/data-structures/graph/abstract-graph.ts +2 -2
  85. package/src/data-structures/graph/directed-graph.ts +3 -0
  86. package/src/data-structures/graph/map-graph.ts +3 -0
  87. package/src/data-structures/graph/undirected-graph.ts +3 -0
  88. package/src/data-structures/hash/hash-map.ts +37 -7
  89. package/src/data-structures/heap/heap.ts +33 -10
  90. package/src/data-structures/linked-list/doubly-linked-list.ts +75 -21
  91. package/src/data-structures/linked-list/singly-linked-list.ts +80 -27
  92. package/src/data-structures/linked-list/skip-linked-list.ts +3 -0
  93. package/src/data-structures/matrix/matrix.ts +3 -0
  94. package/src/data-structures/matrix/navigator.ts +3 -0
  95. package/src/data-structures/priority-queue/max-priority-queue.ts +3 -0
  96. package/src/data-structures/priority-queue/min-priority-queue.ts +3 -0
  97. package/src/data-structures/queue/deque.ts +72 -28
  98. package/src/data-structures/queue/queue.ts +50 -7
  99. package/src/data-structures/stack/stack.ts +39 -20
  100. package/src/data-structures/trie/trie.ts +8 -7
  101. package/src/index.ts +2 -2
  102. package/src/interfaces/binary-tree.ts +10 -21
  103. package/src/types/data-structures/base/base.ts +1 -1
  104. package/src/types/data-structures/binary-tree/avl-tree-counter.ts +3 -0
  105. package/src/types/data-structures/binary-tree/avl-tree-multi-map.ts +1 -6
  106. package/src/types/data-structures/binary-tree/avl-tree.ts +0 -5
  107. package/src/types/data-structures/binary-tree/binary-tree.ts +0 -5
  108. package/src/types/data-structures/binary-tree/bst.ts +6 -6
  109. package/src/types/data-structures/binary-tree/index.ts +3 -1
  110. package/src/types/data-structures/binary-tree/red-black-tree.ts +5 -0
  111. package/src/types/data-structures/binary-tree/tree-counter.ts +3 -0
  112. package/src/types/data-structures/binary-tree/tree-multi-map.ts +2 -7
  113. package/dist/data-structures/binary-tree/rb-tree.d.ts +0 -209
  114. package/src/types/data-structures/binary-tree/rb-tree.ts +0 -10
@@ -6,8 +6,6 @@
6
6
  * @license MIT License
7
7
  */
8
8
  import type {
9
- BSTNested,
10
- BSTNodeNested,
11
9
  BSTNOptKeyOrNode,
12
10
  BSTOptions,
13
11
  BTNRep,
@@ -15,10 +13,12 @@ import type {
15
13
  Comparator,
16
14
  CP,
17
15
  DFSOrderPattern,
16
+ EntryCallback,
18
17
  IterationType,
19
18
  NodeCallback,
20
19
  NodePredicate,
21
- OptNode
20
+ OptNode,
21
+ OptNodeOrNull
22
22
  } from '../../types';
23
23
  import { BinaryTree, BinaryTreeNode } from './binary-tree';
24
24
  import { IBinaryTree } from '../../interfaces';
@@ -26,61 +26,44 @@ import { Queue } from '../queue';
26
26
  import { isComparable } from '../../utils';
27
27
  import { Range } from '../../common';
28
28
 
29
- export class BSTNode<K = any, V = any, NODE extends BSTNode<K, V, NODE> = BSTNodeNested<K, V>> extends BinaryTreeNode<
30
- K,
31
- V,
32
- NODE
33
- > {
34
- override parent?: NODE;
35
-
29
+ export class BSTNode<K = any, V = any> extends BinaryTreeNode<K, V> {
30
+ /**
31
+ * This TypeScript constructor function initializes an instance with a key and an optional value.
32
+ * @param {K} key - The `key` parameter is typically used to uniquely identify an object or element
33
+ * within a data structure. It serves as a reference or identifier for accessing or manipulating the
34
+ * associated value.
35
+ * @param {V} [value] - The `value` parameter in the constructor is optional, meaning it does not
36
+ * have to be provided when creating an instance of the class. If a value is not provided, it will
37
+ * default to `undefined`.
38
+ */
36
39
  constructor(key: K, value?: V) {
37
40
  super(key, value);
38
- this.parent = undefined;
39
- this._left = undefined;
40
- this._right = undefined;
41
41
  }
42
42
 
43
- protected override _left?: NODE;
43
+ override parent?: BSTNode<K, V> = undefined;
44
44
 
45
- /**
46
- * The function returns the value of the `_left` property.
47
- * @returns The `_left` property of the current object is being returned.
48
- */
49
- override get left(): OptNode<NODE> {
45
+ override _left?: OptNodeOrNull<BSTNode<K, V>> = undefined;
46
+
47
+ override get left(): OptNodeOrNull<BSTNode<K, V>> {
50
48
  return this._left;
51
49
  }
52
50
 
53
- /**
54
- * The function sets the left child of a node and updates the parent reference of the child.
55
- * @param {OptNode<NODE>} v - The parameter `v` is of type `OptNode<NODE>`. It can either be an
56
- * instance of the `NODE` class or `undefined`.
57
- */
58
- override set left(v: OptNode<NODE>) {
51
+ override set left(v: OptNodeOrNull<BSTNode<K, V>>) {
59
52
  if (v) {
60
- v.parent = this as unknown as NODE;
53
+ v.parent = this;
61
54
  }
62
55
  this._left = v;
63
56
  }
64
57
 
65
- protected override _right?: NODE;
58
+ override _right?: OptNodeOrNull<BSTNode<K, V>> = undefined;
66
59
 
67
- /**
68
- * The function returns the right node of a binary tree or undefined if there is no right node.
69
- * @returns The method is returning the value of the `_right` property, which is of type `NODE` or
70
- * `undefined`.
71
- */
72
- override get right(): OptNode<NODE> {
60
+ override get right(): OptNodeOrNull<BSTNode<K, V>> {
73
61
  return this._right;
74
62
  }
75
63
 
76
- /**
77
- * The function sets the right child of a node and updates the parent reference of the child.
78
- * @param {OptNode<NODE>} v - The parameter `v` is of type `OptNode<NODE>`. It can either be a
79
- * `NODE` object or `undefined`.
80
- */
81
- override set right(v: OptNode<NODE>) {
64
+ override set right(v: OptNodeOrNull<BSTNode<K, V>>) {
82
65
  if (v) {
83
- v.parent = this as unknown as NODE;
66
+ v.parent = this;
84
67
  }
85
68
  this._right = v;
86
69
  }
@@ -95,32 +78,48 @@ export class BSTNode<K = any, V = any, NODE extends BSTNode<K, V, NODE> = BSTNod
95
78
  * 6. Balance Variability: Can become unbalanced; special types maintain balance.
96
79
  * 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.
97
80
  * @example
98
- * // Find kth smallest element
99
- * // Create a BST with some elements
100
- * const bst = new BST<number>([5, 3, 7, 1, 4, 6, 8]);
101
- * const sortedKeys = bst.dfs(node => node.key, 'IN');
81
+ * // Merge 3 sorted datasets
82
+ * const dataset1 = new BST<number, string>([
83
+ * [1, 'A'],
84
+ * [7, 'G']
85
+ * ]);
86
+ * const dataset2 = [
87
+ * [2, 'B'],
88
+ * [6, 'F']
89
+ * ];
90
+ * const dataset3 = new BST<number, string>([
91
+ * [3, 'C'],
92
+ * [5, 'E'],
93
+ * [4, 'D']
94
+ * ]);
102
95
  *
103
- * // Helper function to find kth smallest
104
- * const findKthSmallest = (k: number): number | undefined => {
105
- * return sortedKeys[k - 1];
106
- * };
96
+ * // Merge datasets into a single BinarySearchTree
97
+ * const merged = new BST<number, string>(dataset1);
98
+ * merged.addMany(dataset2);
99
+ * merged.merge(dataset3);
107
100
  *
108
- * // Assertions
109
- * console.log(findKthSmallest(1)); // 1
110
- * console.log(findKthSmallest(3)); // 4
111
- * console.log(findKthSmallest(7)); // 8
101
+ * // Verify merged dataset is in sorted order
102
+ * console.log([...merged.values()]); // ['A', 'B', 'C', 'D', 'E', 'F', 'G']
112
103
  * @example
113
104
  * // Find elements in a range
114
105
  * const bst = new BST<number>([10, 5, 15, 3, 7, 12, 18]);
115
106
  * console.log(bst.search(new Range(5, 10))); // [10, 5, 7]
116
- * console.log(bst.search(new Range(4, 12))); // [10, 12, 5, 7]
107
+ * console.log(bst.rangeSearch([4, 12], node => node.key.toString())); // ['10', '12', '5', '7']
117
108
  * console.log(bst.search(new Range(4, 12, true, false))); // [10, 5, 7]
118
- * console.log(bst.search(new Range(15, 20))); // [15, 18]
109
+ * console.log(bst.rangeSearch([15, 20])); // [15, 18]
119
110
  * console.log(bst.search(new Range(15, 20, false))); // [18]
120
111
  * @example
121
112
  * // Find lowest common ancestor
122
113
  * const bst = new BST<number>([20, 10, 30, 5, 15, 25, 35, 3, 7, 12, 18]);
123
114
  *
115
+ * // LCA helper function
116
+ * const findLCA = (num1: number, num2: number): number | undefined => {
117
+ * const path1 = bst.getPathToRoot(num1);
118
+ * const path2 = bst.getPathToRoot(num2);
119
+ * // Find the first common ancestor
120
+ * return findFirstCommon(path1, path2);
121
+ * };
122
+ *
124
123
  * function findFirstCommon(arr1: number[], arr2: number[]): number | undefined {
125
124
  * for (const num of arr1) {
126
125
  * if (arr2.indexOf(num) !== -1) {
@@ -130,116 +129,112 @@ export class BSTNode<K = any, V = any, NODE extends BSTNode<K, V, NODE> = BSTNod
130
129
  * return undefined;
131
130
  * }
132
131
  *
133
- * // LCA helper function
134
- * const findLCA = (num1: number, num2: number): number | undefined => {
135
- * const path1 = bst.getPathToRoot(num1);
136
- * const path2 = bst.getPathToRoot(num2);
137
- * // Find the first common ancestor
138
- * return findFirstCommon(path1, path2);
139
- * };
140
- *
141
132
  * // Assertions
142
133
  * console.log(findLCA(3, 10)); // 7
143
134
  * console.log(findLCA(5, 35)); // 15
144
135
  * console.log(findLCA(20, 30)); // 25
145
136
  */
146
- export class BST<
147
- K = any,
148
- V = any,
149
- R = object,
150
- NODE extends BSTNode<K, V, NODE> = BSTNode<K, V, BSTNodeNested<K, V>>,
151
- TREE extends BST<K, V, R, NODE, TREE> = BST<K, V, R, NODE, BSTNested<K, V, R, NODE>>
152
- >
153
- extends BinaryTree<K, V, R, NODE, TREE>
154
- implements IBinaryTree<K, V, R, NODE, TREE>
137
+ export class BST<K = any, V = any, R = object, MK = any, MV = any, MR = object>
138
+ extends BinaryTree<K, V, R, MK, MV, MR>
139
+ implements IBinaryTree<K, V, R, MK, MV, MR>
155
140
  {
156
141
  /**
157
- * This is the constructor function for a Binary Search Tree class in TypeScript.
158
- * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter is an
159
- * iterable that can contain either keys, nodes, entries, or raw elements. These elements will be
160
- * added to the binary search tree during the construction of the object.
161
- * @param [options] - An optional object that contains additional options for the Binary Search Tree.
162
- * It can include a comparator function that defines the order of the elements in the tree.
142
+ * This TypeScript constructor initializes a binary search tree with optional options and adds
143
+ * elements if provided.
144
+ * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an
145
+ * iterable that can contain elements of type `BTNRep<K, V, BSTNode<K, V>>` or `R`. It is used to
146
+ * initialize the binary search tree with keys, nodes, entries, or raw data.
147
+ * @param [options] - The `options` parameter is an optional object that can contain the following
148
+ * properties:
163
149
  */
164
- constructor(keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, NODE>> = [], options?: BSTOptions<K, V, R>) {
150
+ constructor(keysNodesEntriesOrRaws: Iterable<BTNRep<K, V, BSTNode<K, V>> | R> = [], options?: BSTOptions<K, V, R>) {
165
151
  super([], options);
166
152
 
167
153
  if (options) {
168
- const { extractComparable, isReverse } = options;
169
- if (typeof extractComparable === 'function') this._extractComparable = extractComparable;
154
+ const { specifyComparable, isReverse } = options;
155
+ if (typeof specifyComparable === 'function') this._specifyComparable = specifyComparable;
170
156
  if (isReverse !== undefined) this._isReverse = isReverse;
171
157
  }
172
158
 
173
159
  if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);
174
160
  }
175
161
 
176
- protected override _root?: NODE = undefined;
162
+ protected override _root?: BSTNode<K, V> = undefined;
177
163
 
178
- /**
179
- * The function returns the root node of a tree structure.
180
- * @returns The `_root` property of the object, which is of type `NODE` or `undefined`.
181
- */
182
- override get root(): OptNode<NODE> {
164
+ override get root(): OptNode<BSTNode<K, V>> {
183
165
  return this._root;
184
166
  }
185
167
 
186
168
  protected _isReverse: boolean = false;
187
169
 
188
- /**
189
- * The above function is a getter method in TypeScript that returns the value of the private property
190
- * `_isReverse`.
191
- * @returns The `isReverse` property of the object, which is a boolean value.
192
- */
193
170
  get isReverse(): boolean {
194
171
  return this._isReverse;
195
172
  }
196
173
 
174
+ protected _comparator: Comparator<K> = (a: K, b: K): number => {
175
+ if (isComparable(a) && isComparable(b)) {
176
+ if (a > b) return 1;
177
+ if (a < b) return -1;
178
+ return 0;
179
+ }
180
+ if (this._specifyComparable) {
181
+ if (this._specifyComparable(a) > this._specifyComparable(b)) return 1;
182
+ if (this._specifyComparable(a) < this._specifyComparable(b)) return -1;
183
+ return 0;
184
+ }
185
+ if (typeof a === 'object' || typeof b === 'object') {
186
+ throw TypeError(
187
+ `When comparing object types, a custom specifyComparable must be defined in the constructor's options parameter.`
188
+ );
189
+ }
190
+
191
+ return 0;
192
+ };
193
+
194
+ get comparator() {
195
+ return this._comparator;
196
+ }
197
+
198
+ protected _specifyComparable?: (key: K) => Comparable;
199
+
200
+ get specifyComparable() {
201
+ return this._specifyComparable;
202
+ }
203
+
197
204
  /**
205
+ * Time Complexity: O(1)
206
+ * Space Complexity: O(1)
207
+ *
198
208
  * The function creates a new BSTNode with the given key and value and returns it.
199
209
  * @param {K} key - The key parameter is of type K, which represents the type of the key for the node
200
210
  * being created.
201
211
  * @param {V} [value] - The "value" parameter is an optional parameter of type V. It represents the
202
212
  * value associated with the key in the node being created.
203
- * @returns The method is returning a new instance of the BSTNode class, casted as the NODE type.
213
+ * @returns The method is returning a new instance of the BSTNode class, casted as the BSTNode<K, V> type.
204
214
  */
205
- override createNode(key: K, value?: V): NODE {
206
- return new BSTNode<K, V, NODE>(key, this._isMapMode ? undefined : value) as NODE;
215
+ override createNode(key: K, value?: V): BSTNode<K, V> {
216
+ return new BSTNode<K, V>(key, this._isMapMode ? undefined : value);
207
217
  }
208
218
 
209
219
  /**
220
+ * Time Complexity: O(1)
221
+ * Space Complexity: O(1)
222
+ *
210
223
  * The function creates a new binary search tree with the specified options.
211
224
  * @param [options] - The `options` parameter is an optional object that allows you to customize the
212
225
  * behavior of the `createTree` method. It accepts a partial `BSTOptions` object, which has the
213
226
  * following properties:
214
227
  * @returns a new instance of the BST class with the provided options.
215
228
  */
216
- override createTree(options?: BSTOptions<K, V, R>): TREE {
217
- return new BST<K, V, R, NODE, TREE>([], {
229
+ override createTree(options?: BSTOptions<K, V, R>) {
230
+ return new BST<K, V, R, MK, MV, MR>([], {
218
231
  iterationType: this.iterationType,
219
232
  isMapMode: this._isMapMode,
220
- extractComparable: this._extractComparable,
233
+ specifyComparable: this._specifyComparable,
221
234
  toEntryFn: this._toEntryFn,
222
235
  isReverse: this._isReverse,
223
236
  ...options
224
- }) as TREE;
225
- }
226
-
227
- /**
228
- * The function overrides a method and converts a key, value pair or entry or raw element to a node.
229
- * @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - A variable that can be of
230
- * type R or BTNRep<K, V, NODE>. It represents either a key, a node, an entry, or a raw
231
- * element.
232
- * @param {V} [value] - The `value` parameter is an optional value of type `V`. It represents the
233
- * value associated with a key in a key-value pair.
234
- * @returns either a NODE object or undefined.
235
- */
236
- override keyValueNodeEntryRawToNodeAndValue(
237
- keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
238
- value?: V
239
- ): [OptNode<NODE>, V | undefined] {
240
- const [node, entryValue] = super.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
241
- if (node === null) return [undefined, undefined];
242
- return [node, value ?? entryValue];
237
+ });
243
238
  }
244
239
 
245
240
  /**
@@ -248,8 +243,8 @@ export class BST<
248
243
  *
249
244
  * The function ensures the existence of a node in a data structure and returns it, or undefined if
250
245
  * it doesn't exist.
251
- * @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
252
- * `keyNodeEntryOrRaw` can accept a value of type `R`, which represents the key, node,
246
+ * @param {BTNRep<K, V, BSTNode<K, V>>} keyNodeOrEntry - The parameter
247
+ * `keyNodeOrEntry` can accept a value of type `R`, which represents the key, node,
253
248
  * entry, or raw element that needs to be ensured in the tree.
254
249
  * @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter is an optional
255
250
  * parameter that specifies the type of iteration to be used when ensuring a node. It has a default
@@ -258,48 +253,54 @@ export class BST<
258
253
  * not be ensured.
259
254
  */
260
255
  override ensureNode(
261
- keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
256
+ keyNodeOrEntry: BTNRep<K, V, BSTNode<K, V>>,
262
257
  iterationType: IterationType = this.iterationType
263
- ): OptNode<NODE> {
264
- return super.ensureNode(keyNodeEntryOrRaw, iterationType) ?? undefined;
258
+ ): OptNode<BSTNode<K, V>> {
259
+ return super.ensureNode(keyNodeOrEntry, iterationType) ?? undefined;
265
260
  }
266
261
 
267
262
  /**
263
+ * Time Complexity: O(1)
264
+ * Space Complexity: O(1)
265
+ *
268
266
  * The function checks if the input is an instance of the BSTNode class.
269
- * @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
270
- * `keyNodeEntryOrRaw` can be of type `R` or `BTNRep<K, V, NODE>`.
271
- * @returns a boolean value indicating whether the input parameter `keyNodeEntryOrRaw` is
267
+ * @param {BTNRep<K, V, BSTNode<K, V>>} keyNodeOrEntry - The parameter
268
+ * `keyNodeOrEntry` can be of type `R` or `BTNRep<K, V, BSTNode<K, V>>`.
269
+ * @returns a boolean value indicating whether the input parameter `keyNodeOrEntry` is
272
270
  * an instance of the `BSTNode` class.
273
271
  */
274
- override isNode(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): keyNodeEntryOrRaw is NODE {
275
- return keyNodeEntryOrRaw instanceof BSTNode;
272
+ override isNode(keyNodeOrEntry: BTNRep<K, V, BSTNode<K, V>>): keyNodeOrEntry is BSTNode<K, V> {
273
+ return keyNodeOrEntry instanceof BSTNode;
276
274
  }
277
275
 
278
276
  /**
279
- * The function "override isKey" checks if a key is comparable based on a given comparator.
277
+ * Time Complexity: O(1)
278
+ * Space Complexity: O(1)
279
+ *
280
+ * The function "override isValidKey" checks if a key is comparable based on a given comparator.
280
281
  * @param {any} key - The `key` parameter is a value that will be checked to determine if it is of
281
282
  * type `K`.
282
- * @returns The `override isKey(key: any): key is K` function is returning a boolean value based on
283
+ * @returns The `override isValidKey(key: any): key is K` function is returning a boolean value based on
283
284
  * the result of the `isComparable` function with the condition `this._compare !==
284
285
  * this._DEFAULT_COMPARATOR`.
285
286
  */
286
- override isKey(key: any): key is K {
287
- return isComparable(key, this._extractComparable !== undefined);
287
+ override isValidKey(key: any): key is K {
288
+ return isComparable(key, this._specifyComparable !== undefined);
288
289
  }
289
290
 
290
291
  /**
291
292
  * Time Complexity: O(log n)
292
- * Space Complexity: O(1)
293
+ * Space Complexity: O(log n)
293
294
  *
294
295
  * The `add` function in TypeScript adds a new node to a binary search tree based on the key value.
295
- * @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
296
- * `keyNodeEntryOrRaw` can accept a value of type `R` or `BTNRep<K, V, NODE>`.
296
+ * @param {BTNRep<K, V, BSTNode<K, V>>} keyNodeOrEntry - The parameter
297
+ * `keyNodeOrEntry` can accept a value of type `R` or `BTNRep<K, V, BSTNode<K, V>>`.
297
298
  * @param {V} [value] - The `value` parameter is an optional value that can be associated with the
298
299
  * key in the binary search tree. If provided, it will be stored in the node along with the key.
299
300
  * @returns a boolean value.
300
301
  */
301
- override add(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V): boolean {
302
- const [newNode, newValue] = this.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
302
+ override add(keyNodeOrEntry: BTNRep<K, V, BSTNode<K, V>>, value?: V): boolean {
303
+ const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
303
304
  if (newNode === undefined) return false;
304
305
 
305
306
  if (this._root === undefined) {
@@ -322,7 +323,7 @@ export class BST<
322
323
  this._size++;
323
324
  return true;
324
325
  }
325
- current = current.left;
326
+ if (current.left !== null) current = current.left;
326
327
  } else {
327
328
  if (current.right === undefined) {
328
329
  current.right = newNode;
@@ -330,7 +331,7 @@ export class BST<
330
331
  this._size++;
331
332
  return true;
332
333
  }
333
- current = current.right;
334
+ if (current.right !== null) current = current.right;
334
335
  }
335
336
  }
336
337
 
@@ -359,7 +360,7 @@ export class BST<
359
360
  * successfully inserted into the data structure.
360
361
  */
361
362
  override addMany(
362
- keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, NODE>>,
363
+ keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, BSTNode<K, V>>>,
363
364
  values?: Iterable<V | undefined>,
364
365
  isBalanceAdd = true,
365
366
  iterationType: IterationType = this.iterationType
@@ -373,15 +374,16 @@ export class BST<
373
374
  }
374
375
 
375
376
  if (!isBalanceAdd) {
376
- for (const kve of keysNodesEntriesOrRaws) {
377
+ for (let kve of keysNodesEntriesOrRaws) {
377
378
  const value = valuesIterator?.next().value;
379
+ if (this.isRaw(kve)) kve = this._toEntryFn!(kve);
378
380
  inserted.push(this.add(kve, value));
379
381
  }
380
382
  return inserted;
381
383
  }
382
384
 
383
385
  const realBTNExemplars: {
384
- key: R | BTNRep<K, V, NODE>;
386
+ key: R | BTNRep<K, V, BSTNode<K, V>>;
385
387
  value: V | undefined;
386
388
  orgIndex: number;
387
389
  }[] = [];
@@ -392,23 +394,21 @@ export class BST<
392
394
  i++;
393
395
  }
394
396
 
395
- let sorted: { key: R | BTNRep<K, V, NODE>; value: V | undefined; orgIndex: number }[] = [];
397
+ let sorted: { key: R | BTNRep<K, V, BSTNode<K, V>>; value: V | undefined; orgIndex: number }[] = [];
396
398
 
397
399
  sorted = realBTNExemplars.sort(({ key: a }, { key: b }) => {
398
400
  let keyA: K | undefined | null, keyB: K | undefined | null;
399
- if (this.isEntry(a)) keyA = a[0];
401
+ if (this.isRaw(a)) keyA = this._toEntryFn!(a)[0];
402
+ else if (this.isEntry(a)) keyA = a[0];
400
403
  else if (this.isRealNode(a)) keyA = a.key;
401
- else if (this._toEntryFn) {
402
- keyA = this._toEntryFn(a as R)[0];
403
- } else {
404
+ else {
404
405
  keyA = a as K;
405
406
  }
406
407
 
407
- if (this.isEntry(b)) keyB = b[0];
408
+ if (this.isRaw(b)) keyB = this._toEntryFn!(b)[0];
409
+ else if (this.isEntry(b)) keyB = b[0];
408
410
  else if (this.isRealNode(b)) keyB = b.key;
409
- else if (this._toEntryFn) {
410
- keyB = this._toEntryFn(b as R)[0];
411
- } else {
411
+ else {
412
412
  keyB = b as K;
413
413
  }
414
414
 
@@ -418,11 +418,17 @@ export class BST<
418
418
  return 0;
419
419
  });
420
420
 
421
- const _dfs = (arr: { key: R | BTNRep<K, V, NODE>; value: V | undefined; orgIndex: number }[]) => {
421
+ const _dfs = (arr: { key: R | BTNRep<K, V, BSTNode<K, V>>; value: V | undefined; orgIndex: number }[]) => {
422
422
  if (arr.length === 0) return;
423
423
 
424
424
  const mid = Math.floor((arr.length - 1) / 2);
425
- const { key, value, orgIndex } = arr[mid];
425
+ let { key, value } = arr[mid];
426
+ const { orgIndex } = arr[mid];
427
+ if (this.isRaw(key)) {
428
+ const entry = this._toEntryFn!(key);
429
+ key = entry[0];
430
+ value = entry[1] ?? value;
431
+ }
426
432
  inserted[orgIndex] = this.add(key, value);
427
433
  _dfs(arr.slice(0, mid));
428
434
  _dfs(arr.slice(mid + 1));
@@ -437,7 +443,13 @@ export class BST<
437
443
  const [l, r] = popped;
438
444
  if (l <= r) {
439
445
  const m = l + Math.floor((r - l) / 2);
440
- const { key, value, orgIndex } = sorted[m];
446
+ let { key, value } = sorted[m];
447
+ const { orgIndex } = sorted[m];
448
+ if (this.isRaw(key)) {
449
+ const entry = this._toEntryFn!(key);
450
+ key = entry[0];
451
+ value = entry[1] ?? value;
452
+ }
441
453
  inserted[orgIndex] = this.add(key, value);
442
454
  stack.push([m + 1, r]);
443
455
  stack.push([l, m - 1]);
@@ -455,36 +467,23 @@ export class BST<
455
467
  return inserted;
456
468
  }
457
469
 
458
- /**
459
- * Time Complexity: O(n)
460
- * Space Complexity: O(1)
461
- *
462
- * The `merge` function overrides the base class method by adding elements from another
463
- * binary search tree.
464
- * @param anotherTree - `anotherTree` is an instance of a Binary Search Tree (BST) with key type `K`,
465
- * value type `V`, return type `R`, node type `NODE`, and tree type `TREE`.
466
- */
467
- override merge(anotherTree: BST<K, V, R, NODE, TREE>) {
468
- this.addMany(anotherTree, [], false);
469
- }
470
-
471
470
  /**
472
471
  * Time Complexity: O(log n)
473
472
  * Space Complexity: O(k + log n)
474
473
  *
475
474
  * The function `search` in TypeScript overrides the search behavior in a binary tree structure based
476
475
  * on specified criteria.
477
- * @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate - The
478
- * `keyNodeEntryRawOrPredicate` parameter in the `override search` method can accept one of the
476
+ * @param {BTNRep<K, V, BSTNode<K, V>> | NodePredicate<BSTNode<K, V>>} keyNodeEntryOrPredicate - The
477
+ * `keyNodeEntryOrPredicate` parameter in the `override search` method can accept one of the
479
478
  * following types:
480
479
  * @param [onlyOne=false] - The `onlyOne` parameter is a boolean flag that determines whether the
481
480
  * search should stop after finding the first matching node. If `onlyOne` is set to `true`, the
482
481
  * search will return as soon as a matching node is found. If `onlyOne` is set to `false`, the
483
482
  * @param {C} callback - The `callback` parameter in the `override search` function is a function
484
483
  * that will be called on each node that matches the search criteria. It is of type `C`, which
485
- * extends `NodeCallback<NODE>`. The callback function should accept a node of type `NODE` as its
484
+ * extends `NodeCallback<BSTNode<K, V>>`. The callback function should accept a node of type `BSTNode<K, V>` as its
486
485
  * argument and
487
- * @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `override search`
486
+ * @param {BTNRep<K, V, BSTNode<K, V>>} startNode - The `startNode` parameter in the `override search`
488
487
  * method represents the node from which the search operation will begin. It is the starting point
489
488
  * for searching within the tree data structure. The method ensures that the `startNode` is a valid
490
489
  * node before proceeding with the search operation. If the `
@@ -496,29 +495,29 @@ export class BST<
496
495
  * structure based on the provided key, predicate, and other options. The search results are
497
496
  * collected in an array and returned as the output of the method.
498
497
  */
499
- override search<C extends NodeCallback<NODE>>(
500
- keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R | NodePredicate<NODE> | Range<K>,
498
+ override search<C extends NodeCallback<BSTNode<K, V>>>(
499
+ keyNodeEntryOrPredicate: BTNRep<K, V, BSTNode<K, V>> | NodePredicate<BSTNode<K, V>> | Range<K>,
501
500
  onlyOne = false,
502
501
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
503
- startNode: BTNRep<K, V, NODE> | R = this._root,
502
+ startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
504
503
  iterationType: IterationType = this.iterationType
505
504
  ): ReturnType<C>[] {
506
- if (keyNodeEntryRawOrPredicate === undefined) return [];
507
- if (keyNodeEntryRawOrPredicate === null) return [];
505
+ if (keyNodeEntryOrPredicate === undefined) return [];
506
+ if (keyNodeEntryOrPredicate === null) return [];
508
507
  startNode = this.ensureNode(startNode);
509
508
  if (!startNode) return [];
510
- let predicate: NodePredicate<NODE>;
509
+ let predicate: NodePredicate<BSTNode<K, V>>;
511
510
 
512
- const isRange = this.isRange(keyNodeEntryRawOrPredicate);
511
+ const isRange = this.isRange(keyNodeEntryOrPredicate);
513
512
  // Set predicate based on parameter type
514
513
  if (isRange) {
515
- predicate = node => keyNodeEntryRawOrPredicate.isInRange(node.key, this._comparator);
514
+ predicate = node => keyNodeEntryOrPredicate.isInRange(node.key, this._comparator);
516
515
  } else {
517
- predicate = this._ensurePredicate(keyNodeEntryRawOrPredicate);
516
+ predicate = this._ensurePredicate(keyNodeEntryOrPredicate);
518
517
  }
519
- const isToLeftByRange = (cur: NODE) => {
518
+ const isToLeftByRange = (cur: BSTNode<K, V>) => {
520
519
  if (isRange) {
521
- const range = keyNodeEntryRawOrPredicate;
520
+ const range = keyNodeEntryOrPredicate;
522
521
  const leftS = this.isReverse ? range.high : range.low;
523
522
  const leftI = this.isReverse ? range.includeHigh : range.includeLow;
524
523
  return (leftI && this._compare(cur.key, leftS) >= 0) || (!leftI && this._compare(cur.key, leftS) > 0);
@@ -526,9 +525,9 @@ export class BST<
526
525
  return false;
527
526
  };
528
527
 
529
- const isToRightByRange = (cur: NODE) => {
528
+ const isToRightByRange = (cur: BSTNode<K, V>) => {
530
529
  if (isRange) {
531
- const range = keyNodeEntryRawOrPredicate;
530
+ const range = keyNodeEntryOrPredicate;
532
531
  const rightS = this.isReverse ? range.low : range.high;
533
532
  const rightI = this.isReverse ? range.includeLow : range.includeLow;
534
533
 
@@ -538,7 +537,7 @@ export class BST<
538
537
  };
539
538
  const ans: ReturnType<C>[] = [];
540
539
  if (iterationType === 'RECURSIVE') {
541
- const dfs = (cur: NODE) => {
540
+ const dfs = (cur: BSTNode<K, V>) => {
542
541
  if (predicate(cur)) {
543
542
  ans.push(callback(cur));
544
543
  if (onlyOne) return;
@@ -549,8 +548,8 @@ export class BST<
549
548
  if (isRange) {
550
549
  if (this.isRealNode(cur.left) && isToLeftByRange(cur)) dfs(cur.left);
551
550
  if (this.isRealNode(cur.right) && isToRightByRange(cur)) dfs(cur.right);
552
- } else if (!this._isPredicate(keyNodeEntryRawOrPredicate)) {
553
- const benchmarkKey = this._extractKey(keyNodeEntryRawOrPredicate);
551
+ } else if (!this._isPredicate(keyNodeEntryOrPredicate)) {
552
+ const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
554
553
  if (
555
554
  this.isRealNode(cur.left) &&
556
555
  benchmarkKey !== null &&
@@ -583,8 +582,8 @@ export class BST<
583
582
  if (isRange) {
584
583
  if (this.isRealNode(cur.left) && isToLeftByRange(cur)) stack.push(cur.left);
585
584
  if (this.isRealNode(cur.right) && isToRightByRange(cur)) stack.push(cur.right);
586
- } else if (!this._isPredicate(keyNodeEntryRawOrPredicate)) {
587
- const benchmarkKey = this._extractKey(keyNodeEntryRawOrPredicate);
585
+ } else if (!this._isPredicate(keyNodeEntryOrPredicate)) {
586
+ const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
588
587
  if (
589
588
  this.isRealNode(cur.right) &&
590
589
  benchmarkKey !== null &&
@@ -611,12 +610,43 @@ export class BST<
611
610
 
612
611
  /**
613
612
  * Time Complexity: O(log n)
614
- * Space Complexity: O(1)
613
+ * Space Complexity: O(k + log n)
614
+ *
615
+ * The `rangeSearch` function searches for nodes within a specified range in a binary search tree.
616
+ * @param {Range<K> | [K, K]} range - The `range` parameter in the `rangeSearch` function can be
617
+ * either a `Range` object or an array of two elements representing the range boundaries.
618
+ * @param {C} callback - The `callback` parameter in the `rangeSearch` function is a callback
619
+ * function that is used to process each node that is found within the specified range during the
620
+ * search operation. It is of type `NodeCallback<BSTNode<K, V>>`, where `BSTNode<K, V>` is the type of nodes in the
621
+ * data structure.
622
+ * @param {BTNRep<K, V, BSTNode<K, V>>} startNode - The `startNode` parameter in the `rangeSearch`
623
+ * function represents the node from which the search for nodes within the specified range will
624
+ * begin. It is the starting point for the range search operation.
625
+ * @param {IterationType} iterationType - The `iterationType` parameter in the `rangeSearch` function
626
+ * is used to specify the type of iteration to be performed during the search operation. It has a
627
+ * default value of `this.iterationType`, which suggests that it is likely a property of the class or
628
+ * object that the `rangeSearch`
629
+ * @returns The `rangeSearch` function is returning the result of calling the `search` method with
630
+ * the specified parameters.
631
+ */
632
+ rangeSearch<C extends NodeCallback<BSTNode<K, V>>>(
633
+ range: Range<K> | [K, K],
634
+ callback: C = this._DEFAULT_NODE_CALLBACK as C,
635
+ startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
636
+ iterationType: IterationType = this.iterationType
637
+ ) {
638
+ const searchRange: Range<K> = range instanceof Range ? range : new Range(range[0], range[1]);
639
+ return this.search(searchRange, false, callback, startNode, iterationType);
640
+ }
641
+
642
+ /**
643
+ * Time Complexity: O(log n)
644
+ * Space Complexity: O(log n)
615
645
  *
616
- * This function retrieves a node based on a given keyNodeEntryRawOrPredicate within a binary search tree structure.
617
- * @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate - The `keyNodeEntryRawOrPredicate`
618
- * parameter can be of type `BTNRep<K, V, NODE>`, `R`, or `NodePredicate<NODE>`.
619
- * @param {R | BSTNOptKeyOrNode<K, NODE>} startNode - The `startNode` parameter in the `getNode` method
646
+ * This function retrieves a node based on a given keyNodeEntryOrPredicate within a binary search tree structure.
647
+ * @param {BTNRep<K, V, BSTNode<K, V>> | NodePredicate<BSTNode<K, V>>} keyNodeEntryOrPredicate - The `keyNodeEntryOrPredicate`
648
+ * parameter can be of type `BTNRep<K, V, BSTNode<K, V>>`, `R`, or `NodePredicate<BSTNode<K, V>>`.
649
+ * @param {BSTNOptKeyOrNode<K, BSTNode<K, V>>} startNode - The `startNode` parameter in the `getNode` method
620
650
  * is used to specify the starting point for searching nodes in the binary search tree. If no
621
651
  * specific starting point is provided, the default value is set to `this._root`, which is the root
622
652
  * node of the binary search tree.
@@ -624,17 +654,17 @@ export class BST<
624
654
  * parameter that specifies the type of iteration to be used. It has a default value of
625
655
  * `this.iterationType`, which means it will use the iteration type defined in the class instance if
626
656
  * no value is provided when calling the method.
627
- * @returns The `getNode` method is returning an optional binary search tree node (`OptNode<NODE>`).
628
- * It is using the `getNodes` method to find the node based on the provided keyNodeEntryRawOrPredicate, beginning at
657
+ * @returns The `getNode` method is returning an optional binary search tree node (`OptNode<BSTNode<K, V>>`).
658
+ * It is using the `getNodes` method to find the node based on the provided keyNodeEntryOrPredicate, beginning at
629
659
  * the specified root node (`startNode`) and using the specified iteration type. The method then
630
660
  * returns the first node found or `undefined` if no node is found.
631
661
  */
632
662
  override getNode(
633
- keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R | NodePredicate<NODE>,
634
- startNode: R | BSTNOptKeyOrNode<K, NODE> = this._root,
663
+ keyNodeEntryOrPredicate: BTNRep<K, V, BSTNode<K, V>> | NodePredicate<BSTNode<K, V>>,
664
+ startNode: BSTNOptKeyOrNode<K, BSTNode<K, V>> = this._root,
635
665
  iterationType: IterationType = this.iterationType
636
- ): OptNode<NODE> {
637
- return this.getNodes(keyNodeEntryRawOrPredicate, true, startNode, iterationType)[0] ?? undefined;
666
+ ): OptNode<BSTNode<K, V>> {
667
+ return this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0] ?? undefined;
638
668
  }
639
669
 
640
670
  /**
@@ -649,7 +679,7 @@ export class BST<
649
679
  * @param {DFSOrderPattern} [pattern=IN] - The "pattern" parameter in the code snippet refers to the
650
680
  * order in which the Depth-First Search (DFS) algorithm visits the nodes in a tree or graph. It can
651
681
  * take one of the following values:
652
- * @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter is the starting
682
+ * @param {BTNRep<K, V, BSTNode<K, V>>} startNode - The `startNode` parameter is the starting
653
683
  * point for the depth-first search traversal. It can be either a root node, a key-value pair, or a
654
684
  * node entry. If not specified, the default value is the root of the tree.
655
685
  * @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter specifies the
@@ -657,10 +687,10 @@ export class BST<
657
687
  * following values:
658
688
  * @returns The method is returning an array of the return type of the callback function.
659
689
  */
660
- override dfs<C extends NodeCallback<NODE>>(
690
+ override dfs<C extends NodeCallback<BSTNode<K, V>>>(
661
691
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
662
692
  pattern: DFSOrderPattern = 'IN',
663
- startNode: BTNRep<K, V, NODE> | R = this._root,
693
+ startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
664
694
  iterationType: IterationType = this.iterationType
665
695
  ): ReturnType<C>[] {
666
696
  return super.dfs(callback, pattern, startNode, iterationType);
@@ -675,7 +705,7 @@ export class BST<
675
705
  * @param {C} callback - The `callback` parameter is a function that will be called for each node
676
706
  * visited during the breadth-first search. It should take a single argument, which is the current
677
707
  * node being visited, and it can return a value of any type.
678
- * @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter is the starting
708
+ * @param {BTNRep<K, V, BSTNode<K, V>>} startNode - The `startNode` parameter is the starting
679
709
  * point for the breadth-first search. It can be either a root node, a key-value pair, or an entry
680
710
  * object. If no value is provided, the default value is the root of the tree.
681
711
  * @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type
@@ -683,9 +713,9 @@ export class BST<
683
713
  * the following values:
684
714
  * @returns an array of the return type of the callback function.
685
715
  */
686
- override bfs<C extends NodeCallback<NODE>>(
716
+ override bfs<C extends NodeCallback<BSTNode<K, V>>>(
687
717
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
688
- startNode: BTNRep<K, V, NODE> | R = this._root,
718
+ startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
689
719
  iterationType: IterationType = this.iterationType
690
720
  ): ReturnType<C>[] {
691
721
  return super.bfs(callback, startNode, iterationType, false);
@@ -698,9 +728,9 @@ export class BST<
698
728
  * The function overrides the listLevels method from the superclass and returns an array of arrays
699
729
  * containing the results of the callback function applied to each level of the tree.
700
730
  * @param {C} callback - The `callback` parameter is a generic type `C` that extends
701
- * `NodeCallback<NODE>`. It represents a callback function that will be called for each node in the
731
+ * `NodeCallback<BSTNode<K, V>>`. It represents a callback function that will be called for each node in the
702
732
  * tree during the iteration process.
703
- * @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter is the starting
733
+ * @param {BTNRep<K, V, BSTNode<K, V>>} startNode - The `startNode` parameter is the starting
704
734
  * point for listing the levels of the binary tree. It can be either a root node of the tree, a
705
735
  * key-value pair representing a node in the tree, or a key representing a node in the tree. If no
706
736
  * value is provided, the root of
@@ -709,9 +739,9 @@ export class BST<
709
739
  * @returns The method is returning a two-dimensional array of the return type of the callback
710
740
  * function.
711
741
  */
712
- override listLevels<C extends NodeCallback<NODE>>(
742
+ override listLevels<C extends NodeCallback<BSTNode<K, V>>>(
713
743
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
714
- startNode: BTNRep<K, V, NODE> | R = this._root,
744
+ startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
715
745
  iterationType: IterationType = this.iterationType
716
746
  ): ReturnType<C>[][] {
717
747
  return super.listLevels(callback, startNode, iterationType, false);
@@ -729,7 +759,7 @@ export class BST<
729
759
  * @param {CP} lesserOrGreater - The `lesserOrGreater` parameter is used to determine whether to
730
760
  * traverse nodes that are lesser, greater, or both than the `targetNode`. It accepts the values -1,
731
761
  * 0, or 1, where:
732
- * @param {BTNRep<K, V, NODE> | R} targetNode - The `targetNode` parameter is the node in
762
+ * @param {BTNRep<K, V, BSTNode<K, V>>} targetNode - The `targetNode` parameter is the node in
733
763
  * the binary tree that you want to start traversing from. It can be specified either by providing
734
764
  * the key of the node, the node itself, or an entry containing the key and value of the node. If no
735
765
  * `targetNode` is provided,
@@ -738,21 +768,21 @@ export class BST<
738
768
  * @returns The function `lesserOrGreaterTraverse` returns an array of values of type
739
769
  * `ReturnType<C>`, which is the return type of the callback function passed as an argument.
740
770
  */
741
- lesserOrGreaterTraverse<C extends NodeCallback<NODE>>(
771
+ lesserOrGreaterTraverse<C extends NodeCallback<BSTNode<K, V>>>(
742
772
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
743
773
  lesserOrGreater: CP = -1,
744
- targetNode: BTNRep<K, V, NODE> | R = this._root,
774
+ targetNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
745
775
  iterationType: IterationType = this.iterationType
746
776
  ): ReturnType<C>[] {
747
777
  const targetNodeEnsured = this.ensureNode(targetNode);
748
- const ans: ReturnType<NodeCallback<NODE>>[] = [];
778
+ const ans: ReturnType<NodeCallback<BSTNode<K, V>>>[] = [];
749
779
  if (!this._root) return ans;
750
780
  if (!targetNodeEnsured) return ans;
751
781
 
752
782
  const targetKey = targetNodeEnsured.key;
753
783
 
754
784
  if (iterationType === 'RECURSIVE') {
755
- const dfs = (cur: NODE) => {
785
+ const dfs = (cur: BSTNode<K, V>) => {
756
786
  const compared = this._compare(cur.key, targetKey);
757
787
  if (Math.sign(compared) === lesserOrGreater) ans.push(callback(cur));
758
788
  // TODO here can be optimized to O(log n)
@@ -763,7 +793,7 @@ export class BST<
763
793
  dfs(this._root);
764
794
  return ans;
765
795
  } else {
766
- const queue = new Queue<NODE>([this._root]);
796
+ const queue = new Queue<BSTNode<K, V>>([this._root]);
767
797
  while (queue.size > 0) {
768
798
  const cur = queue.shift();
769
799
  if (this.isRealNode(cur)) {
@@ -847,7 +877,7 @@ export class BST<
847
877
  let balanced = true;
848
878
 
849
879
  if (iterationType === 'RECURSIVE') {
850
- const _height = (cur: OptNode<NODE>): number => {
880
+ const _height = (cur: OptNodeOrNull<BSTNode<K, V>>): number => {
851
881
  if (!cur) return 0;
852
882
  const leftHeight = _height(cur.left),
853
883
  rightHeight = _height(cur.right);
@@ -856,15 +886,15 @@ export class BST<
856
886
  };
857
887
  _height(this._root);
858
888
  } else {
859
- const stack: NODE[] = [];
860
- let node: OptNode<NODE> = this._root,
861
- last: OptNode<NODE> = undefined;
862
- const depths: Map<NODE, number> = new Map();
889
+ const stack: BSTNode<K, V>[] = [];
890
+ let node: OptNode<BSTNode<K, V>> = this._root,
891
+ last: OptNode<BSTNode<K, V>> = undefined;
892
+ const depths: Map<BSTNode<K, V>, number> = new Map();
863
893
 
864
894
  while (stack.length > 0 || node) {
865
895
  if (node) {
866
896
  stack.push(node);
867
- node = node.left;
897
+ if (node.left !== null) node = node.left;
868
898
  } else {
869
899
  node = stack[stack.length - 1];
870
900
  if (!node.right || last === node.right) {
@@ -885,57 +915,102 @@ export class BST<
885
915
  return balanced;
886
916
  }
887
917
 
888
- protected _comparator: Comparator<K> = (a: K, b: K): number => {
889
- if (isComparable(a) && isComparable(b)) {
890
- if (a > b) return 1;
891
- if (a < b) return -1;
892
- return 0;
893
- }
894
- if (this._extractComparable) {
895
- if (this._extractComparable(a) > this._extractComparable(b)) return 1;
896
- if (this._extractComparable(a) < this._extractComparable(b)) return -1;
897
- return 0;
898
- }
899
- if (typeof a === 'object' || typeof b === 'object') {
900
- throw TypeError(
901
- `When comparing object types, a custom extractComparable must be defined in the constructor's options parameter.`
902
- );
918
+ /**
919
+ * Time complexity: O(n)
920
+ * Space complexity: O(n)
921
+ *
922
+ * The `map` function in TypeScript overrides the default map behavior for a binary search tree by
923
+ * applying a callback function to each entry and creating a new tree with the results.
924
+ * @param callback - A function that will be called for each entry in the BST. It takes four
925
+ * arguments: the key, the value (which can be undefined), the index of the entry, and a reference to
926
+ * the BST itself.
927
+ * @param [options] - The `options` parameter in the `override map` method is of type `BSTOptions<MK,
928
+ * MV, MR>`. It is an optional parameter that allows you to specify additional options for the Binary
929
+ * Search Tree (BST) being created in the `map` method. These options could include configuration
930
+ * @param {any} [thisArg] - The `thisArg` parameter in the `override map` method is used to specify
931
+ * the value of `this` that should be used when executing the `callback` function. It allows you to
932
+ * set the context or scope in which the callback function will be called. This can be useful when
933
+ * you want
934
+ * @returns The `map` method is returning a new Binary Search Tree (`BST`) instance with the entries
935
+ * transformed by the provided callback function.
936
+ */
937
+ override map(
938
+ callback: EntryCallback<K, V | undefined, [MK, MV]>,
939
+ options?: BSTOptions<MK, MV, MR>,
940
+ thisArg?: any
941
+ ): BST<MK, MV, MR> {
942
+ const newTree = new BST<MK, MV, MR>([], options);
943
+ let index = 0;
944
+ for (const [key, value] of this) {
945
+ newTree.add(callback.call(thisArg, key, value, index++, this));
903
946
  }
904
-
905
- return 0;
906
- };
947
+ return newTree;
948
+ }
907
949
 
908
950
  /**
909
- * The function returns the value of the _comparator property.
910
- * @returns The `_comparator` property is being returned.
951
+ * Time complexity: O(n)
952
+ * Space complexity: O(n)
953
+ *
954
+ * The function `clone` overrides the default cloning behavior to create a deep copy of a tree
955
+ * structure.
956
+ * @returns The `cloned` object is being returned.
911
957
  */
912
- get comparator() {
913
- return this._comparator;
958
+ override clone() {
959
+ const cloned = this.createTree();
960
+ this._clone(cloned);
961
+ return cloned;
914
962
  }
915
963
 
916
- protected _extractComparable?: (key: K) => Comparable;
917
-
918
964
  /**
919
- * This function returns the value of the `_extractComparable` property.
920
- * @returns The method `extractComparable()` is being returned, which is a getter method for the
921
- * `_extractComparable` property.
965
+ * Time Complexity: O(1)
966
+ * Space Complexity: O(1)
967
+ *
968
+ * The function overrides a method and converts a key, value pair or entry or raw element to a node.
969
+ * @param {BTNRep<K, V, BSTNode<K, V>>} keyNodeOrEntry - A variable that can be of
970
+ * type R or BTNRep<K, V, BSTNode<K, V>>. It represents either a key, a node, an entry, or a raw
971
+ * element.
972
+ * @param {V} [value] - The `value` parameter is an optional value of type `V`. It represents the
973
+ * value associated with a key in a key-value pair.
974
+ * @returns either a BSTNode<K, V> object or undefined.
922
975
  */
923
- get extractComparable() {
924
- return this._extractComparable;
976
+ protected override _keyValueNodeOrEntryToNodeAndValue(
977
+ keyNodeOrEntry: BTNRep<K, V, BSTNode<K, V>>,
978
+ value?: V
979
+ ): [OptNode<BSTNode<K, V>>, V | undefined] {
980
+ const [node, entryValue] = super._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
981
+ if (node === null) return [undefined, undefined];
982
+ return [node, value ?? entryValue];
925
983
  }
926
984
 
927
985
  /**
986
+ * Time Complexity: O(1)
987
+ * Space Complexity: O(1)
988
+ *
928
989
  * The function sets the root of a tree-like structure and updates the parent property of the new
929
990
  * root.
930
- * @param {OptNode<NODE>} v - v is a parameter of type NODE or undefined.
991
+ * @param {OptNode<BSTNode<K, V>>} v - v is a parameter of type BSTNode<K, V> or undefined.
931
992
  */
932
- protected override _setRoot(v: OptNode<NODE>) {
993
+ protected override _setRoot(v: OptNode<BSTNode<K, V>>) {
933
994
  if (v) {
934
995
  v.parent = undefined;
935
996
  }
936
997
  this._root = v;
937
998
  }
938
999
 
1000
+ /**
1001
+ * Time Complexity: O(1)
1002
+ * Space Complexity: O(1)
1003
+ *
1004
+ * The _compare function compares two values using a specified comparator function and optionally
1005
+ * reverses the result.
1006
+ * @param {K} a - The parameter `a` is of type `K`, which is used as an input for comparison in the
1007
+ * `_compare` method.
1008
+ * @param {K} b - The parameter `b` in the `_compare` function is of type `K`.
1009
+ * @returns The `_compare` method is returning the result of the ternary expression. If `_isReverse`
1010
+ * is true, it returns the negation of the result of calling the `_comparator` function with
1011
+ * arguments `a` and `b`. If `_isReverse` is false, it returns the result of calling the
1012
+ * `_comparator` function with arguments `a` and `b`.
1013
+ */
939
1014
  protected _compare(a: K, b: K) {
940
1015
  return this._isReverse ? -this._comparator(a, b) : this._comparator(a, b);
941
1016
  }