red-black-tree-typed 1.53.6 → 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 (121) hide show
  1. package/README.md +52 -0
  2. package/dist/common/index.d.ts +12 -0
  3. package/dist/common/index.js +28 -0
  4. package/dist/data-structures/base/iterable-entry-base.js +4 -4
  5. package/dist/data-structures/binary-tree/avl-tree-counter.d.ts +213 -0
  6. package/dist/data-structures/binary-tree/avl-tree-counter.js +407 -0
  7. package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +71 -170
  8. package/dist/data-structures/binary-tree/avl-tree-multi-map.js +133 -331
  9. package/dist/data-structures/binary-tree/avl-tree.d.ts +103 -69
  10. package/dist/data-structures/binary-tree/avl-tree.js +131 -71
  11. package/dist/data-structures/binary-tree/binary-indexed-tree.d.ts +3 -0
  12. package/dist/data-structures/binary-tree/binary-indexed-tree.js +3 -0
  13. package/dist/data-structures/binary-tree/binary-tree.d.ts +309 -208
  14. package/dist/data-structures/binary-tree/binary-tree.js +382 -300
  15. package/dist/data-structures/binary-tree/bst.d.ts +245 -127
  16. package/dist/data-structures/binary-tree/bst.js +366 -163
  17. package/dist/data-structures/binary-tree/index.d.ts +3 -1
  18. package/dist/data-structures/binary-tree/index.js +3 -1
  19. package/dist/data-structures/binary-tree/red-black-tree.d.ts +286 -0
  20. package/dist/data-structures/binary-tree/{rb-tree.js → red-black-tree.js} +181 -108
  21. package/dist/data-structures/binary-tree/tree-counter.d.ts +212 -0
  22. package/dist/data-structures/binary-tree/tree-counter.js +444 -0
  23. package/dist/data-structures/binary-tree/tree-multi-map.d.ts +78 -170
  24. package/dist/data-structures/binary-tree/tree-multi-map.js +145 -367
  25. package/dist/data-structures/graph/abstract-graph.js +2 -2
  26. package/dist/data-structures/graph/directed-graph.d.ts +3 -0
  27. package/dist/data-structures/graph/directed-graph.js +3 -0
  28. package/dist/data-structures/graph/map-graph.d.ts +3 -0
  29. package/dist/data-structures/graph/map-graph.js +3 -0
  30. package/dist/data-structures/graph/undirected-graph.d.ts +3 -0
  31. package/dist/data-structures/graph/undirected-graph.js +3 -0
  32. package/dist/data-structures/hash/hash-map.d.ts +31 -1
  33. package/dist/data-structures/hash/hash-map.js +35 -5
  34. package/dist/data-structures/heap/heap.d.ts +26 -9
  35. package/dist/data-structures/heap/heap.js +37 -17
  36. package/dist/data-structures/linked-list/doubly-linked-list.d.ts +64 -19
  37. package/dist/data-structures/linked-list/doubly-linked-list.js +92 -31
  38. package/dist/data-structures/linked-list/singly-linked-list.d.ts +48 -12
  39. package/dist/data-structures/linked-list/singly-linked-list.js +74 -27
  40. package/dist/data-structures/linked-list/skip-linked-list.d.ts +3 -0
  41. package/dist/data-structures/linked-list/skip-linked-list.js +3 -0
  42. package/dist/data-structures/matrix/matrix.d.ts +3 -0
  43. package/dist/data-structures/matrix/matrix.js +3 -0
  44. package/dist/data-structures/matrix/navigator.d.ts +3 -0
  45. package/dist/data-structures/matrix/navigator.js +3 -0
  46. package/dist/data-structures/priority-queue/max-priority-queue.d.ts +3 -0
  47. package/dist/data-structures/priority-queue/max-priority-queue.js +3 -0
  48. package/dist/data-structures/priority-queue/min-priority-queue.d.ts +3 -0
  49. package/dist/data-structures/priority-queue/min-priority-queue.js +3 -0
  50. package/dist/data-structures/queue/deque.d.ts +37 -8
  51. package/dist/data-structures/queue/deque.js +73 -29
  52. package/dist/data-structures/queue/queue.d.ts +41 -1
  53. package/dist/data-structures/queue/queue.js +51 -9
  54. package/dist/data-structures/stack/stack.d.ts +27 -10
  55. package/dist/data-structures/stack/stack.js +39 -20
  56. package/dist/data-structures/trie/trie.d.ts +111 -10
  57. package/dist/data-structures/trie/trie.js +123 -18
  58. package/dist/index.d.ts +2 -1
  59. package/dist/index.js +2 -1
  60. package/dist/interfaces/binary-tree.d.ts +8 -8
  61. package/dist/types/data-structures/base/base.d.ts +1 -1
  62. package/dist/types/data-structures/binary-tree/avl-tree-counter.d.ts +2 -0
  63. package/dist/types/data-structures/binary-tree/avl-tree-counter.js +2 -0
  64. package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +1 -4
  65. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +0 -3
  66. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -4
  67. package/dist/types/data-structures/binary-tree/bst.d.ts +6 -5
  68. package/dist/types/data-structures/binary-tree/index.d.ts +2 -0
  69. package/dist/types/data-structures/binary-tree/index.js +2 -0
  70. package/dist/types/data-structures/binary-tree/rb-tree.d.ts +2 -5
  71. package/dist/types/data-structures/binary-tree/tree-counter.d.ts +2 -0
  72. package/dist/types/data-structures/binary-tree/tree-counter.js +2 -0
  73. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +2 -5
  74. package/dist/types/utils/utils.d.ts +10 -6
  75. package/dist/utils/utils.js +4 -2
  76. package/package.json +2 -2
  77. package/src/common/index.ts +25 -0
  78. package/src/data-structures/base/iterable-entry-base.ts +4 -4
  79. package/src/data-structures/binary-tree/avl-tree-counter.ts +463 -0
  80. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +152 -373
  81. package/src/data-structures/binary-tree/avl-tree.ts +164 -106
  82. package/src/data-structures/binary-tree/binary-indexed-tree.ts +3 -0
  83. package/src/data-structures/binary-tree/binary-tree.ts +563 -447
  84. package/src/data-structures/binary-tree/bst.ts +433 -237
  85. package/src/data-structures/binary-tree/index.ts +3 -1
  86. package/src/data-structures/binary-tree/{rb-tree.ts → red-black-tree.ts} +224 -146
  87. package/src/data-structures/binary-tree/tree-counter.ts +504 -0
  88. package/src/data-structures/binary-tree/tree-multi-map.ts +159 -401
  89. package/src/data-structures/graph/abstract-graph.ts +2 -2
  90. package/src/data-structures/graph/directed-graph.ts +3 -0
  91. package/src/data-structures/graph/map-graph.ts +3 -0
  92. package/src/data-structures/graph/undirected-graph.ts +3 -0
  93. package/src/data-structures/hash/hash-map.ts +37 -7
  94. package/src/data-structures/heap/heap.ts +72 -49
  95. package/src/data-structures/linked-list/doubly-linked-list.ts +186 -118
  96. package/src/data-structures/linked-list/singly-linked-list.ts +81 -28
  97. package/src/data-structures/linked-list/skip-linked-list.ts +3 -0
  98. package/src/data-structures/matrix/matrix.ts +3 -0
  99. package/src/data-structures/matrix/navigator.ts +3 -0
  100. package/src/data-structures/priority-queue/max-priority-queue.ts +3 -0
  101. package/src/data-structures/priority-queue/min-priority-queue.ts +3 -0
  102. package/src/data-structures/queue/deque.ts +72 -28
  103. package/src/data-structures/queue/queue.ts +50 -7
  104. package/src/data-structures/stack/stack.ts +39 -20
  105. package/src/data-structures/trie/trie.ts +123 -17
  106. package/src/index.ts +4 -3
  107. package/src/interfaces/binary-tree.ts +10 -21
  108. package/src/types/data-structures/base/base.ts +1 -1
  109. package/src/types/data-structures/binary-tree/avl-tree-counter.ts +3 -0
  110. package/src/types/data-structures/binary-tree/avl-tree-multi-map.ts +1 -6
  111. package/src/types/data-structures/binary-tree/avl-tree.ts +0 -5
  112. package/src/types/data-structures/binary-tree/binary-tree.ts +1 -6
  113. package/src/types/data-structures/binary-tree/bst.ts +8 -7
  114. package/src/types/data-structures/binary-tree/index.ts +3 -1
  115. package/src/types/data-structures/binary-tree/red-black-tree.ts +5 -0
  116. package/src/types/data-structures/binary-tree/tree-counter.ts +3 -0
  117. package/src/types/data-structures/binary-tree/tree-multi-map.ts +2 -7
  118. package/src/types/utils/utils.ts +16 -10
  119. package/src/utils/utils.ts +4 -2
  120. package/dist/data-structures/binary-tree/rb-tree.d.ts +0 -205
  121. package/src/types/data-structures/binary-tree/rb-tree.ts +0 -10
