data-structure-typed 1.52.8 → 1.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -1
- package/README.md +13 -13
- package/benchmark/report.html +13 -13
- package/benchmark/report.json +151 -151
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +22 -22
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +64 -47
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/avl-tree.d.ts +20 -20
- package/dist/cjs/data-structures/binary-tree/avl-tree.js +28 -26
- package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +240 -141
- package/dist/cjs/data-structures/binary-tree/binary-tree.js +395 -269
- package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/bst.d.ts +56 -56
- package/dist/cjs/data-structures/binary-tree/bst.js +114 -91
- package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/rb-tree.d.ts +13 -13
- package/dist/cjs/data-structures/binary-tree/rb-tree.js +35 -31
- package/dist/cjs/data-structures/binary-tree/rb-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.d.ts +22 -23
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +59 -48
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
- package/dist/cjs/data-structures/trie/trie.js +3 -3
- package/dist/cjs/interfaces/binary-tree.d.ts +5 -5
- package/dist/cjs/types/data-structures/binary-tree/binary-tree.d.ts +13 -13
- package/dist/cjs/types/data-structures/binary-tree/bst.d.ts +3 -3
- package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +22 -22
- package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.js +64 -46
- package/dist/mjs/data-structures/binary-tree/avl-tree.d.ts +20 -20
- package/dist/mjs/data-structures/binary-tree/avl-tree.js +28 -25
- package/dist/mjs/data-structures/binary-tree/binary-tree.d.ts +240 -141
- package/dist/mjs/data-structures/binary-tree/binary-tree.js +395 -268
- package/dist/mjs/data-structures/binary-tree/bst.d.ts +56 -56
- package/dist/mjs/data-structures/binary-tree/bst.js +114 -89
- package/dist/mjs/data-structures/binary-tree/rb-tree.d.ts +13 -13
- package/dist/mjs/data-structures/binary-tree/rb-tree.js +35 -30
- package/dist/mjs/data-structures/binary-tree/tree-multi-map.d.ts +22 -23
- package/dist/mjs/data-structures/binary-tree/tree-multi-map.js +59 -47
- package/dist/mjs/data-structures/trie/trie.js +3 -3
- package/dist/mjs/interfaces/binary-tree.d.ts +5 -5
- package/dist/mjs/types/data-structures/binary-tree/binary-tree.d.ts +13 -13
- package/dist/mjs/types/data-structures/binary-tree/bst.d.ts +3 -3
- package/dist/umd/data-structure-typed.js +617 -482
- package/dist/umd/data-structure-typed.min.js +5 -5
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +6 -6
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +60 -55
- package/src/data-structures/binary-tree/avl-tree.ts +31 -35
- package/src/data-structures/binary-tree/binary-tree.ts +461 -385
- package/src/data-structures/binary-tree/bst.ts +155 -128
- package/src/data-structures/binary-tree/rb-tree.ts +37 -39
- package/src/data-structures/binary-tree/tree-multi-map.ts +57 -60
- package/src/data-structures/trie/trie.ts +3 -3
- package/src/interfaces/binary-tree.ts +6 -6
- package/src/types/data-structures/binary-tree/binary-tree.ts +14 -15
- package/src/types/data-structures/binary-tree/bst.ts +4 -4
- package/test/integration/bst.test.ts +2 -2
- package/test/performance/data-structures/binary-tree/avl-tree.test.ts +1 -1
- package/test/performance/data-structures/binary-tree/binary-tree-overall.test.ts +2 -2
- package/test/performance/data-structures/binary-tree/binary-tree.test.ts +1 -1
- package/test/performance/data-structures/binary-tree/bst.test.ts +1 -1
- package/test/performance/data-structures/binary-tree/rb-tree.test.ts +1 -1
- package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +113 -1
- package/test/unit/data-structures/binary-tree/avl-tree.test.ts +107 -1
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +169 -26
- package/test/unit/data-structures/binary-tree/bst.test.ts +326 -21
- package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +139 -1
|
@@ -68,25 +68,35 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
68
68
|
/**
|
|
69
69
|
* The constructor initializes a binary tree with optional options and adds keys, nodes, entries, or
|
|
70
70
|
* raw data if provided.
|
|
71
|
-
* @param
|
|
72
|
-
* is an iterable that can contain elements of type `
|
|
71
|
+
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor
|
|
72
|
+
* is an iterable that can contain elements of type `BTNRep<K, V, NODE>` or `R`. It is
|
|
73
73
|
* initialized with an empty array `[]` by default.
|
|
74
74
|
* @param [options] - The `options` parameter in the constructor is an object that can contain the
|
|
75
75
|
* following properties:
|
|
76
76
|
*/
|
|
77
|
-
constructor(
|
|
77
|
+
constructor(keysNodesEntriesOrRaws = [], options) {
|
|
78
78
|
super();
|
|
79
79
|
if (options) {
|
|
80
|
-
const { iterationType, toEntryFn } = options;
|
|
80
|
+
const { iterationType, toEntryFn, isMapMode } = options;
|
|
81
81
|
if (iterationType)
|
|
82
82
|
this.iterationType = iterationType;
|
|
83
|
+
if (isMapMode !== undefined)
|
|
84
|
+
this._isMapMode = isMapMode;
|
|
83
85
|
if (typeof toEntryFn === 'function')
|
|
84
86
|
this._toEntryFn = toEntryFn;
|
|
85
87
|
else if (toEntryFn)
|
|
86
88
|
throw TypeError('toEntryFn must be a function type');
|
|
87
89
|
}
|
|
88
|
-
if (
|
|
89
|
-
this.addMany(
|
|
90
|
+
if (keysNodesEntriesOrRaws)
|
|
91
|
+
this.addMany(keysNodesEntriesOrRaws);
|
|
92
|
+
}
|
|
93
|
+
_isMapMode = false;
|
|
94
|
+
get isMapMode() {
|
|
95
|
+
return this._isMapMode;
|
|
96
|
+
}
|
|
97
|
+
_store = new Map();
|
|
98
|
+
get store() {
|
|
99
|
+
return this._store;
|
|
90
100
|
}
|
|
91
101
|
_root;
|
|
92
102
|
get root() {
|
|
@@ -127,51 +137,54 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
127
137
|
createTree(options) {
|
|
128
138
|
return new BinaryTree([], {
|
|
129
139
|
iterationType: this.iterationType,
|
|
140
|
+
isMapMode: this._isMapMode,
|
|
130
141
|
toEntryFn: this._toEntryFn,
|
|
131
142
|
...options
|
|
132
143
|
});
|
|
133
144
|
}
|
|
134
145
|
/**
|
|
135
|
-
* The function `
|
|
146
|
+
* The function `keyValueNodeEntryRawToNodeAndValue` converts various input types into a node object
|
|
136
147
|
* or returns null.
|
|
137
|
-
* @param {
|
|
138
|
-
* `
|
|
139
|
-
* can be of type `
|
|
148
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The
|
|
149
|
+
* `keyValueNodeEntryRawToNodeAndValue` function takes in a parameter `keyNodeEntryOrRaw`, which
|
|
150
|
+
* can be of type `BTNRep<K, V, NODE>` or `R`. This parameter represents either a key, a
|
|
140
151
|
* node, an entry
|
|
141
|
-
* @param {V} [value] - The `value` parameter in the `
|
|
152
|
+
* @param {V} [value] - The `value` parameter in the `keyValueNodeEntryRawToNodeAndValue` function is
|
|
142
153
|
* an optional parameter of type `V`. It represents the value associated with the key in the node
|
|
143
154
|
* being created. If a `value` is provided, it will be used when creating the node. If
|
|
144
|
-
* @returns The `
|
|
145
|
-
* (`
|
|
146
|
-
* input parameter (`
|
|
155
|
+
* @returns The `keyValueNodeEntryRawToNodeAndValue` function returns an optional node
|
|
156
|
+
* (`OptNodeOrNull<NODE>`) based on the input parameters provided. The function checks the type of the
|
|
157
|
+
* input parameter (`keyNodeEntryOrRaw`) and processes it accordingly to return a node or null
|
|
147
158
|
* value.
|
|
148
159
|
*/
|
|
149
|
-
|
|
150
|
-
if (
|
|
151
|
-
return;
|
|
152
|
-
if (
|
|
153
|
-
return null;
|
|
154
|
-
if (this.isNode(
|
|
155
|
-
return
|
|
156
|
-
if (this.isEntry(
|
|
157
|
-
const [key, entryValue] =
|
|
160
|
+
keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value) {
|
|
161
|
+
if (keyNodeEntryOrRaw === undefined)
|
|
162
|
+
return [undefined, undefined];
|
|
163
|
+
if (keyNodeEntryOrRaw === null)
|
|
164
|
+
return [null, undefined];
|
|
165
|
+
if (this.isNode(keyNodeEntryOrRaw))
|
|
166
|
+
return [keyNodeEntryOrRaw, value];
|
|
167
|
+
if (this.isEntry(keyNodeEntryOrRaw)) {
|
|
168
|
+
const [key, entryValue] = keyNodeEntryOrRaw;
|
|
158
169
|
if (key === undefined)
|
|
159
|
-
return;
|
|
170
|
+
return [undefined, undefined];
|
|
160
171
|
else if (key === null)
|
|
161
|
-
return null;
|
|
162
|
-
|
|
163
|
-
|
|
172
|
+
return [null, undefined];
|
|
173
|
+
const finalValue = value ?? entryValue;
|
|
174
|
+
return [this.createNode(key, finalValue), finalValue];
|
|
164
175
|
}
|
|
165
|
-
if (this.
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
176
|
+
if (this.isKey(keyNodeEntryOrRaw))
|
|
177
|
+
return [this.createNode(keyNodeEntryOrRaw, value), value];
|
|
178
|
+
if (this.isRaw(keyNodeEntryOrRaw)) {
|
|
179
|
+
if (this._toEntryFn) {
|
|
180
|
+
const [key, entryValue] = this._toEntryFn(keyNodeEntryOrRaw);
|
|
181
|
+
const finalValue = value ?? entryValue;
|
|
182
|
+
if (this.isKey(key))
|
|
183
|
+
return [this.createNode(key, finalValue), finalValue];
|
|
184
|
+
}
|
|
185
|
+
return [undefined, undefined];
|
|
171
186
|
}
|
|
172
|
-
|
|
173
|
-
return this.createNode(keyOrNodeOrEntryOrRaw, value);
|
|
174
|
-
return;
|
|
187
|
+
return [undefined, undefined];
|
|
175
188
|
}
|
|
176
189
|
/**
|
|
177
190
|
* Time Complexity: O(n)
|
|
@@ -179,8 +192,8 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
179
192
|
*
|
|
180
193
|
* The function `ensureNode` in TypeScript checks if a given input is a node, entry, key, or raw
|
|
181
194
|
* value and returns the corresponding node or null.
|
|
182
|
-
* @param {
|
|
183
|
-
* parameter in the `ensureNode` function can be of type `
|
|
195
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The `keyNodeEntryOrRaw`
|
|
196
|
+
* parameter in the `ensureNode` function can be of type `BTNRep<K, V, NODE>` or `R`. It
|
|
184
197
|
* is used to determine whether the input is a key, node, entry, or raw data. The
|
|
185
198
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `ensureNode` function
|
|
186
199
|
* is used to specify the type of iteration to be performed. It has a default value of
|
|
@@ -188,17 +201,17 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
188
201
|
* @returns The `ensureNode` function returns either a node, `null`, or `undefined` based on the
|
|
189
202
|
* conditions specified in the code snippet.
|
|
190
203
|
*/
|
|
191
|
-
ensureNode(
|
|
192
|
-
if (
|
|
204
|
+
ensureNode(keyNodeEntryOrRaw, iterationType = this.iterationType) {
|
|
205
|
+
if (keyNodeEntryOrRaw === null)
|
|
193
206
|
return null;
|
|
194
|
-
if (
|
|
207
|
+
if (keyNodeEntryOrRaw === undefined)
|
|
195
208
|
return;
|
|
196
|
-
if (
|
|
209
|
+
if (keyNodeEntryOrRaw === this._NIL)
|
|
197
210
|
return;
|
|
198
|
-
if (this.isNode(
|
|
199
|
-
return
|
|
200
|
-
if (this.isEntry(
|
|
201
|
-
const key =
|
|
211
|
+
if (this.isNode(keyNodeEntryOrRaw))
|
|
212
|
+
return keyNodeEntryOrRaw;
|
|
213
|
+
if (this.isEntry(keyNodeEntryOrRaw)) {
|
|
214
|
+
const key = keyNodeEntryOrRaw[0];
|
|
202
215
|
if (key === null)
|
|
203
216
|
return null;
|
|
204
217
|
if (key === undefined)
|
|
@@ -206,95 +219,98 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
206
219
|
return this.getNodeByKey(key, iterationType);
|
|
207
220
|
}
|
|
208
221
|
if (this._toEntryFn) {
|
|
209
|
-
const [key] = this._toEntryFn(
|
|
222
|
+
const [key] = this._toEntryFn(keyNodeEntryOrRaw);
|
|
210
223
|
if (this.isKey(key))
|
|
211
224
|
return this.getNodeByKey(key);
|
|
212
225
|
}
|
|
213
|
-
if (this.isKey(
|
|
214
|
-
return this.getNodeByKey(
|
|
226
|
+
if (this.isKey(keyNodeEntryOrRaw))
|
|
227
|
+
return this.getNodeByKey(keyNodeEntryOrRaw, iterationType);
|
|
215
228
|
return;
|
|
216
229
|
}
|
|
217
230
|
/**
|
|
218
231
|
* The function isNode checks if the input is an instance of BinaryTreeNode.
|
|
219
|
-
* @param {
|
|
220
|
-
* `
|
|
232
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
|
|
233
|
+
* `keyNodeEntryOrRaw` can be either a key, a node, an entry, or raw data. The function is
|
|
221
234
|
* checking if the input is an instance of a `BinaryTreeNode` and returning a boolean value
|
|
222
235
|
* accordingly.
|
|
223
|
-
* @returns The function `isNode` is checking if the input `
|
|
236
|
+
* @returns The function `isNode` is checking if the input `keyNodeEntryOrRaw` is an instance of
|
|
224
237
|
* `BinaryTreeNode`. If it is, the function returns `true`, indicating that the input is a node. If
|
|
225
238
|
* it is not an instance of `BinaryTreeNode`, the function returns `false`, indicating that the input
|
|
226
239
|
* is not a node.
|
|
227
240
|
*/
|
|
228
|
-
isNode(
|
|
229
|
-
return
|
|
241
|
+
isNode(keyNodeEntryOrRaw) {
|
|
242
|
+
return keyNodeEntryOrRaw instanceof BinaryTreeNode;
|
|
243
|
+
}
|
|
244
|
+
isRaw(keyNodeEntryOrRaw) {
|
|
245
|
+
return typeof keyNodeEntryOrRaw === 'object';
|
|
230
246
|
}
|
|
231
247
|
/**
|
|
232
248
|
* The function `isRealNode` checks if a given input is a valid node in a binary tree.
|
|
233
|
-
* @param {
|
|
234
|
-
* parameter in the `isRealNode` function can be of type `
|
|
249
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The `keyNodeEntryOrRaw`
|
|
250
|
+
* parameter in the `isRealNode` function can be of type `BTNRep<K, V, NODE>` or `R`.
|
|
235
251
|
* The function checks if the input parameter is a `NODE` type by verifying if it is not equal
|
|
236
|
-
* @returns The function `isRealNode` is checking if the input `
|
|
252
|
+
* @returns The function `isRealNode` is checking if the input `keyNodeEntryOrRaw` is a valid
|
|
237
253
|
* node by comparing it to `this._NIL`, `null`, and `undefined`. If the input is not one of these
|
|
238
254
|
* values, it then calls the `isNode` method to further determine if the input is a node. The
|
|
239
255
|
* function will return a boolean value indicating whether the
|
|
240
256
|
*/
|
|
241
|
-
isRealNode(
|
|
242
|
-
if (
|
|
257
|
+
isRealNode(keyNodeEntryOrRaw) {
|
|
258
|
+
if (keyNodeEntryOrRaw === this._NIL || keyNodeEntryOrRaw === null || keyNodeEntryOrRaw === undefined)
|
|
243
259
|
return false;
|
|
244
|
-
return this.isNode(
|
|
260
|
+
return this.isNode(keyNodeEntryOrRaw);
|
|
245
261
|
}
|
|
246
262
|
/**
|
|
247
263
|
* The function checks if a given input is a valid node or null.
|
|
248
|
-
* @param {
|
|
249
|
-
* `
|
|
264
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
|
|
265
|
+
* `keyNodeEntryOrRaw` in the `isRealNodeOrNull` function can be of type `BTNRep<K,
|
|
250
266
|
* V, NODE>` or `R`. It is a union type that can either be a key, a node, an entry, or
|
|
251
267
|
* @returns The function `isRealNodeOrNull` is returning a boolean value. It checks if the input
|
|
252
|
-
* `
|
|
268
|
+
* `keyNodeEntryOrRaw` is either `null` or a real node, and returns `true` if it is a node or
|
|
253
269
|
* `null`, and `false` otherwise.
|
|
254
270
|
*/
|
|
255
|
-
isRealNodeOrNull(
|
|
256
|
-
return
|
|
271
|
+
isRealNodeOrNull(keyNodeEntryOrRaw) {
|
|
272
|
+
return keyNodeEntryOrRaw === null || this.isRealNode(keyNodeEntryOrRaw);
|
|
257
273
|
}
|
|
258
274
|
/**
|
|
259
275
|
* The function isNIL checks if a given key, node, entry, or raw value is equal to the _NIL value.
|
|
260
|
-
* @param {
|
|
276
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - BTNRep<K, V,
|
|
261
277
|
* NODE> | R
|
|
262
|
-
* @returns The function is checking if the `
|
|
278
|
+
* @returns The function is checking if the `keyNodeEntryOrRaw` parameter is equal to the `_NIL`
|
|
263
279
|
* property of the current object and returning a boolean value based on that comparison.
|
|
264
280
|
*/
|
|
265
|
-
isNIL(
|
|
266
|
-
return
|
|
281
|
+
isNIL(keyNodeEntryOrRaw) {
|
|
282
|
+
return keyNodeEntryOrRaw === this._NIL;
|
|
267
283
|
}
|
|
268
284
|
/**
|
|
269
285
|
* The function determines whether a given key, node, entry, or raw data is a leaf node in a binary
|
|
270
286
|
* tree.
|
|
271
|
-
* @param {
|
|
272
|
-
* `
|
|
287
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
|
|
288
|
+
* `keyNodeEntryOrRaw` can be of type `BTNRep<K, V, NODE>` or `R`. It represents a
|
|
273
289
|
* key, node, entry, or raw data in a binary tree structure. The function `isLeaf` checks whether the
|
|
274
290
|
* provided
|
|
275
291
|
* @returns The function `isLeaf` returns a boolean value indicating whether the input
|
|
276
|
-
* `
|
|
292
|
+
* `keyNodeEntryOrRaw` is a leaf node in a binary tree.
|
|
277
293
|
*/
|
|
278
|
-
isLeaf(
|
|
279
|
-
|
|
280
|
-
if (
|
|
294
|
+
isLeaf(keyNodeEntryOrRaw) {
|
|
295
|
+
keyNodeEntryOrRaw = this.ensureNode(keyNodeEntryOrRaw);
|
|
296
|
+
if (keyNodeEntryOrRaw === undefined)
|
|
281
297
|
return false;
|
|
282
|
-
if (
|
|
298
|
+
if (keyNodeEntryOrRaw === null)
|
|
283
299
|
return true;
|
|
284
|
-
return !this.isRealNode(
|
|
300
|
+
return !this.isRealNode(keyNodeEntryOrRaw.left) && !this.isRealNode(keyNodeEntryOrRaw.right);
|
|
285
301
|
}
|
|
286
302
|
/**
|
|
287
303
|
* The function `isEntry` checks if the input is a BTNEntry object by verifying if it is an array
|
|
288
304
|
* with a length of 2.
|
|
289
|
-
* @param {
|
|
290
|
-
* parameter in the `isEntry` function can be of type `
|
|
291
|
-
* The function checks if the provided `
|
|
292
|
-
* @returns The `isEntry` function is checking if the `
|
|
305
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The `keyNodeEntryOrRaw`
|
|
306
|
+
* parameter in the `isEntry` function can be of type `BTNRep<K, V, NODE>` or type `R`.
|
|
307
|
+
* The function checks if the provided `keyNodeEntryOrRaw` is of type `BTN
|
|
308
|
+
* @returns The `isEntry` function is checking if the `keyNodeEntryOrRaw` parameter is an array
|
|
293
309
|
* with a length of 2. If it is, then it returns `true`, indicating that the parameter is of type
|
|
294
310
|
* `BTNEntry<K, V>`. If the condition is not met, it returns `false`.
|
|
295
311
|
*/
|
|
296
|
-
isEntry(
|
|
297
|
-
return Array.isArray(
|
|
312
|
+
isEntry(keyNodeEntryOrRaw) {
|
|
313
|
+
return Array.isArray(keyNodeEntryOrRaw) && keyNodeEntryOrRaw.length === 2;
|
|
298
314
|
}
|
|
299
315
|
/**
|
|
300
316
|
* Time Complexity O(1)
|
|
@@ -318,8 +334,8 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
318
334
|
*
|
|
319
335
|
* The `add` function in TypeScript adds a new node to a binary tree while handling duplicate keys
|
|
320
336
|
* and finding the correct insertion position.
|
|
321
|
-
* @param {
|
|
322
|
-
* seems to be for adding a new node to a binary tree structure. The `
|
|
337
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The `add` method you provided
|
|
338
|
+
* seems to be for adding a new node to a binary tree structure. The `keyNodeEntryOrRaw`
|
|
323
339
|
* parameter in the method can accept different types of values:
|
|
324
340
|
* @param {V} [value] - The `value` parameter in the `add` method represents the value associated
|
|
325
341
|
* with the key that you want to add to the binary tree. When adding a key-value pair to the binary
|
|
@@ -329,13 +345,15 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
329
345
|
* node was successful, and `false` if the insertion position could not be found or if a duplicate
|
|
330
346
|
* key was found and the node was replaced instead of inserted.
|
|
331
347
|
*/
|
|
332
|
-
add(
|
|
333
|
-
const newNode = this.
|
|
348
|
+
add(keyNodeEntryOrRaw, value) {
|
|
349
|
+
const [newNode, newValue] = this.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
|
|
334
350
|
if (newNode === undefined)
|
|
335
351
|
return false;
|
|
336
352
|
// If the tree is empty, directly set the new node as the root node
|
|
337
353
|
if (!this._root) {
|
|
338
354
|
this._setRoot(newNode);
|
|
355
|
+
if (this._isMapMode)
|
|
356
|
+
this._setValue(newNode?.key, newValue);
|
|
339
357
|
this._size = 1;
|
|
340
358
|
return true;
|
|
341
359
|
}
|
|
@@ -348,6 +366,8 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
348
366
|
// Check for duplicate keys when newNode is not null
|
|
349
367
|
if (newNode !== null && cur.key === newNode.key) {
|
|
350
368
|
this._replaceNode(cur, newNode);
|
|
369
|
+
if (this._isMapMode)
|
|
370
|
+
this._setValue(cur.key, newValue);
|
|
351
371
|
return true; // If duplicate keys are found, no insertion is performed
|
|
352
372
|
}
|
|
353
373
|
// Record the first possible insertion location found
|
|
@@ -372,6 +392,8 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
372
392
|
else if (potentialParent.right === undefined) {
|
|
373
393
|
potentialParent.right = newNode;
|
|
374
394
|
}
|
|
395
|
+
if (this._isMapMode)
|
|
396
|
+
this._setValue(newNode?.key, newValue);
|
|
375
397
|
this._size++;
|
|
376
398
|
return true;
|
|
377
399
|
}
|
|
@@ -384,25 +406,25 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
384
406
|
* The `addMany` function takes in multiple keys or nodes or entries or raw values along with
|
|
385
407
|
* optional values, and adds them to a data structure while returning an array indicating whether
|
|
386
408
|
* each insertion was successful.
|
|
387
|
-
* @param
|
|
409
|
+
* @param keysNodesEntriesOrRaws - `keysNodesEntriesOrRaws` is an iterable that can contain a
|
|
388
410
|
* mix of keys, nodes, entries, or raw values. Each element in this iterable can be of type
|
|
389
|
-
* `
|
|
411
|
+
* `BTNRep<K, V, NODE>` or `R`.
|
|
390
412
|
* @param [values] - The `values` parameter in the `addMany` function is an optional parameter that
|
|
391
413
|
* accepts an iterable of values. These values correspond to the keys or nodes being added in the
|
|
392
|
-
* `
|
|
414
|
+
* `keysNodesEntriesOrRaws` parameter. If provided, the function will iterate over the values and
|
|
393
415
|
* assign them
|
|
394
416
|
* @returns The `addMany` method returns an array of boolean values indicating whether each key,
|
|
395
417
|
* node, entry, or raw value was successfully added to the data structure. Each boolean value
|
|
396
418
|
* corresponds to the success of adding the corresponding key or value in the input iterable.
|
|
397
419
|
*/
|
|
398
|
-
addMany(
|
|
420
|
+
addMany(keysNodesEntriesOrRaws, values) {
|
|
399
421
|
// TODO not sure addMany not be run multi times
|
|
400
422
|
const inserted = [];
|
|
401
423
|
let valuesIterator;
|
|
402
424
|
if (values) {
|
|
403
425
|
valuesIterator = values[Symbol.iterator]();
|
|
404
426
|
}
|
|
405
|
-
for (const
|
|
427
|
+
for (const keyNodeEntryOrRaw of keysNodesEntriesOrRaws) {
|
|
406
428
|
let value = undefined;
|
|
407
429
|
if (valuesIterator) {
|
|
408
430
|
const valueResult = valuesIterator.next();
|
|
@@ -410,7 +432,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
410
432
|
value = valueResult.value;
|
|
411
433
|
}
|
|
412
434
|
}
|
|
413
|
-
inserted.push(this.add(
|
|
435
|
+
inserted.push(this.add(keyNodeEntryOrRaw, value));
|
|
414
436
|
}
|
|
415
437
|
return inserted;
|
|
416
438
|
}
|
|
@@ -420,15 +442,15 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
420
442
|
*
|
|
421
443
|
* The `refill` function clears the existing data structure and then adds new key-value pairs based
|
|
422
444
|
* on the provided input.
|
|
423
|
-
* @param
|
|
424
|
-
* method can accept an iterable containing a mix of `
|
|
445
|
+
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the `refill`
|
|
446
|
+
* method can accept an iterable containing a mix of `BTNRep<K, V, NODE>` objects or `R`
|
|
425
447
|
* objects.
|
|
426
448
|
* @param [values] - The `values` parameter in the `refill` method is an optional parameter that
|
|
427
449
|
* accepts an iterable of values of type `V` or `undefined`.
|
|
428
450
|
*/
|
|
429
|
-
refill(
|
|
451
|
+
refill(keysNodesEntriesOrRaws, values) {
|
|
430
452
|
this.clear();
|
|
431
|
-
this.addMany(
|
|
453
|
+
this.addMany(keysNodesEntriesOrRaws, values);
|
|
432
454
|
}
|
|
433
455
|
/**
|
|
434
456
|
* Time Complexity: O(n)
|
|
@@ -436,20 +458,20 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
436
458
|
*
|
|
437
459
|
* The function `delete` in TypeScript implements the deletion of a node in a binary tree and returns
|
|
438
460
|
* the deleted node along with information for tree balancing.
|
|
439
|
-
* @param {
|
|
461
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw
|
|
440
462
|
* - The `delete` method you provided is used to delete a node from a binary tree based on the key,
|
|
441
|
-
* node, entry
|
|
463
|
+
* node, entry or raw data. The method returns an array of
|
|
442
464
|
* `BinaryTreeDeleteResult` objects containing information about the deleted node and whether
|
|
443
465
|
* balancing is needed.
|
|
444
466
|
* @returns The `delete` method returns an array of `BinaryTreeDeleteResult` objects. Each object in
|
|
445
467
|
* the array contains information about the node that was deleted (`deleted`) and the node that may
|
|
446
468
|
* need to be balanced (`needBalanced`).
|
|
447
469
|
*/
|
|
448
|
-
delete(
|
|
470
|
+
delete(keyNodeEntryOrRaw) {
|
|
449
471
|
const deletedResult = [];
|
|
450
472
|
if (!this._root)
|
|
451
473
|
return deletedResult;
|
|
452
|
-
const curr = this.getNode(
|
|
474
|
+
const curr = this.getNode(keyNodeEntryOrRaw);
|
|
453
475
|
if (!curr)
|
|
454
476
|
return deletedResult;
|
|
455
477
|
const parent = curr?.parent;
|
|
@@ -488,6 +510,8 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
488
510
|
}
|
|
489
511
|
this._size = this._size - 1;
|
|
490
512
|
deletedResult.push({ deleted: orgCurrent, needBalanced });
|
|
513
|
+
if (this._isMapMode && orgCurrent)
|
|
514
|
+
this._store.delete(orgCurrent.key);
|
|
491
515
|
return deletedResult;
|
|
492
516
|
}
|
|
493
517
|
/**
|
|
@@ -496,12 +520,12 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
496
520
|
*
|
|
497
521
|
* The function `getNodes` retrieves nodes from a binary tree based on a key, node, entry, raw data,
|
|
498
522
|
* or predicate, with options for recursive or iterative traversal.
|
|
499
|
-
* @param {
|
|
523
|
+
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate
|
|
500
524
|
* - The `getNodes` function you provided takes several parameters:
|
|
501
525
|
* @param [onlyOne=false] - The `onlyOne` parameter in the `getNodes` function is a boolean flag that
|
|
502
526
|
* determines whether to return only the first node that matches the criteria specified by the
|
|
503
|
-
* `
|
|
504
|
-
* @param {
|
|
527
|
+
* `keyNodeEntryRawOrPredicate` parameter. If `onlyOne` is set to `true`, the function will
|
|
528
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
505
529
|
* `getNodes` function is used to specify the starting point for traversing the binary tree. It
|
|
506
530
|
* represents the root node of the binary tree or the node from which the traversal should begin. If
|
|
507
531
|
* not provided, the default value is set to `this._root
|
|
@@ -511,15 +535,15 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
511
535
|
* @returns The `getNodes` function returns an array of nodes that satisfy the provided condition
|
|
512
536
|
* based on the input parameters and the iteration type specified.
|
|
513
537
|
*/
|
|
514
|
-
getNodes(
|
|
515
|
-
if (
|
|
538
|
+
getNodes(keyNodeEntryRawOrPredicate, onlyOne = false, startNode = this._root, iterationType = this.iterationType) {
|
|
539
|
+
if (keyNodeEntryRawOrPredicate === undefined)
|
|
516
540
|
return [];
|
|
517
|
-
if (
|
|
541
|
+
if (keyNodeEntryRawOrPredicate === null)
|
|
518
542
|
return [];
|
|
519
|
-
|
|
520
|
-
if (!
|
|
543
|
+
startNode = this.ensureNode(startNode);
|
|
544
|
+
if (!startNode)
|
|
521
545
|
return [];
|
|
522
|
-
const callback = this._ensurePredicate(
|
|
546
|
+
const callback = this._ensurePredicate(keyNodeEntryRawOrPredicate);
|
|
523
547
|
const ans = [];
|
|
524
548
|
if (iterationType === 'RECURSIVE') {
|
|
525
549
|
const dfs = (cur) => {
|
|
@@ -535,10 +559,10 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
535
559
|
if (this.isRealNode(cur.right))
|
|
536
560
|
dfs(cur.right);
|
|
537
561
|
};
|
|
538
|
-
dfs(
|
|
562
|
+
dfs(startNode);
|
|
539
563
|
}
|
|
540
564
|
else {
|
|
541
|
-
const stack = [
|
|
565
|
+
const stack = [startNode];
|
|
542
566
|
while (stack.length > 0) {
|
|
543
567
|
const cur = stack.pop();
|
|
544
568
|
if (this.isRealNode(cur)) {
|
|
@@ -562,10 +586,10 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
562
586
|
*
|
|
563
587
|
* The `getNode` function retrieves a node based on the provided key, node, entry, raw data, or
|
|
564
588
|
* predicate.
|
|
565
|
-
* @param {
|
|
566
|
-
* - The `
|
|
589
|
+
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate
|
|
590
|
+
* - The `keyNodeEntryRawOrPredicate` parameter in the `getNode` function can accept a key,
|
|
567
591
|
* node, entry, raw data, or a predicate function.
|
|
568
|
-
* @param {
|
|
592
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
569
593
|
* `getNode` function is used to specify the starting point for searching for a node in a binary
|
|
570
594
|
* tree. If no specific starting point is provided, the default value is set to `this._root`, which
|
|
571
595
|
* is typically the root node of the binary tree.
|
|
@@ -576,8 +600,8 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
576
600
|
* @returns The `getNode` function is returning the first node that matches the specified criteria,
|
|
577
601
|
* or `null` if no matching node is found.
|
|
578
602
|
*/
|
|
579
|
-
getNode(
|
|
580
|
-
return this.getNodes(
|
|
603
|
+
getNode(keyNodeEntryRawOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
604
|
+
return this.getNodes(keyNodeEntryRawOrPredicate, true, startNode, iterationType)[0] ?? null;
|
|
581
605
|
}
|
|
582
606
|
/**
|
|
583
607
|
* Time Complexity: O(n)
|
|
@@ -590,7 +614,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
590
614
|
* specifies how the tree nodes should be traversed when searching for a node with the given key. It
|
|
591
615
|
* is an optional parameter with a default value of `this.iterationType`.
|
|
592
616
|
* @returns The `getNodeByKey` function is returning an optional binary tree node
|
|
593
|
-
* (`
|
|
617
|
+
* (`OptNodeOrNull<NODE>`).
|
|
594
618
|
*/
|
|
595
619
|
getNodeByKey(key, iterationType = this.iterationType) {
|
|
596
620
|
return this.getNode(key, this._root, iterationType);
|
|
@@ -601,10 +625,10 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
601
625
|
*
|
|
602
626
|
* This function overrides the `get` method to retrieve the value associated with a specified key,
|
|
603
627
|
* node, entry, raw data, or predicate in a data structure.
|
|
604
|
-
* @param {
|
|
605
|
-
* - The `
|
|
628
|
+
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate
|
|
629
|
+
* - The `keyNodeEntryRawOrPredicate` parameter in the `get` method can accept one of the
|
|
606
630
|
* following types:
|
|
607
|
-
* @param {
|
|
631
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `get`
|
|
608
632
|
* method is used to specify the starting point for searching for a key or node in the binary tree.
|
|
609
633
|
* If no specific starting point is provided, the default starting point is the root of the binary
|
|
610
634
|
* tree (`this._root`).
|
|
@@ -617,8 +641,14 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
617
641
|
* the method returns the corresponding value. If the key or node is not found, it returns
|
|
618
642
|
* `undefined`.
|
|
619
643
|
*/
|
|
620
|
-
get(
|
|
621
|
-
|
|
644
|
+
get(keyNodeEntryRawOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
645
|
+
if (this._isMapMode) {
|
|
646
|
+
const key = this._getKey(keyNodeEntryRawOrPredicate);
|
|
647
|
+
if (key === null || key === undefined)
|
|
648
|
+
return;
|
|
649
|
+
return this._store.get(key);
|
|
650
|
+
}
|
|
651
|
+
return this.getNode(keyNodeEntryRawOrPredicate, startNode, iterationType)?.value;
|
|
622
652
|
}
|
|
623
653
|
/**
|
|
624
654
|
* Time Complexity: O(n)
|
|
@@ -626,10 +656,10 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
626
656
|
*
|
|
627
657
|
* The `has` function in TypeScript checks if a specified key, node, entry, raw data, or predicate
|
|
628
658
|
* exists in the data structure.
|
|
629
|
-
* @param {
|
|
630
|
-
* - The `
|
|
659
|
+
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate
|
|
660
|
+
* - The `keyNodeEntryRawOrPredicate` parameter in the `override has` method can accept one of
|
|
631
661
|
* the following types:
|
|
632
|
-
* @param {
|
|
662
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
633
663
|
* `override` method is used to specify the starting point for the search operation within the data
|
|
634
664
|
* structure. It defaults to `this._root` if not provided explicitly.
|
|
635
665
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `override has` method
|
|
@@ -641,8 +671,8 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
641
671
|
* are matching nodes, it returns `true`, indicating that the tree contains the specified element.
|
|
642
672
|
* Otherwise, it returns `false`.
|
|
643
673
|
*/
|
|
644
|
-
has(
|
|
645
|
-
return this.getNodes(
|
|
674
|
+
has(keyNodeEntryRawOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
675
|
+
return this.getNodes(keyNodeEntryRawOrPredicate, true, startNode, iterationType).length > 0;
|
|
646
676
|
}
|
|
647
677
|
/**
|
|
648
678
|
* Time Complexity: O(1)
|
|
@@ -651,8 +681,9 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
651
681
|
* The `clear` function resets the root node and size of a data structure to empty.
|
|
652
682
|
*/
|
|
653
683
|
clear() {
|
|
654
|
-
this.
|
|
655
|
-
this.
|
|
684
|
+
this._clearNodes();
|
|
685
|
+
if (this._isMapMode)
|
|
686
|
+
this._clearValues();
|
|
656
687
|
}
|
|
657
688
|
/**
|
|
658
689
|
* Time Complexity: O(1)
|
|
@@ -672,17 +703,17 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
672
703
|
*
|
|
673
704
|
* The function checks if a binary tree is perfectly balanced by comparing its minimum height with
|
|
674
705
|
* its height.
|
|
675
|
-
* @param {
|
|
706
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter is the starting
|
|
676
707
|
* point for checking if the binary tree is perfectly balanced. It represents the root node of the
|
|
677
708
|
* binary tree or a specific node from which the balance check should begin.
|
|
678
709
|
* @returns The method `isPerfectlyBalanced` is returning a boolean value, which indicates whether
|
|
679
|
-
* the tree starting from the `
|
|
710
|
+
* the tree starting from the `startNode` node is perfectly balanced or not. The return value is
|
|
680
711
|
* determined by comparing the minimum height of the tree with the height of the tree. If the minimum
|
|
681
712
|
* height plus 1 is greater than or equal to the height of the tree, then it is considered perfectly
|
|
682
713
|
* balanced and
|
|
683
714
|
*/
|
|
684
|
-
isPerfectlyBalanced(
|
|
685
|
-
return this.getMinHeight(
|
|
715
|
+
isPerfectlyBalanced(startNode = this._root) {
|
|
716
|
+
return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);
|
|
686
717
|
}
|
|
687
718
|
/**
|
|
688
719
|
* Time Complexity: O(n)
|
|
@@ -690,7 +721,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
690
721
|
*
|
|
691
722
|
* The function `isBST` in TypeScript checks if a binary search tree is valid using either recursive
|
|
692
723
|
* or iterative methods.
|
|
693
|
-
* @param {
|
|
724
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `isBST`
|
|
694
725
|
* function represents the starting point for checking whether a binary search tree (BST) is valid.
|
|
695
726
|
* It can be a node in the BST or a reference to the root of the BST. If no specific node is
|
|
696
727
|
* provided, the function will default to
|
|
@@ -702,10 +733,10 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
702
733
|
* the tree satisfies the BST property, where for every node, all nodes in its left subtree have keys
|
|
703
734
|
* less than the node's key, and all nodes in its right subtree have keys greater than the node's
|
|
704
735
|
*/
|
|
705
|
-
isBST(
|
|
736
|
+
isBST(startNode = this._root, iterationType = this.iterationType) {
|
|
706
737
|
// TODO there is a bug
|
|
707
|
-
|
|
708
|
-
if (!
|
|
738
|
+
startNode = this.ensureNode(startNode);
|
|
739
|
+
if (!startNode)
|
|
709
740
|
return true;
|
|
710
741
|
if (iterationType === 'RECURSIVE') {
|
|
711
742
|
const dfs = (cur, min, max) => {
|
|
@@ -716,8 +747,8 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
716
747
|
return false;
|
|
717
748
|
return dfs(cur.left, min, numKey) && dfs(cur.right, numKey, max);
|
|
718
749
|
};
|
|
719
|
-
const isStandardBST = dfs(
|
|
720
|
-
const isInverseBST = dfs(
|
|
750
|
+
const isStandardBST = dfs(startNode, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
|
|
751
|
+
const isInverseBST = dfs(startNode, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER);
|
|
721
752
|
return isStandardBST || isInverseBST;
|
|
722
753
|
}
|
|
723
754
|
else {
|
|
@@ -725,7 +756,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
725
756
|
const stack = [];
|
|
726
757
|
let prev = checkMax ? Number.MAX_SAFE_INTEGER : Number.MIN_SAFE_INTEGER;
|
|
727
758
|
// @ts-ignore
|
|
728
|
-
let curr =
|
|
759
|
+
let curr = startNode;
|
|
729
760
|
while (this.isRealNode(curr) || stack.length > 0) {
|
|
730
761
|
while (this.isRealNode(curr)) {
|
|
731
762
|
stack.push(curr);
|
|
@@ -749,20 +780,20 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
749
780
|
* Space Complexity: O(1)
|
|
750
781
|
*
|
|
751
782
|
* The `getDepth` function calculates the depth between two nodes in a binary tree.
|
|
752
|
-
* @param {
|
|
783
|
+
* @param {BTNRep<K, V, NODE> | R} dist - The `dist` parameter in the `getDepth`
|
|
753
784
|
* function represents the node or entry in a binary tree map, or a reference to a node in the tree.
|
|
754
|
-
* It is the target node for which you want to calculate the depth from the `
|
|
755
|
-
* @param {
|
|
785
|
+
* It is the target node for which you want to calculate the depth from the `startNode` node.
|
|
786
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
756
787
|
* `getDepth` function represents the starting point from which you want to calculate the depth of a
|
|
757
788
|
* given node or entry in a binary tree. If no specific starting point is provided, the default value
|
|
758
|
-
* for `
|
|
789
|
+
* for `startNode` is set to the root of the binary
|
|
759
790
|
* @returns The `getDepth` method returns the depth of a given node `dist` relative to the
|
|
760
|
-
* `
|
|
791
|
+
* `startNode` node in a binary tree. If the `dist` node is not found in the path to the `startNode`
|
|
761
792
|
* node, it returns the depth of the `dist` node from the root of the tree.
|
|
762
793
|
*/
|
|
763
|
-
getDepth(dist,
|
|
794
|
+
getDepth(dist, startNode = this._root) {
|
|
764
795
|
let distEnsured = this.ensureNode(dist);
|
|
765
|
-
const beginRootEnsured = this.ensureNode(
|
|
796
|
+
const beginRootEnsured = this.ensureNode(startNode);
|
|
766
797
|
let depth = 0;
|
|
767
798
|
while (distEnsured?.parent) {
|
|
768
799
|
if (distEnsured === beginRootEnsured) {
|
|
@@ -779,7 +810,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
779
810
|
*
|
|
780
811
|
* The `getHeight` function calculates the maximum height of a binary tree using either a recursive
|
|
781
812
|
* or iterative approach in TypeScript.
|
|
782
|
-
* @param {
|
|
813
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter is the starting
|
|
783
814
|
* point from which the height of the binary tree will be calculated. It can be a node in the binary
|
|
784
815
|
* tree or a reference to the root of the tree. If not provided, it defaults to the root of the
|
|
785
816
|
* binary tree data structure.
|
|
@@ -790,9 +821,9 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
790
821
|
* root node. The height is calculated based on the maximum depth of the tree, considering either a
|
|
791
822
|
* recursive approach or an iterative approach depending on the `iterationType` parameter.
|
|
792
823
|
*/
|
|
793
|
-
getHeight(
|
|
794
|
-
|
|
795
|
-
if (!this.isRealNode(
|
|
824
|
+
getHeight(startNode = this._root, iterationType = this.iterationType) {
|
|
825
|
+
startNode = this.ensureNode(startNode);
|
|
826
|
+
if (!this.isRealNode(startNode))
|
|
796
827
|
return -1;
|
|
797
828
|
if (iterationType === 'RECURSIVE') {
|
|
798
829
|
const _getMaxHeight = (cur) => {
|
|
@@ -802,10 +833,10 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
802
833
|
const rightHeight = _getMaxHeight(cur.right);
|
|
803
834
|
return Math.max(leftHeight, rightHeight) + 1;
|
|
804
835
|
};
|
|
805
|
-
return _getMaxHeight(
|
|
836
|
+
return _getMaxHeight(startNode);
|
|
806
837
|
}
|
|
807
838
|
else {
|
|
808
|
-
const stack = [{ node:
|
|
839
|
+
const stack = [{ node: startNode, depth: 0 }];
|
|
809
840
|
let maxHeight = 0;
|
|
810
841
|
while (stack.length > 0) {
|
|
811
842
|
const { node, depth } = stack.pop();
|
|
@@ -824,7 +855,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
824
855
|
*
|
|
825
856
|
* The `getMinHeight` function calculates the minimum height of a binary tree using either a
|
|
826
857
|
* recursive or iterative approach in TypeScript.
|
|
827
|
-
* @param {
|
|
858
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
828
859
|
* `getMinHeight` function represents the starting node from which the minimum height of the binary
|
|
829
860
|
* tree will be calculated. It is either a node in the binary tree or a reference to the root of the
|
|
830
861
|
* tree. If not provided, the default value is the root
|
|
@@ -836,9 +867,9 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
836
867
|
* leaf node in the tree. The method uses either a recursive approach or an iterative approach (using
|
|
837
868
|
* a stack) based on the `iterationType` parameter.
|
|
838
869
|
*/
|
|
839
|
-
getMinHeight(
|
|
840
|
-
|
|
841
|
-
if (!
|
|
870
|
+
getMinHeight(startNode = this._root, iterationType = this.iterationType) {
|
|
871
|
+
startNode = this.ensureNode(startNode);
|
|
872
|
+
if (!startNode)
|
|
842
873
|
return -1;
|
|
843
874
|
if (iterationType === 'RECURSIVE') {
|
|
844
875
|
const _getMinHeight = (cur) => {
|
|
@@ -850,11 +881,11 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
850
881
|
const rightMinHeight = _getMinHeight(cur.right);
|
|
851
882
|
return Math.min(leftMinHeight, rightMinHeight) + 1;
|
|
852
883
|
};
|
|
853
|
-
return _getMinHeight(
|
|
884
|
+
return _getMinHeight(startNode);
|
|
854
885
|
}
|
|
855
886
|
else {
|
|
856
887
|
const stack = [];
|
|
857
|
-
let node =
|
|
888
|
+
let node = startNode, last = null;
|
|
858
889
|
const depths = new Map();
|
|
859
890
|
while (stack.length > 0 || node) {
|
|
860
891
|
if (this.isRealNode(node)) {
|
|
@@ -877,7 +908,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
877
908
|
node = node.right;
|
|
878
909
|
}
|
|
879
910
|
}
|
|
880
|
-
return depths.get(
|
|
911
|
+
return depths.get(startNode);
|
|
881
912
|
}
|
|
882
913
|
}
|
|
883
914
|
/**
|
|
@@ -890,7 +921,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
890
921
|
* the path to the root. It is expected to be a function that takes a node as an argument and returns
|
|
891
922
|
* a value based on that node. The return type of the callback function is determined by the generic
|
|
892
923
|
* type `C
|
|
893
|
-
* @param {
|
|
924
|
+
* @param {BTNRep<K, V, NODE> | R} beginNode - The `beginNode` parameter in the
|
|
894
925
|
* `getPathToRoot` function can be either a key, a node, an entry, or any other value of type `R`.
|
|
895
926
|
* @param [isReverse=true] - The `isReverse` parameter in the `getPathToRoot` function determines
|
|
896
927
|
* whether the resulting path from the given `beginNode` to the root should be in reverse order or
|
|
@@ -900,7 +931,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
900
931
|
* array is either in reverse order or in the original order based on the value of the `isReverse`
|
|
901
932
|
* parameter.
|
|
902
933
|
*/
|
|
903
|
-
getPathToRoot(callback = this.
|
|
934
|
+
getPathToRoot(callback = this._DEFAULT_NODE_CALLBACK, beginNode, isReverse = true) {
|
|
904
935
|
const result = [];
|
|
905
936
|
let beginNodeEnsured = this.ensureNode(beginNode);
|
|
906
937
|
if (!beginNodeEnsured)
|
|
@@ -921,8 +952,8 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
921
952
|
* tail-recursive iteration.
|
|
922
953
|
* @param {C} callback - The `callback` parameter is a function that will be called with the leftmost
|
|
923
954
|
* node of a binary tree or with `undefined` if the tree is empty. It is provided with a default
|
|
924
|
-
* value of `
|
|
925
|
-
* @param {
|
|
955
|
+
* value of `_DEFAULT_NODE_CALLBACK` if not specified.
|
|
956
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
926
957
|
* `getLeftMost` function represents the starting point for finding the leftmost node in a binary
|
|
927
958
|
* tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
|
|
928
959
|
* starting point is provided, the function will default
|
|
@@ -930,23 +961,23 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
930
961
|
* specifies the type of iteration to be used when traversing the binary tree nodes. It can have two
|
|
931
962
|
* possible values:
|
|
932
963
|
* @returns The `getLeftMost` function returns the result of the callback function `C` applied to the
|
|
933
|
-
* leftmost node in the binary tree starting from the `
|
|
934
|
-
* `NIL`, it returns the result of the callback function applied to `undefined`. If the `
|
|
964
|
+
* leftmost node in the binary tree starting from the `startNode` node. If the `startNode` node is
|
|
965
|
+
* `NIL`, it returns the result of the callback function applied to `undefined`. If the `startNode`
|
|
935
966
|
* node is not a real node, it returns the result of the callback
|
|
936
967
|
*/
|
|
937
|
-
getLeftMost(callback = this.
|
|
938
|
-
if (this.isNIL(
|
|
968
|
+
getLeftMost(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
|
|
969
|
+
if (this.isNIL(startNode))
|
|
939
970
|
return callback(undefined);
|
|
940
|
-
|
|
941
|
-
if (!this.isRealNode(
|
|
942
|
-
return callback(
|
|
971
|
+
startNode = this.ensureNode(startNode);
|
|
972
|
+
if (!this.isRealNode(startNode))
|
|
973
|
+
return callback(startNode);
|
|
943
974
|
if (iterationType === 'RECURSIVE') {
|
|
944
975
|
const dfs = (cur) => {
|
|
945
976
|
if (!this.isRealNode(cur.left))
|
|
946
977
|
return cur;
|
|
947
978
|
return dfs(cur.left);
|
|
948
979
|
};
|
|
949
|
-
return callback(dfs(
|
|
980
|
+
return callback(dfs(startNode));
|
|
950
981
|
}
|
|
951
982
|
else {
|
|
952
983
|
// Indirect implementation of iteration using tail recursion optimization
|
|
@@ -955,7 +986,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
955
986
|
return cur;
|
|
956
987
|
return dfs.cont(cur.left);
|
|
957
988
|
});
|
|
958
|
-
return callback(dfs(
|
|
989
|
+
return callback(dfs(startNode));
|
|
959
990
|
}
|
|
960
991
|
}
|
|
961
992
|
/**
|
|
@@ -965,10 +996,10 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
965
996
|
* The function `getRightMost` retrieves the rightmost node in a binary tree using either recursive
|
|
966
997
|
* or iterative traversal methods.
|
|
967
998
|
* @param {C} callback - The `callback` parameter is a function that will be called with the result
|
|
968
|
-
* of finding the rightmost node in a binary tree. It is of type `
|
|
999
|
+
* of finding the rightmost node in a binary tree. It is of type `NodeCallback<OptNodeOrNull<NODE>>`,
|
|
969
1000
|
* which means it is a callback function that can accept either an optional binary tree node or null
|
|
970
1001
|
* as
|
|
971
|
-
* @param {
|
|
1002
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
972
1003
|
* `getRightMost` function represents the starting point for finding the rightmost node in a binary
|
|
973
1004
|
* tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
|
|
974
1005
|
* starting point is provided, the function will default
|
|
@@ -980,20 +1011,20 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
980
1011
|
* the binary tree structure, determined based on the specified iteration type ('RECURSIVE' or
|
|
981
1012
|
* other).
|
|
982
1013
|
*/
|
|
983
|
-
getRightMost(callback = this.
|
|
984
|
-
if (this.isNIL(
|
|
1014
|
+
getRightMost(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
|
|
1015
|
+
if (this.isNIL(startNode))
|
|
985
1016
|
return callback(undefined);
|
|
986
1017
|
// TODO support get right most by passing key in
|
|
987
|
-
|
|
988
|
-
if (!
|
|
989
|
-
return callback(
|
|
1018
|
+
startNode = this.ensureNode(startNode);
|
|
1019
|
+
if (!startNode)
|
|
1020
|
+
return callback(startNode);
|
|
990
1021
|
if (iterationType === 'RECURSIVE') {
|
|
991
1022
|
const dfs = (cur) => {
|
|
992
1023
|
if (!this.isRealNode(cur.right))
|
|
993
1024
|
return cur;
|
|
994
1025
|
return dfs(cur.right);
|
|
995
1026
|
};
|
|
996
|
-
return callback(dfs(
|
|
1027
|
+
return callback(dfs(startNode));
|
|
997
1028
|
}
|
|
998
1029
|
else {
|
|
999
1030
|
// Indirect implementation of iteration using tail recursion optimization
|
|
@@ -1002,7 +1033,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1002
1033
|
return cur;
|
|
1003
1034
|
return dfs.cont(cur.right);
|
|
1004
1035
|
});
|
|
1005
|
-
return callback(dfs(
|
|
1036
|
+
return callback(dfs(startNode));
|
|
1006
1037
|
}
|
|
1007
1038
|
}
|
|
1008
1039
|
/**
|
|
@@ -1066,14 +1097,14 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1066
1097
|
* The function `dfs` performs a depth-first search traversal on a binary tree structure based on the
|
|
1067
1098
|
* specified parameters.
|
|
1068
1099
|
* @param {C} callback - The `callback` parameter is a generic type `C` that extends the
|
|
1069
|
-
* `
|
|
1070
|
-
* `this.
|
|
1100
|
+
* `NodeCallback` interface with a type parameter of `OptNodeOrNull<NODE>`. It has a default value of
|
|
1101
|
+
* `this._DEFAULT_NODE_CALLBACK as C`.
|
|
1071
1102
|
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `dfs` method specifies the
|
|
1072
1103
|
* order in which the Depth-First Search (DFS) algorithm should traverse the nodes in the tree. The
|
|
1073
1104
|
* possible values for the `pattern` parameter are:
|
|
1074
|
-
* @param {
|
|
1105
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `dfs`
|
|
1075
1106
|
* method is used to specify the starting point for the Depth-First Search traversal. It can be
|
|
1076
|
-
* either a `
|
|
1107
|
+
* either a `BTNRep` object representing a key, node, or entry in the binary tree map,
|
|
1077
1108
|
* or it can be a
|
|
1078
1109
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `dfs` method specifies
|
|
1079
1110
|
* the type of iteration to be performed during the depth-first search traversal. It is used to
|
|
@@ -1085,11 +1116,11 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1085
1116
|
* @returns The `dfs` method is returning an array of the return type specified by the generic type
|
|
1086
1117
|
* parameter `C`. The return type is determined by the callback function provided to the method.
|
|
1087
1118
|
*/
|
|
1088
|
-
dfs(callback = this.
|
|
1089
|
-
|
|
1090
|
-
if (!
|
|
1119
|
+
dfs(callback = this._DEFAULT_NODE_CALLBACK, pattern = 'IN', startNode = this._root, iterationType = this.iterationType, includeNull = false) {
|
|
1120
|
+
startNode = this.ensureNode(startNode);
|
|
1121
|
+
if (!startNode)
|
|
1091
1122
|
return [];
|
|
1092
|
-
return this._dfs(callback, pattern,
|
|
1123
|
+
return this._dfs(callback, pattern, startNode, iterationType, includeNull);
|
|
1093
1124
|
}
|
|
1094
1125
|
/**
|
|
1095
1126
|
* Time complexity: O(n)
|
|
@@ -1099,8 +1130,8 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1099
1130
|
* tree, executing a specified callback function on each node visited.
|
|
1100
1131
|
* @param {C} callback - The `callback` parameter in the `bfs` function is a function that will be
|
|
1101
1132
|
* called on each node visited during the breadth-first search traversal. It is a generic type `C`
|
|
1102
|
-
* that extends the `
|
|
1103
|
-
* @param {
|
|
1133
|
+
* that extends the `NodeCallback` type, which takes a parameter of type `NODE` or `null`.
|
|
1134
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `bfs`
|
|
1104
1135
|
* function represents the starting point for the breadth-first search traversal in a binary tree. It
|
|
1105
1136
|
* can be specified as a key, node, or entry in the binary tree structure. If not provided, the
|
|
1106
1137
|
* default value is the root node of the binary
|
|
@@ -1114,13 +1145,13 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1114
1145
|
* @returns The `bfs` function returns an array of values that are the result of applying the
|
|
1115
1146
|
* provided callback function to each node in the binary tree in a breadth-first search manner.
|
|
1116
1147
|
*/
|
|
1117
|
-
bfs(callback = this.
|
|
1118
|
-
|
|
1119
|
-
if (!
|
|
1148
|
+
bfs(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType, includeNull = false) {
|
|
1149
|
+
startNode = this.ensureNode(startNode);
|
|
1150
|
+
if (!startNode)
|
|
1120
1151
|
return [];
|
|
1121
1152
|
const ans = [];
|
|
1122
1153
|
if (iterationType === 'RECURSIVE') {
|
|
1123
|
-
const queue = new Queue([
|
|
1154
|
+
const queue = new Queue([startNode]);
|
|
1124
1155
|
const dfs = (level) => {
|
|
1125
1156
|
if (queue.size === 0)
|
|
1126
1157
|
return;
|
|
@@ -1143,7 +1174,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1143
1174
|
dfs(0);
|
|
1144
1175
|
}
|
|
1145
1176
|
else {
|
|
1146
|
-
const queue = new Queue([
|
|
1177
|
+
const queue = new Queue([startNode]);
|
|
1147
1178
|
while (queue.size > 0) {
|
|
1148
1179
|
const levelSize = queue.size;
|
|
1149
1180
|
for (let i = 0; i < levelSize; i++) {
|
|
@@ -1174,7 +1205,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1174
1205
|
* structure based on a specified callback and iteration type.
|
|
1175
1206
|
* @param {C} callback - The `callback` parameter is a function that will be called on each leaf node
|
|
1176
1207
|
* in the binary tree. It is optional and defaults to a default callback function if not provided.
|
|
1177
|
-
* @param {
|
|
1208
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `leaves`
|
|
1178
1209
|
* method is used to specify the starting point for finding and processing the leaves of a binary
|
|
1179
1210
|
* tree. It can be provided as either a key, a node, or an entry in the binary tree structure. If not
|
|
1180
1211
|
* explicitly provided, the default value
|
|
@@ -1184,10 +1215,10 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1184
1215
|
* @returns The `leaves` method returns an array of values that are the result of applying the
|
|
1185
1216
|
* provided callback function to each leaf node in the binary tree.
|
|
1186
1217
|
*/
|
|
1187
|
-
leaves(callback = this.
|
|
1188
|
-
|
|
1218
|
+
leaves(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
|
|
1219
|
+
startNode = this.ensureNode(startNode);
|
|
1189
1220
|
const leaves = [];
|
|
1190
|
-
if (!this.isRealNode(
|
|
1221
|
+
if (!this.isRealNode(startNode))
|
|
1191
1222
|
return [];
|
|
1192
1223
|
if (iterationType === 'RECURSIVE') {
|
|
1193
1224
|
const dfs = (cur) => {
|
|
@@ -1201,10 +1232,10 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1201
1232
|
if (this.isRealNode(cur.right))
|
|
1202
1233
|
dfs(cur.right);
|
|
1203
1234
|
};
|
|
1204
|
-
dfs(
|
|
1235
|
+
dfs(startNode);
|
|
1205
1236
|
}
|
|
1206
1237
|
else {
|
|
1207
|
-
const queue = new Queue([
|
|
1238
|
+
const queue = new Queue([startNode]);
|
|
1208
1239
|
while (queue.size > 0) {
|
|
1209
1240
|
const cur = queue.shift();
|
|
1210
1241
|
if (this.isRealNode(cur)) {
|
|
@@ -1229,7 +1260,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1229
1260
|
* @param {C} callback - The `callback` parameter is a function that will be applied to each node in
|
|
1230
1261
|
* the binary tree during the traversal. It is used to process each node and determine what
|
|
1231
1262
|
* information to include in the output for each level of the tree.
|
|
1232
|
-
* @param {
|
|
1263
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
1233
1264
|
* `listLevels` function represents the starting point for traversing the binary tree. It can be
|
|
1234
1265
|
* either a key, a node, or an entry in the binary tree. If not provided, the default value is the
|
|
1235
1266
|
* root of the binary tree.
|
|
@@ -1244,10 +1275,10 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1244
1275
|
* level in a binary tree. Each inner array contains the return value of the provided callback
|
|
1245
1276
|
* function applied to the nodes at that level.
|
|
1246
1277
|
*/
|
|
1247
|
-
listLevels(callback = this.
|
|
1248
|
-
|
|
1278
|
+
listLevels(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType, includeNull = false) {
|
|
1279
|
+
startNode = this.ensureNode(startNode);
|
|
1249
1280
|
const levelsNodes = [];
|
|
1250
|
-
if (!
|
|
1281
|
+
if (!startNode)
|
|
1251
1282
|
return levelsNodes;
|
|
1252
1283
|
if (iterationType === 'RECURSIVE') {
|
|
1253
1284
|
const _recursive = (node, level) => {
|
|
@@ -1267,10 +1298,10 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1267
1298
|
_recursive(node.right, level + 1);
|
|
1268
1299
|
}
|
|
1269
1300
|
};
|
|
1270
|
-
_recursive(
|
|
1301
|
+
_recursive(startNode, 0);
|
|
1271
1302
|
}
|
|
1272
1303
|
else {
|
|
1273
|
-
const stack = [[
|
|
1304
|
+
const stack = [[startNode, 0]];
|
|
1274
1305
|
while (stack.length > 0) {
|
|
1275
1306
|
const head = stack.pop();
|
|
1276
1307
|
const [node, level] = head;
|
|
@@ -1301,11 +1332,11 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1301
1332
|
* Morris Traversal algorithm with different order patterns.
|
|
1302
1333
|
* @param {C} callback - The `callback` parameter in the `morris` function is a function that will be
|
|
1303
1334
|
* called on each node in the binary tree during the traversal. It is of type `C`, which extends the
|
|
1304
|
-
* `
|
|
1335
|
+
* `NodeCallback<NODE>` type. The default value for `callback` is `this._DEFAULT
|
|
1305
1336
|
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `morris` function specifies
|
|
1306
1337
|
* the type of Depth-First Search (DFS) order pattern to traverse the binary tree. The possible
|
|
1307
1338
|
* values for the `pattern` parameter are:
|
|
1308
|
-
* @param {
|
|
1339
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `morris`
|
|
1309
1340
|
* function is the starting point for the Morris traversal algorithm. It represents the root node of
|
|
1310
1341
|
* the binary tree or the node from which the traversal should begin. It can be provided as either a
|
|
1311
1342
|
* key, a node, an entry, or a reference
|
|
@@ -1313,12 +1344,12 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1313
1344
|
* provided callback function to each node in the binary tree in the specified order pattern (IN,
|
|
1314
1345
|
* PRE, or POST).
|
|
1315
1346
|
*/
|
|
1316
|
-
morris(callback = this.
|
|
1317
|
-
|
|
1318
|
-
if (!
|
|
1347
|
+
morris(callback = this._DEFAULT_NODE_CALLBACK, pattern = 'IN', startNode = this._root) {
|
|
1348
|
+
startNode = this.ensureNode(startNode);
|
|
1349
|
+
if (!startNode)
|
|
1319
1350
|
return [];
|
|
1320
1351
|
const ans = [];
|
|
1321
|
-
let cur =
|
|
1352
|
+
let cur = startNode;
|
|
1322
1353
|
const _reverseEdge = (node) => {
|
|
1323
1354
|
let pre = null;
|
|
1324
1355
|
let next = null;
|
|
@@ -1393,7 +1424,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1393
1424
|
}
|
|
1394
1425
|
cur = cur.right;
|
|
1395
1426
|
}
|
|
1396
|
-
_printEdge(
|
|
1427
|
+
_printEdge(startNode);
|
|
1397
1428
|
break;
|
|
1398
1429
|
}
|
|
1399
1430
|
return ans;
|
|
@@ -1414,9 +1445,15 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1414
1445
|
this.bfs(node => {
|
|
1415
1446
|
if (node === null)
|
|
1416
1447
|
cloned.add(null);
|
|
1417
|
-
else
|
|
1418
|
-
|
|
1448
|
+
else {
|
|
1449
|
+
if (this._isMapMode)
|
|
1450
|
+
cloned.add([node.key, this._store.get(node.key)]);
|
|
1451
|
+
else
|
|
1452
|
+
cloned.add([node.key, node.value]);
|
|
1453
|
+
}
|
|
1419
1454
|
}, this._root, this.iterationType, true);
|
|
1455
|
+
if (this._isMapMode)
|
|
1456
|
+
cloned._store = this._store;
|
|
1420
1457
|
return cloned;
|
|
1421
1458
|
}
|
|
1422
1459
|
/**
|
|
@@ -1483,7 +1520,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1483
1520
|
*
|
|
1484
1521
|
* The function `toVisual` in TypeScript overrides the visual representation of a binary tree with
|
|
1485
1522
|
* customizable options for displaying undefined, null, and sentinel nodes.
|
|
1486
|
-
* @param {
|
|
1523
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
1487
1524
|
* `toVisual` method is used to specify the starting point for visualizing the binary tree structure.
|
|
1488
1525
|
* It can be a node, key, entry, or the root of the tree. If no specific starting point is provided,
|
|
1489
1526
|
* the default is set to the root
|
|
@@ -1495,21 +1532,18 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1495
1532
|
* the lines to the output string. The final output string contains the visual representation of the
|
|
1496
1533
|
* binary tree with the specified options.
|
|
1497
1534
|
*/
|
|
1498
|
-
toVisual(
|
|
1499
|
-
const opts = { isShowUndefined: false, isShowNull:
|
|
1500
|
-
|
|
1535
|
+
toVisual(startNode = this._root, options) {
|
|
1536
|
+
const opts = { isShowUndefined: false, isShowNull: true, isShowRedBlackNIL: false, ...options };
|
|
1537
|
+
startNode = this.ensureNode(startNode);
|
|
1501
1538
|
let output = '';
|
|
1502
|
-
if (!
|
|
1539
|
+
if (!startNode)
|
|
1503
1540
|
return output;
|
|
1504
1541
|
if (opts.isShowUndefined)
|
|
1505
|
-
output += `U for undefined
|
|
1506
|
-
`;
|
|
1542
|
+
output += `U for undefined\n`;
|
|
1507
1543
|
if (opts.isShowNull)
|
|
1508
|
-
output += `N for null
|
|
1509
|
-
`;
|
|
1544
|
+
output += `N for null\n`;
|
|
1510
1545
|
if (opts.isShowRedBlackNIL)
|
|
1511
|
-
output += `S for Sentinel Node(NIL)
|
|
1512
|
-
`;
|
|
1546
|
+
output += `S for Sentinel Node(NIL)\n`;
|
|
1513
1547
|
const display = (root) => {
|
|
1514
1548
|
const [lines, , ,] = this._displayAux(root, opts);
|
|
1515
1549
|
let paragraph = '';
|
|
@@ -1518,9 +1552,27 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1518
1552
|
}
|
|
1519
1553
|
output += paragraph;
|
|
1520
1554
|
};
|
|
1521
|
-
display(
|
|
1555
|
+
display(startNode);
|
|
1522
1556
|
return output;
|
|
1523
1557
|
}
|
|
1558
|
+
/**
|
|
1559
|
+
* Time Complexity: O(n)
|
|
1560
|
+
* Space Complexity: O(n)
|
|
1561
|
+
*
|
|
1562
|
+
* The function `print` in TypeScript overrides the default print behavior to log a visual
|
|
1563
|
+
* representation of the binary tree to the console.
|
|
1564
|
+
* @param {BinaryTreePrintOptions} [options] - The `options` parameter is used to specify the
|
|
1565
|
+
* printing options for the binary tree. It is an optional parameter that allows you to customize how
|
|
1566
|
+
* the binary tree is printed, such as choosing between different traversal orders or formatting
|
|
1567
|
+
* options.
|
|
1568
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
1569
|
+
* `override print` method is used to specify the starting point for printing the binary tree. It can
|
|
1570
|
+
* be either a key, a node, an entry, or the root of the tree. If no specific starting point is
|
|
1571
|
+
* provided, the default value is set to
|
|
1572
|
+
*/
|
|
1573
|
+
print(options, startNode = this._root) {
|
|
1574
|
+
console.log(this.toVisual(startNode, options));
|
|
1575
|
+
}
|
|
1524
1576
|
/**
|
|
1525
1577
|
* Time complexity: O(n)
|
|
1526
1578
|
* Space complexity: O(n)
|
|
@@ -1529,13 +1581,13 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1529
1581
|
* the specified order pattern and callback function.
|
|
1530
1582
|
* @param {C} callback - The `callback` parameter in the `_dfs` method is a function that will be
|
|
1531
1583
|
* called on each node visited during the depth-first search traversal. It is of type `C`, which
|
|
1532
|
-
* extends `
|
|
1584
|
+
* extends `NodeCallback<OptNodeOrNull<NODE>>`. The default value for this parameter is `this._DEFAULT
|
|
1533
1585
|
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `_dfs` method specifies the
|
|
1534
1586
|
* order in which the nodes are visited during the Depth-First Search traversal. It can have one of
|
|
1535
1587
|
* the following values:
|
|
1536
|
-
* @param {
|
|
1588
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `_dfs`
|
|
1537
1589
|
* method is used to specify the starting point for the depth-first search traversal in a binary
|
|
1538
|
-
* tree. It can be provided as either a `
|
|
1590
|
+
* tree. It can be provided as either a `BTNRep` object or a reference to the root node
|
|
1539
1591
|
* of the tree. If no specific
|
|
1540
1592
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `_dfs` method
|
|
1541
1593
|
* specifies the type of iteration to be performed during the Depth-First Search (DFS) traversal of a
|
|
@@ -1563,13 +1615,13 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1563
1615
|
* @returns The function `_dfs` returns an array of the return type of the callback function provided
|
|
1564
1616
|
* as input.
|
|
1565
1617
|
*/
|
|
1566
|
-
_dfs(callback = this.
|
|
1618
|
+
_dfs(callback = this._DEFAULT_NODE_CALLBACK, pattern = 'IN', startNode = this._root, iterationType = this.iterationType, includeNull = false, shouldVisitLeft = node => !!node, shouldVisitRight = node => !!node, shouldVisitRoot = node => {
|
|
1567
1619
|
if (includeNull)
|
|
1568
1620
|
return this.isRealNodeOrNull(node);
|
|
1569
1621
|
return this.isRealNode(node);
|
|
1570
1622
|
}, shouldProcessRoot = node => this.isRealNodeOrNull(node)) {
|
|
1571
|
-
|
|
1572
|
-
if (!
|
|
1623
|
+
startNode = this.ensureNode(startNode);
|
|
1624
|
+
if (!startNode)
|
|
1573
1625
|
return [];
|
|
1574
1626
|
const ans = [];
|
|
1575
1627
|
if (iterationType === 'RECURSIVE') {
|
|
@@ -1605,10 +1657,10 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1605
1657
|
break;
|
|
1606
1658
|
}
|
|
1607
1659
|
};
|
|
1608
|
-
dfs(
|
|
1660
|
+
dfs(startNode);
|
|
1609
1661
|
}
|
|
1610
1662
|
else {
|
|
1611
|
-
const stack = [{ opt: DFSOperation.VISIT, node:
|
|
1663
|
+
const stack = [{ opt: DFSOperation.VISIT, node: startNode }];
|
|
1612
1664
|
const pushLeft = (cur) => {
|
|
1613
1665
|
if (shouldVisitLeft(cur.node))
|
|
1614
1666
|
stack.push({ opt: DFSOperation.VISIT, node: cur.node?.left });
|
|
@@ -1682,7 +1734,10 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1682
1734
|
}
|
|
1683
1735
|
current = stack.pop();
|
|
1684
1736
|
if (this.isRealNode(current)) {
|
|
1685
|
-
|
|
1737
|
+
if (this._isMapMode)
|
|
1738
|
+
yield [current.key, this._store.get(current.key)];
|
|
1739
|
+
else
|
|
1740
|
+
yield [current.key, current.value];
|
|
1686
1741
|
current = current.right;
|
|
1687
1742
|
}
|
|
1688
1743
|
}
|
|
@@ -1691,7 +1746,10 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1691
1746
|
if (node.left && this.isRealNode(node)) {
|
|
1692
1747
|
yield* this[Symbol.iterator](node.left);
|
|
1693
1748
|
}
|
|
1694
|
-
|
|
1749
|
+
if (this._isMapMode)
|
|
1750
|
+
yield [node.key, this._store.get(node.key)];
|
|
1751
|
+
else
|
|
1752
|
+
yield [node.key, node.value];
|
|
1695
1753
|
if (node.right && this.isRealNode(node)) {
|
|
1696
1754
|
yield* this[Symbol.iterator](node.right);
|
|
1697
1755
|
}
|
|
@@ -1764,18 +1822,18 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1764
1822
|
];
|
|
1765
1823
|
}
|
|
1766
1824
|
}
|
|
1767
|
-
|
|
1825
|
+
_DEFAULT_NODE_CALLBACK = (node) => (node ? node.key : undefined);
|
|
1768
1826
|
/**
|
|
1769
1827
|
* Time Complexity: O(1)
|
|
1770
1828
|
* Space Complexity: O(1)
|
|
1771
1829
|
*
|
|
1772
1830
|
* The _swapProperties function swaps key and value properties between two nodes in a binary tree.
|
|
1773
|
-
* @param {
|
|
1774
|
-
* `_swapProperties` method can be either a
|
|
1831
|
+
* @param {BTNRep<K, V, NODE> | R} srcNode - The `srcNode` parameter in the
|
|
1832
|
+
* `_swapProperties` method can be either a BTNRep object containing key and value
|
|
1775
1833
|
* properties, or it can be of type R.
|
|
1776
|
-
* @param {
|
|
1834
|
+
* @param {BTNRep<K, V, NODE> | R} destNode - The `destNode` parameter in the
|
|
1777
1835
|
* `_swapProperties` method represents the node or entry where the properties will be swapped with
|
|
1778
|
-
* the `srcNode`. It can be of type `
|
|
1836
|
+
* the `srcNode`. It can be of type `BTNRep<K, V, NODE>` or `R`. The method ensures that
|
|
1779
1837
|
* both `srcNode
|
|
1780
1838
|
* @returns The `_swapProperties` method returns either the `destNode` with its key and value swapped
|
|
1781
1839
|
* with the `srcNode`, or `undefined` if either `srcNode` or `destNode` is falsy.
|
|
@@ -1788,9 +1846,11 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1788
1846
|
const tempNode = this.createNode(key, value);
|
|
1789
1847
|
if (tempNode) {
|
|
1790
1848
|
destNode.key = srcNode.key;
|
|
1791
|
-
|
|
1849
|
+
if (!this._isMapMode)
|
|
1850
|
+
destNode.value = srcNode.value;
|
|
1792
1851
|
srcNode.key = tempNode.key;
|
|
1793
|
-
|
|
1852
|
+
if (!this._isMapMode)
|
|
1853
|
+
srcNode.value = tempNode.value;
|
|
1794
1854
|
}
|
|
1795
1855
|
return destNode;
|
|
1796
1856
|
}
|
|
@@ -1833,7 +1893,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1833
1893
|
*
|
|
1834
1894
|
* The function _setRoot sets the root node of a data structure while updating the parent reference
|
|
1835
1895
|
* of the previous root node.
|
|
1836
|
-
* @param v - The parameter `v` in the `_setRoot` method is of type `
|
|
1896
|
+
* @param v - The parameter `v` in the `_setRoot` method is of type `OptNodeOrNull<NODE>`, which means
|
|
1837
1897
|
* it can either be an optional `NODE` type or `null`.
|
|
1838
1898
|
*/
|
|
1839
1899
|
_setRoot(v) {
|
|
@@ -1848,44 +1908,111 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1848
1908
|
*
|
|
1849
1909
|
* The function `_ensurePredicate` in TypeScript ensures that the input is converted into a valid
|
|
1850
1910
|
* predicate function for a binary tree node.
|
|
1851
|
-
* @param {
|
|
1911
|
+
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate - The
|
|
1852
1912
|
* `_ensurePredicate` method in the provided code snippet is responsible for ensuring that the input
|
|
1853
|
-
* parameter `
|
|
1913
|
+
* parameter `keyNodeEntryRawOrPredicate` is transformed into a valid predicate function that can be
|
|
1854
1914
|
* used for filtering nodes in a binary tree.
|
|
1855
|
-
* @returns A
|
|
1915
|
+
* @returns A NodePredicate<NODE> function is being returned.
|
|
1856
1916
|
*/
|
|
1857
|
-
_ensurePredicate(
|
|
1858
|
-
if (
|
|
1917
|
+
_ensurePredicate(keyNodeEntryRawOrPredicate) {
|
|
1918
|
+
if (keyNodeEntryRawOrPredicate === null || keyNodeEntryRawOrPredicate === undefined)
|
|
1859
1919
|
return (node) => (node ? false : false);
|
|
1860
|
-
if (this.
|
|
1861
|
-
return
|
|
1862
|
-
if (this.isRealNode(
|
|
1863
|
-
return (node) => node ===
|
|
1864
|
-
if (this.isEntry(
|
|
1865
|
-
const [key] =
|
|
1920
|
+
if (this._isPredicate(keyNodeEntryRawOrPredicate))
|
|
1921
|
+
return keyNodeEntryRawOrPredicate;
|
|
1922
|
+
if (this.isRealNode(keyNodeEntryRawOrPredicate))
|
|
1923
|
+
return (node) => node === keyNodeEntryRawOrPredicate;
|
|
1924
|
+
if (this.isEntry(keyNodeEntryRawOrPredicate)) {
|
|
1925
|
+
const [key] = keyNodeEntryRawOrPredicate;
|
|
1866
1926
|
return (node) => node.key === key;
|
|
1867
1927
|
}
|
|
1868
|
-
if (this.isKey(
|
|
1869
|
-
return (node) => node.key ===
|
|
1928
|
+
if (this.isKey(keyNodeEntryRawOrPredicate))
|
|
1929
|
+
return (node) => node.key === keyNodeEntryRawOrPredicate;
|
|
1870
1930
|
if (this._toEntryFn) {
|
|
1871
|
-
const [key] = this._toEntryFn(
|
|
1931
|
+
const [key] = this._toEntryFn(keyNodeEntryRawOrPredicate);
|
|
1872
1932
|
return (node) => node.key === key;
|
|
1873
1933
|
}
|
|
1874
|
-
return (node) => node.key ===
|
|
1934
|
+
return (node) => node.key === keyNodeEntryRawOrPredicate;
|
|
1875
1935
|
}
|
|
1876
1936
|
/**
|
|
1877
1937
|
* Time Complexity: O(1)
|
|
1878
1938
|
* Space Complexity: O(1)
|
|
1879
1939
|
*
|
|
1880
|
-
* The function `
|
|
1940
|
+
* The function `_isPredicate` checks if a given parameter is a function.
|
|
1881
1941
|
* @param {any} p - The parameter `p` is a variable of type `any`, which means it can hold any type
|
|
1882
|
-
* of value. In this context, the function `
|
|
1883
|
-
* satisfies the type `
|
|
1942
|
+
* of value. In this context, the function `_isPredicate` is checking if `p` is a function that
|
|
1943
|
+
* satisfies the type `NodePredicate<NODE>`.
|
|
1884
1944
|
* @returns The function is checking if the input `p` is a function and returning a boolean value
|
|
1885
1945
|
* based on that check. If `p` is a function, it will return `true`, indicating that `p` is a
|
|
1886
1946
|
* predicate function for a binary tree node. If `p` is not a function, it will return `false`.
|
|
1887
1947
|
*/
|
|
1888
|
-
|
|
1948
|
+
_isPredicate(p) {
|
|
1889
1949
|
return typeof p === 'function';
|
|
1890
1950
|
}
|
|
1951
|
+
/**
|
|
1952
|
+
* Time Complexity: O(1)
|
|
1953
|
+
* Space Complexity: O(1)
|
|
1954
|
+
*
|
|
1955
|
+
* The function `_getKey` in TypeScript returns the key from a given input, which can be a node,
|
|
1956
|
+
* entry, raw data, or null/undefined.
|
|
1957
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The `_getKey` method you provided is a
|
|
1958
|
+
* TypeScript method that takes in a parameter `keyNodeEntryOrRaw` of type `BTNRep<K, V, NODE> | R`,
|
|
1959
|
+
* where `BTNRep` is a generic type with keys `K`, `V`, and `NODE`, and `
|
|
1960
|
+
* @returns The `_getKey` method returns the key value extracted from the `keyNodeEntryOrRaw`
|
|
1961
|
+
* parameter. The return value can be a key value of type `K`, `null`, or `undefined`, depending on
|
|
1962
|
+
* the conditions checked in the method.
|
|
1963
|
+
*/
|
|
1964
|
+
_getKey(keyNodeEntryOrRaw) {
|
|
1965
|
+
if (keyNodeEntryOrRaw === null)
|
|
1966
|
+
return null;
|
|
1967
|
+
if (keyNodeEntryOrRaw === undefined)
|
|
1968
|
+
return;
|
|
1969
|
+
if (keyNodeEntryOrRaw === this._NIL)
|
|
1970
|
+
return;
|
|
1971
|
+
if (this.isNode(keyNodeEntryOrRaw))
|
|
1972
|
+
return keyNodeEntryOrRaw.key;
|
|
1973
|
+
if (this.isEntry(keyNodeEntryOrRaw))
|
|
1974
|
+
return keyNodeEntryOrRaw[0];
|
|
1975
|
+
if (this.isRaw(keyNodeEntryOrRaw)) {
|
|
1976
|
+
if (this._toEntryFn) {
|
|
1977
|
+
const [key] = this._toEntryFn(keyNodeEntryOrRaw);
|
|
1978
|
+
return key;
|
|
1979
|
+
}
|
|
1980
|
+
return;
|
|
1981
|
+
}
|
|
1982
|
+
return keyNodeEntryOrRaw;
|
|
1983
|
+
}
|
|
1984
|
+
/**
|
|
1985
|
+
* Time Complexity: O(1)
|
|
1986
|
+
* Space Complexity: O(1)
|
|
1987
|
+
*
|
|
1988
|
+
* The function `_setValue` sets a value in a store based on a key, handling cases where the key or
|
|
1989
|
+
* value is null or undefined.
|
|
1990
|
+
* @param {K | null | undefined} key - The `key` parameter can be of type `K`, `null`, or
|
|
1991
|
+
* `undefined`.
|
|
1992
|
+
* @param {V | undefined} value - The `value` parameter in the `_setValue` method can be of type `V`
|
|
1993
|
+
* or `undefined`.
|
|
1994
|
+
* @returns The method `_setValue` returns `false` if either the `key` is `null` or `undefined`, or
|
|
1995
|
+
* if the `value` is `undefined`. Otherwise, it returns the result of calling the `set` method on the
|
|
1996
|
+
* `_store` object with the `key` and `value` arguments.
|
|
1997
|
+
*/
|
|
1998
|
+
_setValue(key, value) {
|
|
1999
|
+
if (key === null || key === undefined)
|
|
2000
|
+
return false;
|
|
2001
|
+
if (value === undefined)
|
|
2002
|
+
return false;
|
|
2003
|
+
return this._store.set(key, value);
|
|
2004
|
+
}
|
|
2005
|
+
/**
|
|
2006
|
+
* The _clearNodes function sets the root node to undefined and resets the size to 0.
|
|
2007
|
+
*/
|
|
2008
|
+
_clearNodes() {
|
|
2009
|
+
this._setRoot(undefined);
|
|
2010
|
+
this._size = 0;
|
|
2011
|
+
}
|
|
2012
|
+
/**
|
|
2013
|
+
* The _clearValues function clears all values stored in the _store object.
|
|
2014
|
+
*/
|
|
2015
|
+
_clearValues() {
|
|
2016
|
+
this._store.clear();
|
|
2017
|
+
}
|
|
1891
2018
|
}
|