min-heap-typed 1.42.6 → 1.42.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data-structures/binary-tree/avl-tree.d.ts +5 -5
- package/dist/data-structures/binary-tree/avl-tree.js +19 -14
- package/dist/data-structures/binary-tree/binary-tree.d.ts +108 -60
- package/dist/data-structures/binary-tree/binary-tree.js +189 -89
- package/dist/data-structures/binary-tree/bst.d.ts +30 -8
- package/dist/data-structures/binary-tree/bst.js +77 -28
- package/dist/data-structures/binary-tree/rb-tree.d.ts +35 -28
- package/dist/data-structures/binary-tree/rb-tree.js +44 -45
- package/dist/data-structures/binary-tree/tree-multimap.d.ts +7 -12
- package/dist/data-structures/binary-tree/tree-multimap.js +38 -37
- package/dist/interfaces/binary-tree.d.ts +2 -2
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/binary-tree.js +6 -0
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +2 -2
- package/package.json +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +24 -18
- package/src/data-structures/binary-tree/binary-tree.ts +248 -142
- package/src/data-structures/binary-tree/bst.ts +88 -38
- package/src/data-structures/binary-tree/rb-tree.ts +52 -58
- package/src/data-structures/binary-tree/tree-multimap.ts +50 -54
- package/src/interfaces/binary-tree.ts +2 -2
- package/src/types/data-structures/binary-tree/binary-tree.ts +7 -1
- package/src/types/data-structures/binary-tree/rb-tree.ts +2 -2
|
@@ -88,13 +88,12 @@ class BinaryTree {
|
|
|
88
88
|
*/
|
|
89
89
|
constructor(options) {
|
|
90
90
|
this.iterationType = types_1.IterationType.ITERATIVE;
|
|
91
|
-
this.
|
|
92
|
-
|
|
93
|
-
this.defaultOneParamCallback = (node) => node.key;
|
|
94
|
-
if (options !== undefined) {
|
|
91
|
+
this._defaultOneParamCallback = (node) => node.key;
|
|
92
|
+
if (options) {
|
|
95
93
|
const { iterationType = types_1.IterationType.ITERATIVE } = options;
|
|
96
94
|
this.iterationType = iterationType;
|
|
97
95
|
}
|
|
96
|
+
this._size = 0;
|
|
98
97
|
}
|
|
99
98
|
/**
|
|
100
99
|
* Get the root node of the binary tree.
|
|
@@ -117,20 +116,6 @@ class BinaryTree {
|
|
|
117
116
|
createNode(key, value) {
|
|
118
117
|
return new BinaryTreeNode(key, value);
|
|
119
118
|
}
|
|
120
|
-
/**
|
|
121
|
-
* Clear the binary tree, removing all nodes.
|
|
122
|
-
*/
|
|
123
|
-
clear() {
|
|
124
|
-
this._setRoot(undefined);
|
|
125
|
-
this._size = 0;
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Check if the binary tree is empty.
|
|
129
|
-
* @returns {boolean} - True if the binary tree is empty, false otherwise.
|
|
130
|
-
*/
|
|
131
|
-
isEmpty() {
|
|
132
|
-
return this.size === 0;
|
|
133
|
-
}
|
|
134
119
|
/**
|
|
135
120
|
* Add a node with the given key and value to the binary tree.
|
|
136
121
|
* @param {BTNKey | N | null} keyOrNode - The key or node to add to the binary tree.
|
|
@@ -164,7 +149,7 @@ class BinaryTree {
|
|
|
164
149
|
if (keyOrNode === null) {
|
|
165
150
|
needInsert = null;
|
|
166
151
|
}
|
|
167
|
-
else if (
|
|
152
|
+
else if (this.isNodeKey(keyOrNode)) {
|
|
168
153
|
needInsert = this.createNode(keyOrNode, value);
|
|
169
154
|
}
|
|
170
155
|
else if (keyOrNode instanceof BinaryTreeNode) {
|
|
@@ -173,19 +158,12 @@ class BinaryTree {
|
|
|
173
158
|
else {
|
|
174
159
|
return;
|
|
175
160
|
}
|
|
176
|
-
// const key = typeof keyOrNode === 'number' ? keyOrNode : keyOrNode ? keyOrNode.key : undefined;
|
|
177
|
-
// const existNode = key !== undefined ? this.getNode(key, (node: N) => node.key) : undefined;
|
|
178
161
|
if (this.root) {
|
|
179
|
-
// if (existNode) {
|
|
180
|
-
// existNode.value = value;
|
|
181
|
-
// inserted = existNode;
|
|
182
|
-
// } else {
|
|
183
162
|
inserted = _bfs(this.root, needInsert);
|
|
184
|
-
// }
|
|
185
163
|
}
|
|
186
164
|
else {
|
|
187
165
|
this._setRoot(needInsert);
|
|
188
|
-
if (needInsert
|
|
166
|
+
if (needInsert) {
|
|
189
167
|
this._size = 1;
|
|
190
168
|
}
|
|
191
169
|
else {
|
|
@@ -222,40 +200,41 @@ class BinaryTree {
|
|
|
222
200
|
* The `refill` function clears the binary tree and adds multiple nodes with the given IDs or nodes and optional data.
|
|
223
201
|
* @param {(BTNKey | N)[]} keysOrNodes - The `keysOrNodes` parameter is an array that can contain either
|
|
224
202
|
* `BTNKey` or `N` values.
|
|
225
|
-
* @param {N[] | Array<V>} [
|
|
203
|
+
* @param {N[] | Array<V>} [values] - The `data` parameter is an optional array of values that will be assigned to
|
|
226
204
|
* the nodes being added. If provided, the length of the `data` array should be equal to the length of the `keysOrNodes`
|
|
227
205
|
* array. Each value in the `data` array will be assigned to the
|
|
228
206
|
* @returns The method is returning a boolean value.
|
|
229
207
|
*/
|
|
230
|
-
refill(keysOrNodes,
|
|
208
|
+
refill(keysOrNodes, values) {
|
|
231
209
|
this.clear();
|
|
232
|
-
return keysOrNodes.length === this.addMany(keysOrNodes,
|
|
210
|
+
return keysOrNodes.length === this.addMany(keysOrNodes, values).length;
|
|
233
211
|
}
|
|
234
212
|
/**
|
|
235
213
|
* The `delete` function removes a node from a binary search tree and returns the deleted node along
|
|
236
214
|
* with the parent node that needs to be balanced.
|
|
237
215
|
* a key (`BTNKey`). If it is a key, the function will find the corresponding node in the
|
|
238
216
|
* binary tree.
|
|
239
|
-
* @returns an array of `
|
|
217
|
+
* @returns an array of `BiTreeDeleteResult<N>` objects.
|
|
240
218
|
* @param {ReturnType<C>} identifier - The `identifier` parameter is either a
|
|
241
219
|
* `BTNKey` or a generic type `N`. It represents the property of the node that we are
|
|
242
220
|
* searching for. It can be a specific key value or any other property of the node.
|
|
243
221
|
* @param callback - The `callback` parameter is a function that takes a node as input and returns a
|
|
244
222
|
* value. This value is compared with the `identifier` parameter to determine if the node should be
|
|
245
223
|
* included in the result. The `callback` parameter has a default value of
|
|
246
|
-
* `this.
|
|
224
|
+
* `this._defaultOneParamCallback`, which
|
|
247
225
|
*/
|
|
248
|
-
delete(identifier, callback = this.
|
|
249
|
-
const
|
|
226
|
+
delete(identifier, callback = this._defaultOneParamCallback) {
|
|
227
|
+
const deletedResult = [];
|
|
250
228
|
if (!this.root)
|
|
251
|
-
return
|
|
229
|
+
return deletedResult;
|
|
252
230
|
if (identifier instanceof BinaryTreeNode)
|
|
253
231
|
callback = (node => node);
|
|
254
232
|
const curr = this.getNode(identifier, callback);
|
|
255
233
|
if (!curr)
|
|
256
|
-
return
|
|
234
|
+
return deletedResult;
|
|
257
235
|
const parent = (curr === null || curr === void 0 ? void 0 : curr.parent) ? curr.parent : null;
|
|
258
|
-
let needBalanced =
|
|
236
|
+
let needBalanced = undefined;
|
|
237
|
+
let orgCurrent = curr;
|
|
259
238
|
if (!curr.left) {
|
|
260
239
|
if (!parent) {
|
|
261
240
|
// Handle the case when there's only one root node
|
|
@@ -287,8 +266,8 @@ class BinaryTree {
|
|
|
287
266
|
}
|
|
288
267
|
}
|
|
289
268
|
this._size = this.size - 1;
|
|
290
|
-
|
|
291
|
-
return
|
|
269
|
+
deletedResult.push({ deleted: orgCurrent, needBalanced });
|
|
270
|
+
return deletedResult;
|
|
292
271
|
}
|
|
293
272
|
/**
|
|
294
273
|
* The function `getDepth` calculates the depth of a given node in a binary tree relative to a
|
|
@@ -303,10 +282,8 @@ class BinaryTree {
|
|
|
303
282
|
* @returns the depth of the `distNode` relative to the `beginRoot`.
|
|
304
283
|
*/
|
|
305
284
|
getDepth(distNode, beginRoot = this.root) {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
if (typeof beginRoot === 'number')
|
|
309
|
-
beginRoot = this.getNode(beginRoot);
|
|
285
|
+
distNode = this.ensureNotKey(distNode);
|
|
286
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
310
287
|
let depth = 0;
|
|
311
288
|
while (distNode === null || distNode === void 0 ? void 0 : distNode.parent) {
|
|
312
289
|
if (distNode === beginRoot) {
|
|
@@ -330,8 +307,7 @@ class BinaryTree {
|
|
|
330
307
|
* @returns the height of the binary tree.
|
|
331
308
|
*/
|
|
332
309
|
getHeight(beginRoot = this.root, iterationType = this.iterationType) {
|
|
333
|
-
|
|
334
|
-
beginRoot = this.getNode(beginRoot);
|
|
310
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
335
311
|
if (!beginRoot)
|
|
336
312
|
return -1;
|
|
337
313
|
if (iterationType === types_1.IterationType.RECURSIVE) {
|
|
@@ -352,12 +328,10 @@ class BinaryTree {
|
|
|
352
328
|
let maxHeight = 0;
|
|
353
329
|
while (stack.length > 0) {
|
|
354
330
|
const { node, depth } = stack.pop();
|
|
355
|
-
if (node.left)
|
|
331
|
+
if (node.left)
|
|
356
332
|
stack.push({ node: node.left, depth: depth + 1 });
|
|
357
|
-
|
|
358
|
-
if (node.right) {
|
|
333
|
+
if (node.right)
|
|
359
334
|
stack.push({ node: node.right, depth: depth + 1 });
|
|
360
|
-
}
|
|
361
335
|
maxHeight = Math.max(maxHeight, depth);
|
|
362
336
|
}
|
|
363
337
|
return maxHeight;
|
|
@@ -375,6 +349,7 @@ class BinaryTree {
|
|
|
375
349
|
*/
|
|
376
350
|
getMinHeight(beginRoot = this.root, iterationType = this.iterationType) {
|
|
377
351
|
var _a, _b, _c;
|
|
352
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
378
353
|
if (!beginRoot)
|
|
379
354
|
return -1;
|
|
380
355
|
if (iterationType === types_1.IterationType.RECURSIVE) {
|
|
@@ -436,7 +411,7 @@ class BinaryTree {
|
|
|
436
411
|
* @param callback - The `callback` parameter is a function that takes a node as input and returns a
|
|
437
412
|
* value. This value is compared with the `identifier` parameter to determine if the node should be
|
|
438
413
|
* included in the result. The `callback` parameter has a default value of
|
|
439
|
-
* `this.
|
|
414
|
+
* `this._defaultOneParamCallback`, which
|
|
440
415
|
* @param [onlyOne=false] - A boolean value indicating whether to stop searching after finding the
|
|
441
416
|
* first node that matches the identifier. If set to true, the function will return an array with
|
|
442
417
|
* only one element (or an empty array if no matching node is found). If set to false (default), the
|
|
@@ -448,11 +423,14 @@ class BinaryTree {
|
|
|
448
423
|
* traverse the binary tree. It can have two possible values:
|
|
449
424
|
* @returns The function `getNodes` returns an array of nodes (`N[]`).
|
|
450
425
|
*/
|
|
451
|
-
getNodes(identifier, callback = this.
|
|
426
|
+
getNodes(identifier, callback = this._defaultOneParamCallback, onlyOne = false, beginRoot = this.root, iterationType = this.iterationType) {
|
|
452
427
|
if (!beginRoot)
|
|
453
428
|
return [];
|
|
454
429
|
if (identifier instanceof BinaryTreeNode)
|
|
455
430
|
callback = (node => node);
|
|
431
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
432
|
+
if (!beginRoot)
|
|
433
|
+
return [];
|
|
456
434
|
const ans = [];
|
|
457
435
|
if (iterationType === types_1.IterationType.RECURSIVE) {
|
|
458
436
|
const _traverse = (cur) => {
|
|
@@ -493,7 +471,7 @@ class BinaryTree {
|
|
|
493
471
|
* @param callback - The `callback` parameter is a function that is used to determine whether a node
|
|
494
472
|
* matches the desired criteria. It takes a node as input and returns a boolean value indicating
|
|
495
473
|
* whether the node matches the criteria or not. The default callback function
|
|
496
|
-
* `this.
|
|
474
|
+
* `this._defaultOneParamCallback` is used if no callback function is
|
|
497
475
|
* @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies
|
|
498
476
|
* the node from which the search should begin. By default, it is set to `this.root`, which means the
|
|
499
477
|
* search will start from the root node of the binary tree. However, you can provide a different node
|
|
@@ -502,7 +480,7 @@ class BinaryTree {
|
|
|
502
480
|
* performed when searching for nodes in the binary tree. It can have one of the following values:
|
|
503
481
|
* @returns a boolean value.
|
|
504
482
|
*/
|
|
505
|
-
has(identifier, callback = this.
|
|
483
|
+
has(identifier, callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType) {
|
|
506
484
|
if (identifier instanceof BinaryTreeNode)
|
|
507
485
|
callback = (node => node);
|
|
508
486
|
return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0;
|
|
@@ -515,19 +493,73 @@ class BinaryTree {
|
|
|
515
493
|
* @param callback - The `callback` parameter is a function that is used to determine whether a node
|
|
516
494
|
* matches the desired criteria. It takes a node as input and returns a boolean value indicating
|
|
517
495
|
* whether the node matches the criteria or not. The default callback function
|
|
518
|
-
* (`this.
|
|
496
|
+
* (`this._defaultOneParamCallback`) is used if no callback function is
|
|
519
497
|
* @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies
|
|
520
498
|
* the root node from which the search should begin.
|
|
521
499
|
* @param iterationType - The `iterationType` parameter specifies the type of iteration to be
|
|
522
500
|
* performed when searching for a node in the binary tree. It can have one of the following values:
|
|
523
501
|
* @returns either the found node (of type N) or null if no node is found.
|
|
524
502
|
*/
|
|
525
|
-
getNode(identifier, callback = this.
|
|
503
|
+
getNode(identifier, callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType) {
|
|
526
504
|
var _a;
|
|
527
505
|
if (identifier instanceof BinaryTreeNode)
|
|
528
506
|
callback = (node => node);
|
|
529
507
|
return (_a = this.getNodes(identifier, callback, true, beginRoot, iterationType)[0]) !== null && _a !== void 0 ? _a : null;
|
|
530
508
|
}
|
|
509
|
+
/**
|
|
510
|
+
* The function `getNodeByKey` searches for a node in a binary tree by its key, using either
|
|
511
|
+
* recursive or iterative iteration.
|
|
512
|
+
* @param {BTNKey} key - The `key` parameter is the key value that we are searching for in the tree.
|
|
513
|
+
* It is used to find the node with the matching key value.
|
|
514
|
+
* @param iterationType - The `iterationType` parameter is used to determine whether the search for
|
|
515
|
+
* the node with the given key should be performed iteratively or recursively. It has two possible
|
|
516
|
+
* values:
|
|
517
|
+
* @returns The function `getNodeByKey` returns a node (`N`) if a node with the specified key is
|
|
518
|
+
* found in the binary tree. If no node is found, it returns `undefined`.
|
|
519
|
+
*/
|
|
520
|
+
getNodeByKey(key, iterationType = types_1.IterationType.ITERATIVE) {
|
|
521
|
+
if (!this.root)
|
|
522
|
+
return undefined;
|
|
523
|
+
if (iterationType === types_1.IterationType.RECURSIVE) {
|
|
524
|
+
const _dfs = (cur) => {
|
|
525
|
+
if (cur.key === key)
|
|
526
|
+
return cur;
|
|
527
|
+
if (!cur.left && !cur.right)
|
|
528
|
+
return;
|
|
529
|
+
if (cur.left)
|
|
530
|
+
return _dfs(cur.left);
|
|
531
|
+
if (cur.right)
|
|
532
|
+
return _dfs(cur.right);
|
|
533
|
+
};
|
|
534
|
+
return _dfs(this.root);
|
|
535
|
+
}
|
|
536
|
+
else {
|
|
537
|
+
const queue = new queue_1.Queue([this.root]);
|
|
538
|
+
while (queue.size > 0) {
|
|
539
|
+
const cur = queue.shift();
|
|
540
|
+
if (cur) {
|
|
541
|
+
if (cur.key === key)
|
|
542
|
+
return cur;
|
|
543
|
+
cur.left && queue.push(cur.left);
|
|
544
|
+
cur.right && queue.push(cur.right);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* The function `ensureNotKey` returns the node corresponding to the given key if it is a valid node
|
|
551
|
+
* key, otherwise it returns the key itself.
|
|
552
|
+
* @param {BTNKey | N | null | undefined} key - The `key` parameter can be of type `BTNKey`, `N`,
|
|
553
|
+
* `null`, or `undefined`. It represents a key used to identify a node in a binary tree.
|
|
554
|
+
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
|
|
555
|
+
* type of iteration to be used when searching for a node by key. It has a default value of
|
|
556
|
+
* `IterationType.ITERATIVE`.
|
|
557
|
+
* @returns either the node corresponding to the given key if it is a valid node key, or the key
|
|
558
|
+
* itself if it is not a valid node key.
|
|
559
|
+
*/
|
|
560
|
+
ensureNotKey(key, iterationType = types_1.IterationType.ITERATIVE) {
|
|
561
|
+
return this.isNodeKey(key) ? this.getNodeByKey(key, iterationType) : key;
|
|
562
|
+
}
|
|
531
563
|
/**
|
|
532
564
|
* The function `get` returns the first node value in a binary tree that matches the given property or key.
|
|
533
565
|
* @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of
|
|
@@ -536,19 +568,33 @@ class BinaryTree {
|
|
|
536
568
|
* @param callback - The `callback` parameter is a function that is used to determine whether a node
|
|
537
569
|
* matches the desired criteria. It takes a node as input and returns a boolean value indicating
|
|
538
570
|
* whether the node matches the criteria or not. The default callback function
|
|
539
|
-
* (`this.
|
|
571
|
+
* (`this._defaultOneParamCallback`) is used if no callback function is
|
|
540
572
|
* @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies
|
|
541
573
|
* the root node from which the search should begin.
|
|
542
574
|
* @param iterationType - The `iterationType` parameter specifies the type of iteration to be
|
|
543
575
|
* performed when searching for a node in the binary tree. It can have one of the following values:
|
|
544
576
|
* @returns either the found value (of type V) or undefined if no node value is found.
|
|
545
577
|
*/
|
|
546
|
-
get(identifier, callback = this.
|
|
578
|
+
get(identifier, callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType) {
|
|
547
579
|
var _a, _b;
|
|
548
580
|
if (identifier instanceof BinaryTreeNode)
|
|
549
581
|
callback = (node => node);
|
|
550
582
|
return (_b = (_a = this.getNode(identifier, callback, beginRoot, iterationType)) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : undefined;
|
|
551
583
|
}
|
|
584
|
+
/**
|
|
585
|
+
* Clear the binary tree, removing all nodes.
|
|
586
|
+
*/
|
|
587
|
+
clear() {
|
|
588
|
+
this._setRoot(undefined);
|
|
589
|
+
this._size = 0;
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* Check if the binary tree is empty.
|
|
593
|
+
* @returns {boolean} - True if the binary tree is empty, false otherwise.
|
|
594
|
+
*/
|
|
595
|
+
isEmpty() {
|
|
596
|
+
return this.size === 0;
|
|
597
|
+
}
|
|
552
598
|
/**
|
|
553
599
|
* The function `getPathToRoot` returns an array of nodes starting from a given node and traversing
|
|
554
600
|
* up to the root node, with the option to reverse the order of the nodes.
|
|
@@ -562,6 +608,9 @@ class BinaryTree {
|
|
|
562
608
|
getPathToRoot(beginRoot, isReverse = true) {
|
|
563
609
|
// TODO to support get path through passing key
|
|
564
610
|
const result = [];
|
|
611
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
612
|
+
if (!beginRoot)
|
|
613
|
+
return result;
|
|
565
614
|
while (beginRoot.parent) {
|
|
566
615
|
// Array.push + Array.reverse is more efficient than Array.unshift
|
|
567
616
|
// TODO may consider using Deque, so far this is not the performance bottleneck
|
|
@@ -583,13 +632,12 @@ class BinaryTree {
|
|
|
583
632
|
* no leftmost node, it returns `null`.
|
|
584
633
|
*/
|
|
585
634
|
getLeftMost(beginRoot = this.root, iterationType = this.iterationType) {
|
|
586
|
-
|
|
587
|
-
beginRoot = this.getNode(beginRoot);
|
|
635
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
588
636
|
if (!beginRoot)
|
|
589
637
|
return beginRoot;
|
|
590
638
|
if (iterationType === types_1.IterationType.RECURSIVE) {
|
|
591
639
|
const _traverse = (cur) => {
|
|
592
|
-
if (!cur.left)
|
|
640
|
+
if (!this.isRealNode(cur.left))
|
|
593
641
|
return cur;
|
|
594
642
|
return _traverse(cur.left);
|
|
595
643
|
};
|
|
@@ -598,7 +646,7 @@ class BinaryTree {
|
|
|
598
646
|
else {
|
|
599
647
|
// Indirect implementation of iteration using tail recursion optimization
|
|
600
648
|
const _traverse = (0, utils_1.trampoline)((cur) => {
|
|
601
|
-
if (!cur.left)
|
|
649
|
+
if (!this.isRealNode(cur.left))
|
|
602
650
|
return cur;
|
|
603
651
|
return _traverse.cont(cur.left);
|
|
604
652
|
});
|
|
@@ -618,11 +666,12 @@ class BinaryTree {
|
|
|
618
666
|
*/
|
|
619
667
|
getRightMost(beginRoot = this.root, iterationType = this.iterationType) {
|
|
620
668
|
// TODO support get right most by passing key in
|
|
669
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
621
670
|
if (!beginRoot)
|
|
622
671
|
return beginRoot;
|
|
623
672
|
if (iterationType === types_1.IterationType.RECURSIVE) {
|
|
624
673
|
const _traverse = (cur) => {
|
|
625
|
-
if (!cur.right)
|
|
674
|
+
if (!this.isRealNode(cur.right))
|
|
626
675
|
return cur;
|
|
627
676
|
return _traverse(cur.right);
|
|
628
677
|
};
|
|
@@ -631,7 +680,7 @@ class BinaryTree {
|
|
|
631
680
|
else {
|
|
632
681
|
// Indirect implementation of iteration using tail recursion optimization
|
|
633
682
|
const _traverse = (0, utils_1.trampoline)((cur) => {
|
|
634
|
-
if (!cur.right)
|
|
683
|
+
if (!this.isRealNode(cur.right))
|
|
635
684
|
return cur;
|
|
636
685
|
return _traverse.cont(cur.right);
|
|
637
686
|
});
|
|
@@ -649,6 +698,7 @@ class BinaryTree {
|
|
|
649
698
|
*/
|
|
650
699
|
isSubtreeBST(beginRoot, iterationType = this.iterationType) {
|
|
651
700
|
// TODO there is a bug
|
|
701
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
652
702
|
if (!beginRoot)
|
|
653
703
|
return true;
|
|
654
704
|
if (iterationType === types_1.IterationType.RECURSIVE) {
|
|
@@ -706,9 +756,8 @@ class BinaryTree {
|
|
|
706
756
|
* @param includeNull - The choice to output null values during binary tree traversal should be provided.
|
|
707
757
|
* @returns The function `subTreeTraverse` returns an array of `ReturnType<BTNCallback<N>>`.
|
|
708
758
|
*/
|
|
709
|
-
subTreeTraverse(callback = this.
|
|
710
|
-
|
|
711
|
-
beginRoot = this.getNode(beginRoot);
|
|
759
|
+
subTreeTraverse(callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType, includeNull = false) {
|
|
760
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
712
761
|
const ans = [];
|
|
713
762
|
if (!beginRoot)
|
|
714
763
|
return ans;
|
|
@@ -747,21 +796,46 @@ class BinaryTree {
|
|
|
747
796
|
}
|
|
748
797
|
return ans;
|
|
749
798
|
}
|
|
750
|
-
|
|
799
|
+
/**
|
|
800
|
+
* The function checks if a given node is a real node by verifying if it is an instance of
|
|
801
|
+
* BinaryTreeNode and its key is not NaN.
|
|
802
|
+
* @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
|
|
803
|
+
* @returns a boolean value.
|
|
804
|
+
*/
|
|
805
|
+
isRealNode(node) {
|
|
751
806
|
return node instanceof BinaryTreeNode && node.key.toString() !== 'NaN';
|
|
752
807
|
}
|
|
808
|
+
/**
|
|
809
|
+
* The function checks if a given node is a BinaryTreeNode instance and has a key value of NaN.
|
|
810
|
+
* @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
|
|
811
|
+
* @returns a boolean value.
|
|
812
|
+
*/
|
|
753
813
|
isNIL(node) {
|
|
754
814
|
return node instanceof BinaryTreeNode && node.key.toString() === 'NaN';
|
|
755
815
|
}
|
|
816
|
+
/**
|
|
817
|
+
* The function checks if a given node is a real node or null.
|
|
818
|
+
* @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
|
|
819
|
+
* @returns a boolean value.
|
|
820
|
+
*/
|
|
756
821
|
isNodeOrNull(node) {
|
|
757
|
-
return this.
|
|
822
|
+
return this.isRealNode(node) || node === null;
|
|
823
|
+
}
|
|
824
|
+
/**
|
|
825
|
+
* The function "isNodeKey" checks if a potential key is a number.
|
|
826
|
+
* @param {any} potentialKey - The potentialKey parameter is of type any, which means it can be any
|
|
827
|
+
* data type.
|
|
828
|
+
* @returns a boolean value indicating whether the potentialKey is of type number or not.
|
|
829
|
+
*/
|
|
830
|
+
isNodeKey(potentialKey) {
|
|
831
|
+
return typeof potentialKey === 'number';
|
|
758
832
|
}
|
|
759
833
|
/**
|
|
760
834
|
* The `dfs` function performs a depth-first search traversal on a binary tree, executing a callback
|
|
761
835
|
* function on each node according to a specified order pattern.
|
|
762
836
|
* @param callback - The `callback` parameter is a function that will be called on each node during
|
|
763
837
|
* the depth-first search traversal. It takes a node as input and returns a value. The default value
|
|
764
|
-
* is `this.
|
|
838
|
+
* is `this._defaultOneParamCallback`, which is a callback function defined elsewhere in the code.
|
|
765
839
|
* @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter determines the order in which the
|
|
766
840
|
* nodes are visited during the depth-first search. There are three possible values for `pattern`:
|
|
767
841
|
* @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the depth-first
|
|
@@ -772,7 +846,8 @@ class BinaryTree {
|
|
|
772
846
|
* @param includeNull - The choice to output null values during binary tree traversal should be provided.
|
|
773
847
|
* @returns The function `dfs` returns an array of `ReturnType<BTNCallback<N>>` values.
|
|
774
848
|
*/
|
|
775
|
-
dfs(callback = this.
|
|
849
|
+
dfs(callback = this._defaultOneParamCallback, pattern = 'in', beginRoot = this.root, iterationType = types_1.IterationType.ITERATIVE, includeNull = false) {
|
|
850
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
776
851
|
if (!beginRoot)
|
|
777
852
|
return [];
|
|
778
853
|
const ans = [];
|
|
@@ -790,7 +865,7 @@ class BinaryTree {
|
|
|
790
865
|
else {
|
|
791
866
|
if (node && node.left)
|
|
792
867
|
_traverse(node.left);
|
|
793
|
-
this.
|
|
868
|
+
this.isRealNode(node) && ans.push(callback(node));
|
|
794
869
|
if (node && node.right)
|
|
795
870
|
_traverse(node.right);
|
|
796
871
|
}
|
|
@@ -804,7 +879,7 @@ class BinaryTree {
|
|
|
804
879
|
_traverse(node.right);
|
|
805
880
|
}
|
|
806
881
|
else {
|
|
807
|
-
this.
|
|
882
|
+
this.isRealNode(node) && ans.push(callback(node));
|
|
808
883
|
if (node && node.left)
|
|
809
884
|
_traverse(node.left);
|
|
810
885
|
if (node && node.right)
|
|
@@ -824,7 +899,7 @@ class BinaryTree {
|
|
|
824
899
|
_traverse(node.left);
|
|
825
900
|
if (node && node.right)
|
|
826
901
|
_traverse(node.right);
|
|
827
|
-
this.
|
|
902
|
+
this.isRealNode(node) && ans.push(callback(node));
|
|
828
903
|
}
|
|
829
904
|
break;
|
|
830
905
|
}
|
|
@@ -882,7 +957,7 @@ class BinaryTree {
|
|
|
882
957
|
* function on each node.
|
|
883
958
|
* @param callback - The `callback` parameter is a function that will be called for each node in the
|
|
884
959
|
* breadth-first search. It takes a node of type `N` as its argument and returns a value of type
|
|
885
|
-
* `ReturnType<BTNCallback<N>>`. The default value for this parameter is `this.
|
|
960
|
+
* `ReturnType<BTNCallback<N>>`. The default value for this parameter is `this._defaultOneParamCallback
|
|
886
961
|
* @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the breadth-first
|
|
887
962
|
* search. It determines from which node the search will begin. If `beginRoot` is `null`, the search
|
|
888
963
|
* will not be performed and an empty array will be returned.
|
|
@@ -891,7 +966,8 @@ class BinaryTree {
|
|
|
891
966
|
* @param includeNull - The choice to output null values during binary tree traversal should be provided.
|
|
892
967
|
* @returns The function `bfs` returns an array of `ReturnType<BTNCallback<N>>[]`.
|
|
893
968
|
*/
|
|
894
|
-
bfs(callback = this.
|
|
969
|
+
bfs(callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType, includeNull = false) {
|
|
970
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
895
971
|
if (!beginRoot)
|
|
896
972
|
return [];
|
|
897
973
|
const ans = [];
|
|
@@ -958,10 +1034,11 @@ class BinaryTree {
|
|
|
958
1034
|
* level in a binary tree. Each inner array contains the return type of the provided callback
|
|
959
1035
|
* function `C` applied to the nodes at that level.
|
|
960
1036
|
*/
|
|
961
|
-
listLevels(callback = this.
|
|
962
|
-
|
|
963
|
-
return [];
|
|
1037
|
+
listLevels(callback = this._defaultOneParamCallback, beginRoot = this.root, iterationType = this.iterationType, includeNull = false) {
|
|
1038
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
964
1039
|
const levelsNodes = [];
|
|
1040
|
+
if (!beginRoot)
|
|
1041
|
+
return levelsNodes;
|
|
965
1042
|
if (iterationType === types_1.IterationType.RECURSIVE) {
|
|
966
1043
|
const _recursive = (node, level) => {
|
|
967
1044
|
if (!levelsNodes[level])
|
|
@@ -1012,9 +1089,12 @@ class BinaryTree {
|
|
|
1012
1089
|
* @returns The function `getPredecessor` returns the predecessor node of the given node `node`.
|
|
1013
1090
|
*/
|
|
1014
1091
|
getPredecessor(node) {
|
|
1092
|
+
node = this.ensureNotKey(node);
|
|
1093
|
+
if (!this.isRealNode(node))
|
|
1094
|
+
return undefined;
|
|
1015
1095
|
if (node.left) {
|
|
1016
1096
|
let predecessor = node.left;
|
|
1017
|
-
while (!predecessor || (predecessor.right && predecessor.right !== node)) {
|
|
1097
|
+
while (!this.isRealNode(predecessor) || (this.isRealNode(predecessor.right) && predecessor.right !== node)) {
|
|
1018
1098
|
if (predecessor) {
|
|
1019
1099
|
predecessor = predecessor.right;
|
|
1020
1100
|
}
|
|
@@ -1033,6 +1113,9 @@ class BinaryTree {
|
|
|
1033
1113
|
* if there is no successor, or `undefined` if the input `x` is `undefined`.
|
|
1034
1114
|
*/
|
|
1035
1115
|
getSuccessor(x) {
|
|
1116
|
+
x = this.ensureNotKey(x);
|
|
1117
|
+
if (!x)
|
|
1118
|
+
return undefined;
|
|
1036
1119
|
if (x.right) {
|
|
1037
1120
|
return this.getLeftMost(x.right);
|
|
1038
1121
|
}
|
|
@@ -1048,7 +1131,7 @@ class BinaryTree {
|
|
|
1048
1131
|
* algorithm and returns an array of values obtained by applying a callback function to each node.
|
|
1049
1132
|
* @param callback - The `callback` parameter is a function that will be called on each node in the
|
|
1050
1133
|
* tree. It takes a node of type `N` as input and returns a value of type `ReturnType<BTNCallback<N>>`. The
|
|
1051
|
-
* default value for this parameter is `this.
|
|
1134
|
+
* default value for this parameter is `this._defaultOneParamCallback`.
|
|
1052
1135
|
* @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter in the `morris` function
|
|
1053
1136
|
* determines the order in which the nodes of a binary tree are traversed. It can have one of the
|
|
1054
1137
|
* following values:
|
|
@@ -1057,7 +1140,8 @@ class BinaryTree {
|
|
|
1057
1140
|
* `beginRoot` is `null`, an empty array will be returned.
|
|
1058
1141
|
* @returns The `morris` function returns an array of `ReturnType<BTNCallback<N>>` values.
|
|
1059
1142
|
*/
|
|
1060
|
-
morris(callback = this.
|
|
1143
|
+
morris(callback = this._defaultOneParamCallback, pattern = 'in', beginRoot = this.root) {
|
|
1144
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
1061
1145
|
if (beginRoot === null)
|
|
1062
1146
|
return [];
|
|
1063
1147
|
const ans = [];
|
|
@@ -1189,15 +1273,20 @@ class BinaryTree {
|
|
|
1189
1273
|
* @returns {N} - The destination node after the swap.
|
|
1190
1274
|
*/
|
|
1191
1275
|
_swap(srcNode, destNode) {
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
if (
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1276
|
+
srcNode = this.ensureNotKey(srcNode);
|
|
1277
|
+
destNode = this.ensureNotKey(destNode);
|
|
1278
|
+
if (srcNode && destNode) {
|
|
1279
|
+
const { key, value } = destNode;
|
|
1280
|
+
const tempNode = this.createNode(key, value);
|
|
1281
|
+
if (tempNode) {
|
|
1282
|
+
destNode.key = srcNode.key;
|
|
1283
|
+
destNode.value = srcNode.value;
|
|
1284
|
+
srcNode.key = tempNode.key;
|
|
1285
|
+
srcNode.value = tempNode.value;
|
|
1286
|
+
}
|
|
1287
|
+
return destNode;
|
|
1199
1288
|
}
|
|
1200
|
-
return
|
|
1289
|
+
return undefined;
|
|
1201
1290
|
}
|
|
1202
1291
|
/**
|
|
1203
1292
|
* The function `_addTo` adds a new node to a binary tree if there is an available position.
|
|
@@ -1211,6 +1300,8 @@ class BinaryTree {
|
|
|
1211
1300
|
* If the parent node is null, the function also returns undefined.
|
|
1212
1301
|
*/
|
|
1213
1302
|
_addTo(newNode, parent) {
|
|
1303
|
+
if (this.isNodeKey(parent))
|
|
1304
|
+
parent = this.getNode(parent);
|
|
1214
1305
|
if (parent) {
|
|
1215
1306
|
// When all leaf nodes are null, it will no longer be possible to add new entity nodes to this binary tree.
|
|
1216
1307
|
// In this scenario, null nodes serve as "sentinel nodes," "virtual nodes," or "placeholder nodes."
|
|
@@ -1248,7 +1339,16 @@ class BinaryTree {
|
|
|
1248
1339
|
}
|
|
1249
1340
|
this._root = v;
|
|
1250
1341
|
}
|
|
1342
|
+
/**
|
|
1343
|
+
* The `print` function is used to display a binary tree structure in a visually appealing way.
|
|
1344
|
+
* @param {N | null | undefined} root - The `root` parameter in the `print` function represents the
|
|
1345
|
+
* root node of a binary tree. It can have one of the following types: `BTNKey`, `N`, `null`, or
|
|
1346
|
+
* `undefined`. The default value is `this.root`, which suggests that `this.root` is the
|
|
1347
|
+
*/
|
|
1251
1348
|
print(beginRoot = this.root) {
|
|
1349
|
+
beginRoot = this.ensureNotKey(beginRoot);
|
|
1350
|
+
if (!beginRoot)
|
|
1351
|
+
return;
|
|
1252
1352
|
const display = (root) => {
|
|
1253
1353
|
const [lines, , ,] = _displayAux(root);
|
|
1254
1354
|
for (const line of lines) {
|