@@ -6,79 +6,64 @@
6
6
  * @license MIT License
7
7
  */
8
8
  import type {
9
- BSTNested,
10
- BSTNodeNested,
11
9
  BSTNOptKeyOrNode,
12
10
  BSTOptions,
13
11
  BTNRep,
12
+ Comparable,
14
13
  Comparator,
15
14
  CP,
16
15
  DFSOrderPattern,
16
+ EntryCallback,
17
17
  IterationType,
18
18
  NodeCallback,
19
19
  NodePredicate,
20
- OptNode
20
+ OptNode,
21
+ OptNodeOrNull
21
22
  } from '../../types';
22
23
  import { BinaryTree, BinaryTreeNode } from './binary-tree';
23
24
  import { IBinaryTree } from '../../interfaces';
24
25
  import { Queue } from '../queue';
25
26
  import { isComparable } from '../../utils';
27
+ import { Range } from '../../common';
26
28
 
27
- export class BSTNode<K = any, V = any, NODE extends BSTNode<K, V, NODE> = BSTNodeNested<K, V>> extends BinaryTreeNode<
28
- K,
29
- V,
30
- NODE
31
- > {
32
- override parent?: NODE;
33
-
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
+ */
34
39
  constructor(key: K, value?: V) {
35
40
  super(key, value);
36
- this.parent = undefined;
37
- this._left = undefined;
38
- this._right = undefined;
39
41
  }
40
42
 
41
- protected override _left?: NODE;
43
+ override parent?: BSTNode<K, V> = undefined;
42
44
 
43
- /**
44
- * The function returns the value of the `_left` property.
45
- * @returns The `_left` property of the current object is being returned.
46
- */
47
- override get left(): OptNode<NODE> {
45
+ override _left?: OptNodeOrNull<BSTNode<K, V>> = undefined;
46
+
47
+ override get left(): OptNodeOrNull<BSTNode<K, V>> {
48
48
  return this._left;
49
49
  }
50
50
 
51
- /**
52
- * The function sets the left child of a node and updates the parent reference of the child.
53
- * @param {OptNode<NODE>} v - The parameter `v` is of type `OptNode<NODE>`. It can either be an
54
- * instance of the `NODE` class or `undefined`.
55
- */
56
- override set left(v: OptNode<NODE>) {
51
+ override set left(v: OptNodeOrNull<BSTNode<K, V>>) {
57
52
  if (v) {
58
- v.parent = this as unknown as NODE;
53
+ v.parent = this;
59
54
  }
60
55
  this._left = v;
61
56
  }
62
57
 
63
- protected override _right?: NODE;
58
+ override _right?: OptNodeOrNull<BSTNode<K, V>> = undefined;
64
59
 
65
- /**
66
- * The function returns the right node of a binary tree or undefined if there is no right node.
67
- * @returns The method is returning the value of the `_right` property, which is of type `NODE` or
68
- * `undefined`.
69
- */
70
- override get right(): OptNode<NODE> {
60
+ override get right(): OptNodeOrNull<BSTNode<K, V>> {
71
61
  return this._right;
72
62
  }
73
63
 
74
- /**
75
- * The function sets the right child of a node and updates the parent reference of the child.
76
- * @param {OptNode<NODE>} v - The parameter `v` is of type `OptNode<NODE>`. It can either be a
77
- * `NODE` object or `undefined`.
78
- */
79
- override set right(v: OptNode<NODE>) {
64
+ override set right(v: OptNodeOrNull<BSTNode<K, V>>) {
80
65
  if (v) {
81
- v.parent = this as unknown as NODE;
66
+ v.parent = this;
82
67
  }
83
68
  this._right = v;
84
69
  }
@@ -92,91 +77,164 @@ export class BSTNode<K = any, V = any, NODE extends BSTNode<K, V, NODE> = BSTNod
92
77
  * 5. Logarithmic Operations: Ideal operations like insertion, deletion, and searching are O(log n) time-efficient.
93
78
  * 6. Balance Variability: Can become unbalanced; special types maintain balance.
94
79
  * 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.
80
+ * @example
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
+ * ]);
95
+ *
96
+ * // Merge datasets into a single BinarySearchTree
97
+ * const merged = new BST<number, string>(dataset1);
98
+ * merged.addMany(dataset2);
99
+ * merged.merge(dataset3);
100
+ *
101
+ * // Verify merged dataset is in sorted order
102
+ * console.log([...merged.values()]); // ['A', 'B', 'C', 'D', 'E', 'F', 'G']
103
+ * @example
104
+ * // Find elements in a range
105
+ * const bst = new BST<number>([10, 5, 15, 3, 7, 12, 18]);
106
+ * console.log(bst.search(new Range(5, 10))); // [10, 5, 7]
107
+ * console.log(bst.rangeSearch([4, 12], node => node.key.toString())); // ['10', '12', '5', '7']
108
+ * console.log(bst.search(new Range(4, 12, true, false))); // [10, 5, 7]
109
+ * console.log(bst.rangeSearch([15, 20])); // [15, 18]
110
+ * console.log(bst.search(new Range(15, 20, false))); // [18]
111
+ * @example
112
+ * // Find lowest common ancestor
113
+ * const bst = new BST<number>([20, 10, 30, 5, 15, 25, 35, 3, 7, 12, 18]);
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
+ *
123
+ * function findFirstCommon(arr1: number[], arr2: number[]): number | undefined {
124
+ * for (const num of arr1) {
125
+ * if (arr2.indexOf(num) !== -1) {
126
+ * return num;
127
+ * }
128
+ * }
129
+ * return undefined;
130
+ * }
131
+ *
132
+ * // Assertions
133
+ * console.log(findLCA(3, 10)); // 7
134
+ * console.log(findLCA(5, 35)); // 15
135
+ * console.log(findLCA(20, 30)); // 25
95
136
  */
96
- export class BST<
97
- K = any,
98
- V = any,
99
- R = object,
100
- NODE extends BSTNode<K, V, NODE> = BSTNode<K, V, BSTNodeNested<K, V>>,
101
- TREE extends BST<K, V, R, NODE, TREE> = BST<K, V, R, NODE, BSTNested<K, V, R, NODE>>
102
- >
103
- extends BinaryTree<K, V, R, NODE, TREE>
104
- 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>
105
140
  {
106
141
  /**
107
- * This is the constructor function for a Binary Search Tree class in TypeScript.
108
- * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter is an
109
- * iterable that can contain either keys, nodes, entries, or raw elements. These elements will be
110
- * added to the binary search tree during the construction of the object.
111
- * @param [options] - An optional object that contains additional options for the Binary Search Tree.
112
- * 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:
113
149
  */
114
- 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>) {
115
151
  super([], options);
116
152
 
117
153
  if (options) {
118
- const { comparator } = options;
119
- if (comparator) this._comparator = comparator;
154
+ const { specifyComparable, isReverse } = options;
155
+ if (typeof specifyComparable === 'function') this._specifyComparable = specifyComparable;
156
+ if (isReverse !== undefined) this._isReverse = isReverse;
120
157
  }
121
158
 
122
159
  if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);
123
160
  }
124
161
 
125
- protected override _root?: NODE = undefined;
162
+ protected override _root?: BSTNode<K, V> = undefined;
126
163
 
127
- /**
128
- * The function returns the root node of a tree structure.
129
- * @returns The `_root` property of the object, which is of type `NODE` or `undefined`.
130
- */
131
- override get root(): OptNode<NODE> {
164
+ override get root(): OptNode<BSTNode<K, V>> {
132
165
  return this._root;
133
166
  }
134
167
 
168
+ protected _isReverse: boolean = false;
169
+
170
+ get isReverse(): boolean {
171
+ return this._isReverse;
172
+ }
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
+
135
204
  /**
205
+ * Time Complexity: O(1)
206
+ * Space Complexity: O(1)
207
+ *
136
208
  * The function creates a new BSTNode with the given key and value and returns it.
137
209
  * @param {K} key - The key parameter is of type K, which represents the type of the key for the node
138
210
  * being created.
139
211
  * @param {V} [value] - The "value" parameter is an optional parameter of type V. It represents the
140
212
  * value associated with the key in the node being created.
141
- * @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.
142
214
  */
143
- override createNode(key: K, value?: V): NODE {
144
- 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);
145
217
  }
146
218
 
147
219
  /**
220
+ * Time Complexity: O(1)
221
+ * Space Complexity: O(1)
222
+ *
148
223
  * The function creates a new binary search tree with the specified options.
149
224
  * @param [options] - The `options` parameter is an optional object that allows you to customize the
150
225
  * behavior of the `createTree` method. It accepts a partial `BSTOptions` object, which has the
151
226
  * following properties:
152
227
  * @returns a new instance of the BST class with the provided options.
153
228
  */
154
- override createTree(options?: BSTOptions<K, V, R>): TREE {
155
- 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>([], {
156
231
  iterationType: this.iterationType,
157
232
  isMapMode: this._isMapMode,
158
- comparator: this._comparator,
233
+ specifyComparable: this._specifyComparable,
159
234
  toEntryFn: this._toEntryFn,
235
+ isReverse: this._isReverse,
160
236
  ...options
161
- }) as TREE;
162
- }
163
-
164
- /**
165
- * The function overrides a method and converts a key, value pair or entry or raw element to a node.
166
- * @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - A variable that can be of
167
- * type R or BTNRep<K, V, NODE>. It represents either a key, a node, an entry, or a raw
168
- * element.
169
- * @param {V} [value] - The `value` parameter is an optional value of type `V`. It represents the
170
- * value associated with a key in a key-value pair.
171
- * @returns either a NODE object or undefined.
172
- */
173
- override keyValueNodeEntryRawToNodeAndValue(
174
- keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
175
- value?: V
176
- ): [OptNode<NODE>, V | undefined] {
177
- const [node, entryValue] = super.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
178
- if (node === null) return [undefined, undefined];
179
- return [node, value ?? entryValue];
237
+ });
180
238
  }
181
239
 
182
240
  /**
@@ -185,8 +243,8 @@ export class BST<
185
243
  *
186
244
  * The function ensures the existence of a node in a data structure and returns it, or undefined if
187
245
  * it doesn't exist.
188
- * @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
189
- * `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,
190
248
  * entry, or raw element that needs to be ensured in the tree.
191
249
  * @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter is an optional
192
250
  * parameter that specifies the type of iteration to be used when ensuring a node. It has a default
@@ -195,48 +253,54 @@ export class BST<
195
253
  * not be ensured.
196
254
  */
197
255
  override ensureNode(
198
- keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
256
+ keyNodeOrEntry: BTNRep<K, V, BSTNode<K, V>>,
199
257
  iterationType: IterationType = this.iterationType
200
- ): OptNode<NODE> {
201
- return super.ensureNode(keyNodeEntryOrRaw, iterationType) ?? undefined;
258
+ ): OptNode<BSTNode<K, V>> {
259
+ return super.ensureNode(keyNodeOrEntry, iterationType) ?? undefined;
202
260
  }
203
261
 
204
262
  /**
263
+ * Time Complexity: O(1)
264
+ * Space Complexity: O(1)
265
+ *
205
266
  * The function checks if the input is an instance of the BSTNode class.
206
- * @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
207
- * `keyNodeEntryOrRaw` can be of type `R` or `BTNRep<K, V, NODE>`.
208
- * @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
209
270
  * an instance of the `BSTNode` class.
210
271
  */
211
- override isNode(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): keyNodeEntryOrRaw is NODE {
212
- return keyNodeEntryOrRaw instanceof BSTNode;
272
+ override isNode(keyNodeOrEntry: BTNRep<K, V, BSTNode<K, V>>): keyNodeOrEntry is BSTNode<K, V> {
273
+ return keyNodeOrEntry instanceof BSTNode;
213
274
  }
214
275
 
215
276
  /**
216
- * 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.
217
281
  * @param {any} key - The `key` parameter is a value that will be checked to determine if it is of
218
282
  * type `K`.
219
- * @returns The `override isKey(key: any): key is K` function is returning a boolean value based on
220
- * the result of the `isComparable` function with the condition `this.comparator !==
283
+ * @returns The `override isValidKey(key: any): key is K` function is returning a boolean value based on
284
+ * the result of the `isComparable` function with the condition `this._compare !==
221
285
  * this._DEFAULT_COMPARATOR`.
222
286
  */
223
- override isKey(key: any): key is K {
224
- return isComparable(key, this.comparator !== this._DEFAULT_COMPARATOR);
287
+ override isValidKey(key: any): key is K {
288
+ return isComparable(key, this._specifyComparable !== undefined);
225
289
  }
226
290
 
227
291
  /**
228
292
  * Time Complexity: O(log n)
229
- * Space Complexity: O(1)
293
+ * Space Complexity: O(log n)
230
294
  *
231
295
  * The `add` function in TypeScript adds a new node to a binary search tree based on the key value.
232
- * @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
233
- * `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>>`.
234
298
  * @param {V} [value] - The `value` parameter is an optional value that can be associated with the
235
299
  * key in the binary search tree. If provided, it will be stored in the node along with the key.
236
300
  * @returns a boolean value.
237
301
  */
238
- override add(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V): boolean {
239
- 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);
240
304
  if (newNode === undefined) return false;
241
305
 
242
306
  if (this._root === undefined) {
@@ -248,18 +312,18 @@ export class BST<
248
312
 
249
313
  let current = this._root;
250
314
  while (current !== undefined) {
251
- if (this.comparator(current.key, newNode.key) === 0) {
315
+ if (this._compare(current.key, newNode.key) === 0) {
252
316
  this._replaceNode(current, newNode);
253
317
  if (this._isMapMode) this._setValue(current.key, newValue);
254
318
  return true;
255
- } else if (this.comparator(current.key, newNode.key) > 0) {
319
+ } else if (this._compare(current.key, newNode.key) > 0) {
256
320
  if (current.left === undefined) {
257
321
  current.left = newNode;
258
322
  if (this._isMapMode) this._setValue(newNode?.key, newValue);
259
323
  this._size++;
260
324
  return true;
261
325
  }
262
- current = current.left;
326
+ if (current.left !== null) current = current.left;
263
327
  } else {
264
328
  if (current.right === undefined) {
265
329
  current.right = newNode;
@@ -267,7 +331,7 @@ export class BST<
267
331
  this._size++;
268
332
  return true;
269
333
  }
270
- current = current.right;
334
+ if (current.right !== null) current = current.right;
271
335
  }
272
336
  }
273
337
 
@@ -296,7 +360,7 @@ export class BST<
296
360
  * successfully inserted into the data structure.
297
361
  */
298
362
  override addMany(
299
- keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, NODE>>,
363
+ keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, BSTNode<K, V>>>,
300
364
  values?: Iterable<V | undefined>,
301
365
  isBalanceAdd = true,
302
366
  iterationType: IterationType = this.iterationType
@@ -310,15 +374,16 @@ export class BST<
310
374
  }
311
375
 
312
376
  if (!isBalanceAdd) {
313
- for (const kve of keysNodesEntriesOrRaws) {
377
+ for (let kve of keysNodesEntriesOrRaws) {
314
378
  const value = valuesIterator?.next().value;
379
+ if (this.isRaw(kve)) kve = this._toEntryFn!(kve);
315
380
  inserted.push(this.add(kve, value));
316
381
  }
317
382
  return inserted;
318
383
  }
319
384
 
320
385
  const realBTNExemplars: {
321
- key: R | BTNRep<K, V, NODE>;
386
+ key: R | BTNRep<K, V, BSTNode<K, V>>;
322
387
  value: V | undefined;
323
388
  orgIndex: number;
324
389
  }[] = [];
@@ -329,37 +394,41 @@ export class BST<
329
394
  i++;
330
395
  }
331
396
 
332
- 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 }[] = [];
333
398
 
334
399
  sorted = realBTNExemplars.sort(({ key: a }, { key: b }) => {
335
400
  let keyA: K | undefined | null, keyB: K | undefined | null;
336
- 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];
337
403
  else if (this.isRealNode(a)) keyA = a.key;
338
- else if (this._toEntryFn) {
339
- keyA = this._toEntryFn(a as R)[0];
340
- } else {
404
+ else {
341
405
  keyA = a as K;
342
406
  }
343
407
 
344
- 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];
345
410
  else if (this.isRealNode(b)) keyB = b.key;
346
- else if (this._toEntryFn) {
347
- keyB = this._toEntryFn(b as R)[0];
348
- } else {
411
+ else {
349
412
  keyB = b as K;
350
413
  }
351
414
 
352
415
  if (keyA !== undefined && keyA !== null && keyB !== undefined && keyB !== null) {
353
- return this.comparator(keyA, keyB);
416
+ return this._compare(keyA, keyB);
354
417
  }
355
418
  return 0;
356
419
  });
357
420
 
358
- 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 }[]) => {
359
422
  if (arr.length === 0) return;
360
423
 
361
424
  const mid = Math.floor((arr.length - 1) / 2);
362
- 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
+ }
363
432
  inserted[orgIndex] = this.add(key, value);
364
433
  _dfs(arr.slice(0, mid));
365
434
  _dfs(arr.slice(mid + 1));
@@ -374,7 +443,13 @@ export class BST<
374
443
  const [l, r] = popped;
375
444
  if (l <= r) {
376
445
  const m = l + Math.floor((r - l) / 2);
377
- 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
+ }
378
453
  inserted[orgIndex] = this.add(key, value);
379
454
  stack.push([m + 1, r]);
380
455
  stack.push([l, m - 1]);
@@ -396,60 +471,97 @@ export class BST<
396
471
  * Time Complexity: O(log n)
397
472
  * Space Complexity: O(k + log n)
398
473
  *
399
- * The function `getNodes` in TypeScript overrides the base class method to retrieve nodes based on a
400
- * given keyNodeEntryRawOrPredicate and iteration type.
401
- * @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate - The `keyNodeEntryRawOrPredicate`
402
- * parameter in the `getNodes` method is used to filter the nodes that will be returned. It can be a
403
- * key, a node, an entry, or a custom keyNodeEntryRawOrPredicate function that determines whether a node should be
404
- * included in the result.
405
- * @param [onlyOne=false] - The `onlyOne` parameter in the `getNodes` method is a boolean flag that
406
- * determines whether to return only the first node that matches the keyNodeEntryRawOrPredicate (`true`) or all nodes
407
- * that match the keyNodeEntryRawOrPredicate (`false`). If `onlyOne` is set to `true`, the method will stop iterating
408
- * and
409
- * @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
410
- * `getNodes` method is used to specify the starting point for traversing the tree when searching for
411
- * nodes that match a given keyNodeEntryRawOrPredicate. It represents the root node of the subtree where the search
412
- * should begin. If not explicitly provided, the default value for `begin
413
- * @param {IterationType} iterationType - The `iterationType` parameter in the `getNodes` method
414
- * specifies the type of iteration to be performed when traversing the nodes of a binary tree. It can
415
- * have two possible values:
416
- * @returns The `getNodes` method returns an array of nodes that satisfy the given keyNodeEntryRawOrPredicate.
474
+ * The function `search` in TypeScript overrides the search behavior in a binary tree structure based
475
+ * on specified criteria.
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
478
+ * following types:
479
+ * @param [onlyOne=false] - The `onlyOne` parameter is a boolean flag that determines whether the
480
+ * search should stop after finding the first matching node. If `onlyOne` is set to `true`, the
481
+ * search will return as soon as a matching node is found. If `onlyOne` is set to `false`, the
482
+ * @param {C} callback - The `callback` parameter in the `override search` function is a function
483
+ * that will be called on each node that matches the search criteria. It is of type `C`, which
484
+ * extends `NodeCallback<BSTNode<K, V>>`. The callback function should accept a node of type `BSTNode<K, V>` as its
485
+ * argument and
486
+ * @param {BTNRep<K, V, BSTNode<K, V>>} startNode - The `startNode` parameter in the `override search`
487
+ * method represents the node from which the search operation will begin. It is the starting point
488
+ * for searching within the tree data structure. The method ensures that the `startNode` is a valid
489
+ * node before proceeding with the search operation. If the `
490
+ * @param {IterationType} iterationType - The `iterationType` parameter in the `override search`
491
+ * function determines the type of iteration to be used during the search operation. It can have two
492
+ * possible values:
493
+ * @returns The `override search` method returns an array of values that match the search criteria
494
+ * specified by the input parameters. The method performs a search operation on a binary tree
495
+ * structure based on the provided key, predicate, and other options. The search results are
496
+ * collected in an array and returned as the output of the method.
417
497
  */
418
- override getNodes(
419
- keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R | NodePredicate<NODE>,
498
+ override search<C extends NodeCallback<BSTNode<K, V>>>(
499
+ keyNodeEntryOrPredicate: BTNRep<K, V, BSTNode<K, V>> | NodePredicate<BSTNode<K, V>> | Range<K>,
420
500
  onlyOne = false,
421
- startNode: BTNRep<K, V, NODE> | R = this._root,
501
+ callback: C = this._DEFAULT_NODE_CALLBACK as C,
502
+ startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
422
503
  iterationType: IterationType = this.iterationType
423
- ): NODE[] {
424
- if (keyNodeEntryRawOrPredicate === undefined) return [];
425
- if (keyNodeEntryRawOrPredicate === null) return [];
504
+ ): ReturnType<C>[] {
505
+ if (keyNodeEntryOrPredicate === undefined) return [];
506
+ if (keyNodeEntryOrPredicate === null) return [];
426
507
  startNode = this.ensureNode(startNode);
427
508
  if (!startNode) return [];
428
- const callback = this._ensurePredicate(keyNodeEntryRawOrPredicate);
429
- const ans: NODE[] = [];
509
+ let predicate: NodePredicate<BSTNode<K, V>>;
430
510
 
511
+ const isRange = this.isRange(keyNodeEntryOrPredicate);
512
+ // Set predicate based on parameter type
513
+ if (isRange) {
514
+ predicate = node => keyNodeEntryOrPredicate.isInRange(node.key, this._comparator);
515
+ } else {
516
+ predicate = this._ensurePredicate(keyNodeEntryOrPredicate);
517
+ }
518
+ const isToLeftByRange = (cur: BSTNode<K, V>) => {
519
+ if (isRange) {
520
+ const range = keyNodeEntryOrPredicate;
521
+ const leftS = this.isReverse ? range.high : range.low;
522
+ const leftI = this.isReverse ? range.includeHigh : range.includeLow;
523
+ return (leftI && this._compare(cur.key, leftS) >= 0) || (!leftI && this._compare(cur.key, leftS) > 0);
524
+ }
525
+ return false;
526
+ };
527
+
528
+ const isToRightByRange = (cur: BSTNode<K, V>) => {
529
+ if (isRange) {
530
+ const range = keyNodeEntryOrPredicate;
531
+ const rightS = this.isReverse ? range.low : range.high;
532
+ const rightI = this.isReverse ? range.includeLow : range.includeLow;
533
+
534
+ return (rightI && this._compare(cur.key, rightS) <= 0) || (!rightI && this._compare(cur.key, rightS) < 0);
535
+ }
536
+ return false;
537
+ };
538
+ const ans: ReturnType<C>[] = [];
431
539
  if (iterationType === 'RECURSIVE') {
432
- const dfs = (cur: NODE) => {
433
- if (callback(cur)) {
434
- ans.push(cur);
540
+ const dfs = (cur: BSTNode<K, V>) => {
541
+ if (predicate(cur)) {
542
+ ans.push(callback(cur));
435
543
  if (onlyOne) return;
436
544
  }
437
545
 
438
546
  if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
439
- if (!this._isPredicate(keyNodeEntryRawOrPredicate)) {
440
- const benchmarkKey = this._getKey(keyNodeEntryRawOrPredicate);
547
+
548
+ if (isRange) {
549
+ if (this.isRealNode(cur.left) && isToLeftByRange(cur)) dfs(cur.left);
550
+ if (this.isRealNode(cur.right) && isToRightByRange(cur)) dfs(cur.right);
551
+ } else if (!this._isPredicate(keyNodeEntryOrPredicate)) {
552
+ const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
441
553
  if (
442
554
  this.isRealNode(cur.left) &&
443
555
  benchmarkKey !== null &&
444
556
  benchmarkKey !== undefined &&
445
- this.comparator(cur.key, benchmarkKey) > 0
557
+ this._compare(cur.key, benchmarkKey) > 0
446
558
  )
447
559
  dfs(cur.left);
448
560
  if (
449
561
  this.isRealNode(cur.right) &&
450
562
  benchmarkKey !== null &&
451
563
  benchmarkKey !== undefined &&
452
- this.comparator(cur.key, benchmarkKey) < 0
564
+ this._compare(cur.key, benchmarkKey) < 0
453
565
  )
454
566
  dfs(cur.right);
455
567
  } else {
@@ -463,24 +575,27 @@ export class BST<
463
575
  const stack = [startNode];
464
576
  while (stack.length > 0) {
465
577
  const cur = stack.pop()!;
466
- if (callback(cur)) {
467
- ans.push(cur);
578
+ if (predicate(cur)) {
579
+ ans.push(callback(cur));
468
580
  if (onlyOne) return ans;
469
581
  }
470
- if (!this._isPredicate(keyNodeEntryRawOrPredicate)) {
471
- const benchmarkKey = this._getKey(keyNodeEntryRawOrPredicate);
582
+ if (isRange) {
583
+ if (this.isRealNode(cur.left) && isToLeftByRange(cur)) stack.push(cur.left);
584
+ if (this.isRealNode(cur.right) && isToRightByRange(cur)) stack.push(cur.right);
585
+ } else if (!this._isPredicate(keyNodeEntryOrPredicate)) {
586
+ const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
472
587
  if (
473
588
  this.isRealNode(cur.right) &&
474
589
  benchmarkKey !== null &&
475
590
  benchmarkKey !== undefined &&
476
- this.comparator(cur.key, benchmarkKey) < 0
591
+ this._compare(cur.key, benchmarkKey) < 0
477
592
  )
478
593
  stack.push(cur.right);
479
594
  if (
480
595
  this.isRealNode(cur.left) &&
481
596
  benchmarkKey !== null &&
482
597
  benchmarkKey !== undefined &&
483
- this.comparator(cur.key, benchmarkKey) > 0
598
+ this._compare(cur.key, benchmarkKey) > 0
484
599
  )
485
600
  stack.push(cur.left);
486
601
  } else {
@@ -495,12 +610,43 @@ export class BST<
495
610
 
496
611
  /**
497
612
  * Time Complexity: O(log n)
498
- * 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)
499
645
  *
500
- * This function retrieves a node based on a given keyNodeEntryRawOrPredicate within a binary search tree structure.
501
- * @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate - The `keyNodeEntryRawOrPredicate`
502
- * parameter can be of type `BTNRep<K, V, NODE>`, `R`, or `NodePredicate<NODE>`.
503
- * @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
504
650
  * is used to specify the starting point for searching nodes in the binary search tree. If no
505
651
  * specific starting point is provided, the default value is set to `this._root`, which is the root
506
652
  * node of the binary search tree.
@@ -508,34 +654,17 @@ export class BST<
508
654
  * parameter that specifies the type of iteration to be used. It has a default value of
509
655
  * `this.iterationType`, which means it will use the iteration type defined in the class instance if
510
656
  * no value is provided when calling the method.
511
- * @returns The `getNode` method is returning an optional binary search tree node (`OptNode<NODE>`).
512
- * 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
513
659
  * the specified root node (`startNode`) and using the specified iteration type. The method then
514
660
  * returns the first node found or `undefined` if no node is found.
515
661
  */
516
662
  override getNode(
517
- keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R | NodePredicate<NODE>,
518
- 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,
519
665
  iterationType: IterationType = this.iterationType
520
- ): OptNode<NODE> {
521
- return this.getNodes(keyNodeEntryRawOrPredicate, true, startNode, iterationType)[0] ?? undefined;
522
- }
523
-
524
- /**
525
- * Time Complexity: O(log n)
526
- * Space Complexity: O(1)
527
- *
528
- * The function `getNodeByKey` returns a node with a specific key from a tree data structure.
529
- * @param {K} key - The key parameter is the value used to search for a specific node in the tree. It
530
- * is typically a unique identifier or a value that can be used to determine the position of the node
531
- * in the tree structure.
532
- * @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter is an optional
533
- * parameter that specifies the type of iteration to be used when searching for a node in the tree.
534
- * It has a default value of `'ITERATIVE'`.
535
- * @returns The method is returning a NODE object or undefined.
536
- */
537
- override getNodeByKey(key: K, iterationType: IterationType = this.iterationType): OptNode<NODE> {
538
- return this.getNode(key, this._root, iterationType);
666
+ ): OptNode<BSTNode<K, V>> {
667
+ return this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0] ?? undefined;
539
668
  }
540
669
 
541
670
  /**
@@ -550,7 +679,7 @@ export class BST<
550
679
  * @param {DFSOrderPattern} [pattern=IN] - The "pattern" parameter in the code snippet refers to the
551
680
  * order in which the Depth-First Search (DFS) algorithm visits the nodes in a tree or graph. It can
552
681
  * take one of the following values:
553
- * @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
554
683
  * point for the depth-first search traversal. It can be either a root node, a key-value pair, or a
555
684
  * node entry. If not specified, the default value is the root of the tree.
556
685
  * @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter specifies the
@@ -558,10 +687,10 @@ export class BST<
558
687
  * following values:
559
688
  * @returns The method is returning an array of the return type of the callback function.
560
689
  */
561
- override dfs<C extends NodeCallback<NODE>>(
690
+ override dfs<C extends NodeCallback<BSTNode<K, V>>>(
562
691
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
563
692
  pattern: DFSOrderPattern = 'IN',
564
- startNode: BTNRep<K, V, NODE> | R = this._root,
693
+ startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
565
694
  iterationType: IterationType = this.iterationType
566
695
  ): ReturnType<C>[] {
567
696
  return super.dfs(callback, pattern, startNode, iterationType);
@@ -576,7 +705,7 @@ export class BST<
576
705
  * @param {C} callback - The `callback` parameter is a function that will be called for each node
577
706
  * visited during the breadth-first search. It should take a single argument, which is the current
578
707
  * node being visited, and it can return a value of any type.
579
- * @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
580
709
  * point for the breadth-first search. It can be either a root node, a key-value pair, or an entry
581
710
  * object. If no value is provided, the default value is the root of the tree.
582
711
  * @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type
@@ -584,9 +713,9 @@ export class BST<
584
713
  * the following values:
585
714
  * @returns an array of the return type of the callback function.
586
715
  */
587
- override bfs<C extends NodeCallback<NODE>>(
716
+ override bfs<C extends NodeCallback<BSTNode<K, V>>>(
588
717
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
589
- startNode: BTNRep<K, V, NODE> | R = this._root,
718
+ startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
590
719
  iterationType: IterationType = this.iterationType
591
720
  ): ReturnType<C>[] {
592
721
  return super.bfs(callback, startNode, iterationType, false);
@@ -599,9 +728,9 @@ export class BST<
599
728
  * The function overrides the listLevels method from the superclass and returns an array of arrays
600
729
  * containing the results of the callback function applied to each level of the tree.
601
730
  * @param {C} callback - The `callback` parameter is a generic type `C` that extends
602
- * `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
603
732
  * tree during the iteration process.
604
- * @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
605
734
  * point for listing the levels of the binary tree. It can be either a root node of the tree, a
606
735
  * key-value pair representing a node in the tree, or a key representing a node in the tree. If no
607
736
  * value is provided, the root of
@@ -610,9 +739,9 @@ export class BST<
610
739
  * @returns The method is returning a two-dimensional array of the return type of the callback
611
740
  * function.
612
741
  */
613
- override listLevels<C extends NodeCallback<NODE>>(
742
+ override listLevels<C extends NodeCallback<BSTNode<K, V>>>(
614
743
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
615
- startNode: BTNRep<K, V, NODE> | R = this._root,
744
+ startNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
616
745
  iterationType: IterationType = this.iterationType
617
746
  ): ReturnType<C>[][] {
618
747
  return super.listLevels(callback, startNode, iterationType, false);
@@ -630,7 +759,7 @@ export class BST<
630
759
  * @param {CP} lesserOrGreater - The `lesserOrGreater` parameter is used to determine whether to
631
760
  * traverse nodes that are lesser, greater, or both than the `targetNode`. It accepts the values -1,
632
761
  * 0, or 1, where:
633
- * @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
634
763
  * the binary tree that you want to start traversing from. It can be specified either by providing
635
764
  * the key of the node, the node itself, or an entry containing the key and value of the node. If no
636
765
  * `targetNode` is provided,
@@ -639,24 +768,24 @@ export class BST<
639
768
  * @returns The function `lesserOrGreaterTraverse` returns an array of values of type
640
769
  * `ReturnType<C>`, which is the return type of the callback function passed as an argument.
641
770
  */
642
- lesserOrGreaterTraverse<C extends NodeCallback<NODE>>(
771
+ lesserOrGreaterTraverse<C extends NodeCallback<BSTNode<K, V>>>(
643
772
  callback: C = this._DEFAULT_NODE_CALLBACK as C,
644
773
  lesserOrGreater: CP = -1,
645
- targetNode: BTNRep<K, V, NODE> | R = this._root,
774
+ targetNode: BTNRep<K, V, BSTNode<K, V>> = this._root,
646
775
  iterationType: IterationType = this.iterationType
647
776
  ): ReturnType<C>[] {
648
777
  const targetNodeEnsured = this.ensureNode(targetNode);
649
- const ans: ReturnType<NodeCallback<NODE>>[] = [];
778
+ const ans: ReturnType<NodeCallback<BSTNode<K, V>>>[] = [];
650
779
  if (!this._root) return ans;
651
780
  if (!targetNodeEnsured) return ans;
652
781
 
653
782
  const targetKey = targetNodeEnsured.key;
654
783
 
655
784
  if (iterationType === 'RECURSIVE') {
656
- const dfs = (cur: NODE) => {
657
- const compared = this.comparator(cur.key, targetKey);
785
+ const dfs = (cur: BSTNode<K, V>) => {
786
+ const compared = this._compare(cur.key, targetKey);
658
787
  if (Math.sign(compared) === lesserOrGreater) ans.push(callback(cur));
659
-
788
+ // TODO here can be optimized to O(log n)
660
789
  if (this.isRealNode(cur.left)) dfs(cur.left);
661
790
  if (this.isRealNode(cur.right)) dfs(cur.right);
662
791
  };
@@ -664,11 +793,11 @@ export class BST<
664
793
  dfs(this._root);
665
794
  return ans;
666
795
  } else {
667
- const queue = new Queue<NODE>([this._root]);
796
+ const queue = new Queue<BSTNode<K, V>>([this._root]);
668
797
  while (queue.size > 0) {
669
798
  const cur = queue.shift();
670
799
  if (this.isRealNode(cur)) {
671
- const compared = this.comparator(cur.key, targetKey);
800
+ const compared = this._compare(cur.key, targetKey);
672
801
  if (Math.sign(compared) === lesserOrGreater) ans.push(callback(cur));
673
802
 
674
803
  if (this.isRealNode(cur.left)) queue.push(cur.left);
@@ -748,7 +877,7 @@ export class BST<
748
877
  let balanced = true;
749
878
 
750
879
  if (iterationType === 'RECURSIVE') {
751
- const _height = (cur: OptNode<NODE>): number => {
880
+ const _height = (cur: OptNodeOrNull<BSTNode<K, V>>): number => {
752
881
  if (!cur) return 0;
753
882
  const leftHeight = _height(cur.left),
754
883
  rightHeight = _height(cur.right);
@@ -757,15 +886,15 @@ export class BST<
757
886
  };
758
887
  _height(this._root);
759
888
  } else {
760
- const stack: NODE[] = [];
761
- let node: OptNode<NODE> = this._root,
762
- last: OptNode<NODE> = undefined;
763
- 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();
764
893
 
765
894
  while (stack.length > 0 || node) {
766
895
  if (node) {
767
896
  stack.push(node);
768
- node = node.left;
897
+ if (node.left !== null) node = node.left;
769
898
  } else {
770
899
  node = stack[stack.length - 1];
771
900
  if (!node.right || last === node.right) {
@@ -786,36 +915,103 @@ export class BST<
786
915
  return balanced;
787
916
  }
788
917
 
789
- protected _DEFAULT_COMPARATOR = (a: K, b: K): number => {
790
- if (typeof a === 'object' || typeof b === 'object') {
791
- throw TypeError(
792
- `When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
793
- );
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));
794
946
  }
795
- if (a > b) return 1;
796
- if (a < b) return -1;
797
- return 0;
798
- };
947
+ return newTree;
948
+ }
799
949
 
800
- protected _comparator: Comparator<K> = this._DEFAULT_COMPARATOR;
950
+ /**
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.
957
+ */
958
+ override clone() {
959
+ const cloned = this.createTree();
960
+ this._clone(cloned);
961
+ return cloned;
962
+ }
801
963
 
802
964
  /**
803
- * The function returns the value of the _comparator property.
804
- * @returns The `_comparator` property is being returned.
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.
805
975
  */
806
- get comparator() {
807
- return this._comparator;
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];
808
983
  }
809
984
 
810
985
  /**
986
+ * Time Complexity: O(1)
987
+ * Space Complexity: O(1)
988
+ *
811
989
  * The function sets the root of a tree-like structure and updates the parent property of the new
812
990
  * root.
813
- * @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.
814
992
  */
815
- protected override _setRoot(v: OptNode<NODE>) {
993
+ protected override _setRoot(v: OptNode<BSTNode<K, V>>) {
816
994
  if (v) {
817
995
  v.parent = undefined;
818
996
  }
819
997
  this._root = v;
820
998
  }
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
+ */
1014
+ protected _compare(a: K, b: K) {
1015
+ return this._isReverse ? -this._comparator(a, b) : this._comparator(a, b);
1016
+ }
821
1017
  }