data-structure-typed 1.52.3 → 1.52.5
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 +2 -1
- package/README.md +13 -13
- package/README_zh-CN.md +216 -26
- package/benchmark/report.html +13 -13
- package/benchmark/report.json +158 -158
- package/dist/cjs/data-structures/base/iterable-element-base.d.ts +1 -37
- package/dist/cjs/data-structures/base/iterable-element-base.js +1 -37
- package/dist/cjs/data-structures/base/iterable-element-base.js.map +1 -1
- package/dist/cjs/data-structures/base/iterable-entry-base.d.ts +2 -54
- package/dist/cjs/data-structures/base/iterable-entry-base.js +1 -49
- package/dist/cjs/data-structures/base/iterable-entry-base.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +0 -32
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +9 -41
- 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 +0 -46
- package/dist/cjs/data-structures/binary-tree/avl-tree.js +0 -46
- package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +82 -147
- package/dist/cjs/data-structures/binary-tree/binary-tree.js +299 -331
- package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/bst.d.ts +1 -40
- package/dist/cjs/data-structures/binary-tree/bst.js +12 -44
- package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/rb-tree.d.ts +0 -48
- package/dist/cjs/data-structures/binary-tree/rb-tree.js +2 -50
- 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 +0 -32
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +9 -41
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
- package/dist/cjs/data-structures/graph/abstract-graph.d.ts +0 -75
- package/dist/cjs/data-structures/graph/abstract-graph.js +0 -75
- package/dist/cjs/data-structures/graph/abstract-graph.js.map +1 -1
- package/dist/cjs/data-structures/graph/directed-graph.d.ts +0 -98
- package/dist/cjs/data-structures/graph/directed-graph.js +0 -98
- package/dist/cjs/data-structures/graph/directed-graph.js.map +1 -1
- package/dist/cjs/data-structures/graph/undirected-graph.d.ts +0 -50
- package/dist/cjs/data-structures/graph/undirected-graph.js +0 -50
- package/dist/cjs/data-structures/graph/undirected-graph.js.map +1 -1
- package/dist/cjs/data-structures/hash/hash-map.d.ts +5 -92
- package/dist/cjs/data-structures/hash/hash-map.js +29 -115
- package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
- package/dist/cjs/data-structures/heap/heap.d.ts +0 -32
- package/dist/cjs/data-structures/heap/heap.js +0 -32
- package/dist/cjs/data-structures/heap/heap.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/doubly-linked-list.d.ts +5 -88
- package/dist/cjs/data-structures/linked-list/doubly-linked-list.js +5 -88
- package/dist/cjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/singly-linked-list.d.ts +1 -83
- package/dist/cjs/data-structures/linked-list/singly-linked-list.js +2 -84
- package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/skip-linked-list.d.ts +1 -35
- package/dist/cjs/data-structures/linked-list/skip-linked-list.js +1 -35
- package/dist/cjs/data-structures/linked-list/skip-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/queue/deque.d.ts +1 -98
- package/dist/cjs/data-structures/queue/deque.js +3 -99
- package/dist/cjs/data-structures/queue/deque.js.map +1 -1
- package/dist/cjs/data-structures/queue/queue.d.ts +5 -58
- package/dist/cjs/data-structures/queue/queue.js +4 -57
- package/dist/cjs/data-structures/queue/queue.js.map +1 -1
- package/dist/cjs/data-structures/stack/stack.d.ts +1 -34
- package/dist/cjs/data-structures/stack/stack.js +1 -34
- package/dist/cjs/data-structures/stack/stack.js.map +1 -1
- package/dist/cjs/data-structures/tree/tree.js +0 -1
- package/dist/cjs/data-structures/tree/tree.js.map +1 -1
- package/dist/cjs/data-structures/trie/trie.d.ts +0 -64
- package/dist/cjs/data-structures/trie/trie.js +0 -64
- package/dist/cjs/data-structures/trie/trie.js.map +1 -1
- package/dist/cjs/types/data-structures/binary-tree/binary-tree.d.ts +8 -0
- package/dist/cjs/types/data-structures/binary-tree/binary-tree.js +6 -0
- package/dist/cjs/types/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/cjs/types/utils/utils.d.ts +13 -12
- package/dist/cjs/utils/number.d.ts +13 -0
- package/dist/cjs/utils/number.js +13 -0
- package/dist/cjs/utils/number.js.map +1 -1
- package/dist/cjs/utils/utils.d.ts +125 -3
- package/dist/cjs/utils/utils.js +177 -21
- package/dist/cjs/utils/utils.js.map +1 -1
- package/dist/mjs/data-structures/base/iterable-element-base.d.ts +1 -37
- package/dist/mjs/data-structures/base/iterable-element-base.js +1 -37
- package/dist/mjs/data-structures/base/iterable-entry-base.d.ts +2 -54
- package/dist/mjs/data-structures/base/iterable-entry-base.js +1 -49
- package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +0 -32
- package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.js +9 -41
- package/dist/mjs/data-structures/binary-tree/avl-tree.d.ts +0 -46
- package/dist/mjs/data-structures/binary-tree/avl-tree.js +0 -46
- package/dist/mjs/data-structures/binary-tree/binary-tree.d.ts +82 -147
- package/dist/mjs/data-structures/binary-tree/binary-tree.js +298 -332
- package/dist/mjs/data-structures/binary-tree/bst.d.ts +1 -40
- package/dist/mjs/data-structures/binary-tree/bst.js +12 -44
- package/dist/mjs/data-structures/binary-tree/rb-tree.d.ts +0 -48
- package/dist/mjs/data-structures/binary-tree/rb-tree.js +2 -50
- package/dist/mjs/data-structures/binary-tree/tree-multi-map.d.ts +0 -32
- package/dist/mjs/data-structures/binary-tree/tree-multi-map.js +9 -41
- package/dist/mjs/data-structures/graph/abstract-graph.d.ts +0 -75
- package/dist/mjs/data-structures/graph/abstract-graph.js +0 -75
- package/dist/mjs/data-structures/graph/directed-graph.d.ts +0 -98
- package/dist/mjs/data-structures/graph/directed-graph.js +0 -98
- package/dist/mjs/data-structures/graph/undirected-graph.d.ts +0 -50
- package/dist/mjs/data-structures/graph/undirected-graph.js +0 -50
- package/dist/mjs/data-structures/hash/hash-map.d.ts +5 -92
- package/dist/mjs/data-structures/hash/hash-map.js +29 -115
- package/dist/mjs/data-structures/heap/heap.d.ts +0 -32
- package/dist/mjs/data-structures/heap/heap.js +0 -32
- package/dist/mjs/data-structures/linked-list/doubly-linked-list.d.ts +5 -88
- package/dist/mjs/data-structures/linked-list/doubly-linked-list.js +5 -88
- package/dist/mjs/data-structures/linked-list/singly-linked-list.d.ts +1 -83
- package/dist/mjs/data-structures/linked-list/singly-linked-list.js +2 -84
- package/dist/mjs/data-structures/linked-list/skip-linked-list.d.ts +1 -35
- package/dist/mjs/data-structures/linked-list/skip-linked-list.js +1 -35
- package/dist/mjs/data-structures/queue/deque.d.ts +1 -98
- package/dist/mjs/data-structures/queue/deque.js +3 -99
- package/dist/mjs/data-structures/queue/queue.d.ts +5 -58
- package/dist/mjs/data-structures/queue/queue.js +4 -57
- package/dist/mjs/data-structures/stack/stack.d.ts +1 -34
- package/dist/mjs/data-structures/stack/stack.js +1 -34
- package/dist/mjs/data-structures/tree/tree.js +0 -1
- package/dist/mjs/data-structures/trie/trie.d.ts +0 -64
- package/dist/mjs/data-structures/trie/trie.js +0 -64
- package/dist/mjs/types/data-structures/binary-tree/binary-tree.d.ts +8 -0
- package/dist/mjs/types/data-structures/binary-tree/binary-tree.js +5 -1
- package/dist/mjs/types/utils/utils.d.ts +13 -12
- package/dist/mjs/utils/number.d.ts +13 -0
- package/dist/mjs/utils/number.js +13 -0
- package/dist/mjs/utils/utils.d.ts +125 -3
- package/dist/mjs/utils/utils.js +177 -21
- package/dist/umd/data-structure-typed.js +414 -1482
- package/dist/umd/data-structure-typed.min.js +5 -4
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +6 -6
- package/src/data-structures/base/iterable-element-base.ts +2 -42
- package/src/data-structures/base/iterable-entry-base.ts +3 -62
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +8 -48
- package/src/data-structures/binary-tree/avl-tree.ts +0 -57
- package/src/data-structures/binary-tree/binary-tree.ts +329 -358
- package/src/data-structures/binary-tree/bst.ts +11 -54
- package/src/data-structures/binary-tree/rb-tree.ts +2 -62
- package/src/data-structures/binary-tree/tree-multi-map.ts +8 -48
- package/src/data-structures/graph/abstract-graph.ts +0 -92
- package/src/data-structures/graph/directed-graph.ts +0 -122
- package/src/data-structures/graph/undirected-graph.ts +0 -62
- package/src/data-structures/hash/hash-map.ts +31 -139
- package/src/data-structures/heap/heap.ts +0 -40
- package/src/data-structures/linked-list/doubly-linked-list.ts +5 -112
- package/src/data-structures/linked-list/singly-linked-list.ts +2 -104
- package/src/data-structures/linked-list/skip-linked-list.ts +1 -44
- package/src/data-structures/queue/deque.ts +2 -125
- package/src/data-structures/queue/queue.ts +5 -72
- package/src/data-structures/stack/stack.ts +1 -43
- package/src/data-structures/tree/tree.ts +1 -1
- package/src/data-structures/trie/trie.ts +0 -80
- package/src/types/data-structures/binary-tree/binary-tree.ts +8 -1
- package/src/types/utils/utils.ts +17 -15
- package/src/utils/number.ts +13 -0
- package/src/utils/utils.ts +174 -18
- package/test/config.ts +8 -0
- package/test/integration/all-in-one.test.ts +1 -1
- package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +13 -13
- package/test/unit/data-structures/binary-tree/avl-tree.test.ts +18 -13
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +471 -64
- package/test/unit/data-structures/binary-tree/bst.test.ts +167 -23
- package/test/unit/data-structures/binary-tree/overall.test.ts +1 -1
- package/test/unit/data-structures/binary-tree/rb-tree.test.ts +136 -13
- package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +18 -13
- package/test/unit/data-structures/graph/directed-graph.test.ts +46 -32
- package/test/unit/data-structures/graph/map-graph.test.ts +24 -2
- package/test/unit/data-structures/graph/undirected-graph.test.ts +24 -24
- package/test/unit/data-structures/hash/hash-map.test.ts +225 -35
- package/test/unit/data-structures/heap/heap.test.ts +47 -39
- package/test/unit/data-structures/heap/min-heap.test.ts +5 -5
- package/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +34 -4
- package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +32 -0
- package/test/unit/data-structures/matrix/matrix.test.ts +35 -5
- package/test/unit/data-structures/priority-queue/max-priority-queue.test.ts +31 -0
- package/test/unit/data-structures/priority-queue/min-priority-queue.test.ts +18 -0
- package/test/unit/data-structures/priority-queue/priority-queue.test.ts +17 -0
- package/test/unit/data-structures/queue/deque.test.ts +288 -47
- package/test/unit/data-structures/queue/queue.test.ts +62 -37
- package/test/unit/data-structures/stack/stack.test.ts +30 -5
- package/test/unit/data-structures/tree/tree.test.ts +58 -0
- package/test/unit/data-structures/trie/trie.test.ts +46 -5
- package/test/unit/utils/utils.test.ts +169 -0
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
8
|
+
import { DFSOperation } from '../../types';
|
|
9
|
+
import { isComparable, trampoline } from '../../utils';
|
|
9
10
|
import { Queue } from '../queue';
|
|
10
11
|
import { IterableEntryBase } from '../base';
|
|
11
12
|
/**
|
|
@@ -189,30 +190,26 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
189
190
|
return null;
|
|
190
191
|
if (this.isNode(keyOrNodeOrEntryOrRawElement))
|
|
191
192
|
return keyOrNodeOrEntryOrRawElement;
|
|
192
|
-
if (this.toEntryFn) {
|
|
193
|
-
const [key, entryValue] = this.toEntryFn(keyOrNodeOrEntryOrRawElement);
|
|
194
|
-
if (key)
|
|
195
|
-
return this.createNode(key, entryValue ?? value);
|
|
196
|
-
else
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
193
|
if (this.isEntry(keyOrNodeOrEntryOrRawElement)) {
|
|
200
|
-
const [key,
|
|
194
|
+
const [key, entryValue] = keyOrNodeOrEntryOrRawElement;
|
|
201
195
|
if (key === undefined)
|
|
202
196
|
return;
|
|
203
197
|
else if (key === null)
|
|
204
198
|
return null;
|
|
199
|
+
if (this.isKey(key))
|
|
200
|
+
return this.createNode(key, value ?? entryValue);
|
|
201
|
+
}
|
|
202
|
+
if (this.toEntryFn) {
|
|
203
|
+
const [key, entryValue] = this.toEntryFn(keyOrNodeOrEntryOrRawElement);
|
|
204
|
+
if (this.isKey(key))
|
|
205
|
+
return this.createNode(key, value ?? entryValue);
|
|
205
206
|
else
|
|
206
|
-
return
|
|
207
|
+
return;
|
|
207
208
|
}
|
|
208
209
|
if (this.isKey(keyOrNodeOrEntryOrRawElement))
|
|
209
210
|
return this.createNode(keyOrNodeOrEntryOrRawElement, value);
|
|
210
211
|
return;
|
|
211
212
|
}
|
|
212
|
-
/**
|
|
213
|
-
* Time Complexity: O(n)
|
|
214
|
-
* Space Complexity: O(log n)
|
|
215
|
-
*/
|
|
216
213
|
/**
|
|
217
214
|
* Time Complexity: O(n)
|
|
218
215
|
* Space Complexity: O(log n)
|
|
@@ -227,7 +224,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
227
224
|
* default value of `'ITERATIVE'`.
|
|
228
225
|
* @returns The function `ensureNode` returns either a `NODE` object, `null`, or `undefined`.
|
|
229
226
|
*/
|
|
230
|
-
ensureNode(keyOrNodeOrEntryOrRawElement, iterationType =
|
|
227
|
+
ensureNode(keyOrNodeOrEntryOrRawElement, iterationType = this.iterationType) {
|
|
231
228
|
if (keyOrNodeOrEntryOrRawElement === null)
|
|
232
229
|
return null;
|
|
233
230
|
if (keyOrNodeOrEntryOrRawElement === undefined)
|
|
@@ -238,7 +235,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
238
235
|
return keyOrNodeOrEntryOrRawElement;
|
|
239
236
|
if (this.toEntryFn) {
|
|
240
237
|
const [key] = this.toEntryFn(keyOrNodeOrEntryOrRawElement);
|
|
241
|
-
if (key)
|
|
238
|
+
if (this.isKey(key))
|
|
242
239
|
return this.getNodeByKey(key);
|
|
243
240
|
}
|
|
244
241
|
if (this.isEntry(keyOrNodeOrEntryOrRawElement)) {
|
|
@@ -280,7 +277,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
280
277
|
* `BTNKeyOrNodeOrEntry<K, V, NODE>`.
|
|
281
278
|
* @returns a boolean value.
|
|
282
279
|
*/
|
|
283
|
-
|
|
280
|
+
isRealNodeOrNull(node) {
|
|
284
281
|
return this.isRealNode(node) || node === null;
|
|
285
282
|
}
|
|
286
283
|
/**
|
|
@@ -292,6 +289,23 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
292
289
|
isNIL(node) {
|
|
293
290
|
return node === this.NIL;
|
|
294
291
|
}
|
|
292
|
+
/**
|
|
293
|
+
* The function `isLeaf` determines whether a given node is a leaf node in a binary tree structure.
|
|
294
|
+
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} node - The `node` parameter in the `isLeaf` function
|
|
295
|
+
* can be either a regular node (`R`) or a `BTNKeyOrNodeOrEntry<K, V, NODE>`.
|
|
296
|
+
* @returns The `isLeaf` function is checking if the provided node is a leaf node in a binary tree.
|
|
297
|
+
* If the node is `undefined`, it returns `false`. If the node is `null`, it returns `true`.
|
|
298
|
+
* Otherwise, it checks if both the left and right children of the node are not real nodes, and
|
|
299
|
+
* returns `true` if they are not, indicating that the node is a
|
|
300
|
+
*/
|
|
301
|
+
isLeaf(node) {
|
|
302
|
+
node = this.ensureNode(node);
|
|
303
|
+
if (node === undefined)
|
|
304
|
+
return false;
|
|
305
|
+
if (node === null)
|
|
306
|
+
return true;
|
|
307
|
+
return !this.isRealNode(node.left) && !this.isRealNode(node.right);
|
|
308
|
+
}
|
|
295
309
|
/**
|
|
296
310
|
* The function checks if the input is an array with two elements, indicating it is a binary tree
|
|
297
311
|
* node entry.
|
|
@@ -303,41 +317,21 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
303
317
|
return Array.isArray(keyOrNodeOrEntryOrRawElement) && keyOrNodeOrEntryOrRawElement.length === 2;
|
|
304
318
|
}
|
|
305
319
|
/**
|
|
306
|
-
*
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
*
|
|
314
|
-
|
|
315
|
-
|
|
320
|
+
* Time Complexity O(1)
|
|
321
|
+
* Space Complexity O(1)
|
|
322
|
+
*
|
|
323
|
+
* The function `isKey` checks if a given key is comparable.
|
|
324
|
+
* @param {any} key - The `key` parameter is of type `any`, which means it can be any data type in
|
|
325
|
+
* TypeScript.
|
|
326
|
+
* @returns The function `isKey` is checking if the `key` parameter is `null` or if it is comparable.
|
|
327
|
+
* If the `key` is `null`, the function returns `true`. Otherwise, it returns the result of the
|
|
328
|
+
* `isComparable` function, which is not provided in the code snippet.
|
|
329
|
+
*/
|
|
330
|
+
isKey(key) {
|
|
316
331
|
if (key === null)
|
|
317
332
|
return true;
|
|
318
|
-
|
|
319
|
-
if (keyType === 'string' || keyType === 'bigint' || keyType === 'boolean')
|
|
320
|
-
return true;
|
|
321
|
-
if (keyType === 'number')
|
|
322
|
-
return !isNaN(key);
|
|
323
|
-
if (keyType === 'symbol' || keyType === 'undefined')
|
|
324
|
-
return false;
|
|
325
|
-
if (keyType === 'function')
|
|
326
|
-
return this.isKey(key());
|
|
327
|
-
if (keyType === 'object') {
|
|
328
|
-
if (typeof key.toString === 'function')
|
|
329
|
-
return true;
|
|
330
|
-
if (isCheckValueOf && typeof key.valueOf === 'function') {
|
|
331
|
-
this.isKey(key.valueOf(), false);
|
|
332
|
-
}
|
|
333
|
-
return false;
|
|
334
|
-
}
|
|
335
|
-
return false;
|
|
333
|
+
return isComparable(key);
|
|
336
334
|
}
|
|
337
|
-
/**
|
|
338
|
-
* Time Complexity O(n)
|
|
339
|
-
* Space Complexity O(1)
|
|
340
|
-
*/
|
|
341
335
|
/**
|
|
342
336
|
* Time Complexity O(n)
|
|
343
337
|
* Space Complexity O(1)
|
|
@@ -400,11 +394,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
400
394
|
}
|
|
401
395
|
return false; // If the insertion position cannot be found, return undefined
|
|
402
396
|
}
|
|
403
|
-
/**
|
|
404
|
-
* Time Complexity: O(k * n)
|
|
405
|
-
* Space Complexity: O(1)
|
|
406
|
-
* Comments: The time complexity for adding a node depends on the depth of the tree. In the best case (when the tree is empty), it's O(1). In the worst case (when the tree is a degenerate tree), it's O(n). The space complexity is constant.
|
|
407
|
-
*/
|
|
408
397
|
/**
|
|
409
398
|
* Time Complexity: O(k * n)
|
|
410
399
|
* Space Complexity: O(1)
|
|
@@ -438,11 +427,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
438
427
|
}
|
|
439
428
|
return inserted;
|
|
440
429
|
}
|
|
441
|
-
/**
|
|
442
|
-
* Time Complexity: O(k * n)
|
|
443
|
-
* Space Complexity: O(1)
|
|
444
|
-
* "n" is the number of nodes in the tree, and "k" is the number of keys to be inserted.
|
|
445
|
-
*/
|
|
446
430
|
/**
|
|
447
431
|
* Time Complexity: O(k * n)
|
|
448
432
|
* Space Complexity: O(1)
|
|
@@ -458,10 +442,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
458
442
|
this.clear();
|
|
459
443
|
this.addMany(keysOrNodesOrEntriesOrRawElements, values);
|
|
460
444
|
}
|
|
461
|
-
/**
|
|
462
|
-
* Time Complexity: O(n)
|
|
463
|
-
* Space Complexity: O(1)
|
|
464
|
-
*/
|
|
465
445
|
/**
|
|
466
446
|
* Time Complexity: O(n)
|
|
467
447
|
* Space Complexity: O(1)
|
|
@@ -492,7 +472,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
492
472
|
this._setRoot(undefined);
|
|
493
473
|
}
|
|
494
474
|
else if (curr.left) {
|
|
495
|
-
const leftSubTreeRightMost = this.getRightMost(curr.left);
|
|
475
|
+
const leftSubTreeRightMost = this.getRightMost(node => node, curr.left);
|
|
496
476
|
if (leftSubTreeRightMost) {
|
|
497
477
|
const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
|
|
498
478
|
orgCurrent = this._swapProperties(curr, leftSubTreeRightMost);
|
|
@@ -523,10 +503,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
523
503
|
deletedResult.push({ deleted: orgCurrent, needBalanced });
|
|
524
504
|
return deletedResult;
|
|
525
505
|
}
|
|
526
|
-
/**
|
|
527
|
-
* Time Complexity: O(n)
|
|
528
|
-
* Space Complexity: O(k + log n)
|
|
529
|
-
*/
|
|
530
506
|
/**
|
|
531
507
|
* Time Complexity: O(n)
|
|
532
508
|
* Space Complexity: O(k + log n)
|
|
@@ -552,6 +528,10 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
552
528
|
* @returns an array of NODE objects.
|
|
553
529
|
*/
|
|
554
530
|
getNodes(identifier, callback = this._DEFAULT_CALLBACK, onlyOne = false, beginRoot = this.root, iterationType = this.iterationType) {
|
|
531
|
+
if (identifier === undefined)
|
|
532
|
+
return [];
|
|
533
|
+
if (identifier === null)
|
|
534
|
+
return [];
|
|
555
535
|
beginRoot = this.ensureNode(beginRoot);
|
|
556
536
|
if (!beginRoot)
|
|
557
537
|
return [];
|
|
@@ -588,10 +568,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
588
568
|
}
|
|
589
569
|
return ans;
|
|
590
570
|
}
|
|
591
|
-
/**
|
|
592
|
-
* Time Complexity: O(n)
|
|
593
|
-
* Space Complexity: O(log n).
|
|
594
|
-
*/
|
|
595
571
|
/**
|
|
596
572
|
* Time Complexity: O(n)
|
|
597
573
|
* Space Complexity: O(log n).
|
|
@@ -613,10 +589,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
613
589
|
getNode(identifier, callback = this._DEFAULT_CALLBACK, beginRoot = this.root, iterationType = this.iterationType) {
|
|
614
590
|
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null;
|
|
615
591
|
}
|
|
616
|
-
/**
|
|
617
|
-
* Time Complexity: O(n)
|
|
618
|
-
* Space Complexity: O(log n)
|
|
619
|
-
*/
|
|
620
592
|
/**
|
|
621
593
|
* Time Complexity: O(n)
|
|
622
594
|
* Space Complexity: O(log n)
|
|
@@ -629,13 +601,9 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
629
601
|
* It has a default value of `'ITERATIVE'`.
|
|
630
602
|
* @returns a value of type NODE, null, or undefined.
|
|
631
603
|
*/
|
|
632
|
-
getNodeByKey(key, iterationType =
|
|
604
|
+
getNodeByKey(key, iterationType = this.iterationType) {
|
|
633
605
|
return this.getNode(key, this._DEFAULT_CALLBACK, this.root, iterationType);
|
|
634
606
|
}
|
|
635
|
-
/**
|
|
636
|
-
* Time Complexity: O(n)
|
|
637
|
-
* Space Complexity: O(log n)
|
|
638
|
-
*/
|
|
639
607
|
/**
|
|
640
608
|
* Time Complexity: O(n)
|
|
641
609
|
* Space Complexity: O(log n)
|
|
@@ -660,10 +628,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
660
628
|
get(identifier, callback = this._DEFAULT_CALLBACK, beginRoot = this.root, iterationType = this.iterationType) {
|
|
661
629
|
return this.getNode(identifier, callback, beginRoot, iterationType)?.value;
|
|
662
630
|
}
|
|
663
|
-
/**
|
|
664
|
-
* Time Complexity: O(n)
|
|
665
|
-
* Space Complexity: O(log n)
|
|
666
|
-
*/
|
|
667
631
|
/**
|
|
668
632
|
* Time Complexity: O(n)
|
|
669
633
|
* Space Complexity: O(log n)
|
|
@@ -688,10 +652,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
688
652
|
callback = this._ensureCallback(identifier, callback);
|
|
689
653
|
return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0;
|
|
690
654
|
}
|
|
691
|
-
/**
|
|
692
|
-
* Time Complexity: O(1)
|
|
693
|
-
* Space Complexity: O(1)
|
|
694
|
-
*/
|
|
695
655
|
/**
|
|
696
656
|
* Time Complexity: O(1)
|
|
697
657
|
* Space Complexity: O(1)
|
|
@@ -702,10 +662,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
702
662
|
this._setRoot(undefined);
|
|
703
663
|
this._size = 0;
|
|
704
664
|
}
|
|
705
|
-
/**
|
|
706
|
-
* Time Complexity: O(1)
|
|
707
|
-
* Space Complexity: O(1)
|
|
708
|
-
*/
|
|
709
665
|
/**
|
|
710
666
|
* Time Complexity: O(1)
|
|
711
667
|
* Space Complexity: O(1)
|
|
@@ -716,10 +672,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
716
672
|
isEmpty() {
|
|
717
673
|
return this.size === 0;
|
|
718
674
|
}
|
|
719
|
-
/**
|
|
720
|
-
* Time Complexity: O(n)
|
|
721
|
-
* Space Complexity: O(log n)
|
|
722
|
-
*/
|
|
723
675
|
/**
|
|
724
676
|
* Time Complexity: O(n)
|
|
725
677
|
* Space Complexity: O(log n)
|
|
@@ -735,10 +687,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
735
687
|
isPerfectlyBalanced(beginRoot = this.root) {
|
|
736
688
|
return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);
|
|
737
689
|
}
|
|
738
|
-
/**
|
|
739
|
-
* Time Complexity: O(n)
|
|
740
|
-
* Space Complexity: O(1)
|
|
741
|
-
*/
|
|
742
690
|
/**
|
|
743
691
|
* Time Complexity: O(n)
|
|
744
692
|
* Space Complexity: O(1)
|
|
@@ -795,10 +743,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
795
743
|
return isStandardBST || isInverseBST;
|
|
796
744
|
}
|
|
797
745
|
}
|
|
798
|
-
/**
|
|
799
|
-
* Time Complexity: O(n)
|
|
800
|
-
* Space Complexity: O(1)
|
|
801
|
-
*/
|
|
802
746
|
/**
|
|
803
747
|
* Time Complexity: O(n)
|
|
804
748
|
* Space Complexity: O(1)
|
|
@@ -826,10 +770,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
826
770
|
}
|
|
827
771
|
return depth;
|
|
828
772
|
}
|
|
829
|
-
/**
|
|
830
|
-
* Time Complexity: O(n)
|
|
831
|
-
* Space Complexity: O(1)
|
|
832
|
-
*/
|
|
833
773
|
/**
|
|
834
774
|
* Time Complexity: O(n)
|
|
835
775
|
* Space Complexity: O(1)
|
|
@@ -871,10 +811,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
871
811
|
return maxHeight;
|
|
872
812
|
}
|
|
873
813
|
}
|
|
874
|
-
/**
|
|
875
|
-
* Time Complexity: O(n)
|
|
876
|
-
* Space Complexity: O(log n)
|
|
877
|
-
*/
|
|
878
814
|
/**
|
|
879
815
|
* Time Complexity: O(n)
|
|
880
816
|
* Space Complexity: O(log n)
|
|
@@ -935,10 +871,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
935
871
|
return depths.get(beginRoot) ?? -1;
|
|
936
872
|
}
|
|
937
873
|
}
|
|
938
|
-
/**
|
|
939
|
-
* Time Complexity: O(log n)
|
|
940
|
-
* Space Complexity: O(log n)
|
|
941
|
-
*/
|
|
942
874
|
/**
|
|
943
875
|
* Time Complexity: O(log n)
|
|
944
876
|
* Space Complexity: O(log n)
|
|
@@ -965,36 +897,40 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
965
897
|
result.push(beginNodeEnsured);
|
|
966
898
|
return isReverse ? result.reverse() : result;
|
|
967
899
|
}
|
|
968
|
-
/**
|
|
969
|
-
* Time Complexity: O(log n)
|
|
970
|
-
* Space Complexity: O(1)
|
|
971
|
-
*/
|
|
972
900
|
/**
|
|
973
901
|
* Time Complexity: O(log n)
|
|
974
902
|
* Space Complexity: O(1)
|
|
975
903
|
*
|
|
976
|
-
* The `getLeftMost`
|
|
977
|
-
*
|
|
978
|
-
* @param {
|
|
979
|
-
*
|
|
980
|
-
*
|
|
981
|
-
* @param {
|
|
982
|
-
*
|
|
983
|
-
*
|
|
904
|
+
* The function `getLeftMost` retrieves the leftmost node in a binary tree using either recursive or
|
|
905
|
+
* tail-recursive iteration.
|
|
906
|
+
* @param {C} callback - The `callback` parameter is a function that will be called with the leftmost
|
|
907
|
+
* node of a binary tree or null if the tree is empty. It has a default value of `_DEFAULT_CALLBACK`
|
|
908
|
+
* if not provided explicitly.
|
|
909
|
+
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter in the
|
|
910
|
+
* `getLeftMost` function represents the starting point for finding the leftmost node in a binary
|
|
911
|
+
* tree. It can be either a reference to the root node of the tree (`R`), or a key, node, or entry in
|
|
912
|
+
* the binary tree structure (`
|
|
913
|
+
* @param {IterationType} iterationType - The `iterationType` parameter in the `getLeftMost` function
|
|
914
|
+
* specifies the type of iteration to be used when traversing the binary tree nodes. It can have two
|
|
915
|
+
* possible values:
|
|
916
|
+
* @returns The `getLeftMost` function returns the result of the callback function `C` applied to the
|
|
917
|
+
* leftmost node in the binary tree starting from the `beginRoot` node. If the `beginRoot` is `NIL`,
|
|
918
|
+
* it returns the result of the callback function applied to `undefined`. If the `beginRoot` is not a
|
|
919
|
+
* real node, it returns the result of the callback function applied
|
|
984
920
|
*/
|
|
985
|
-
getLeftMost(beginRoot = this.root, iterationType = this.iterationType) {
|
|
921
|
+
getLeftMost(callback = this._DEFAULT_CALLBACK, beginRoot = this.root, iterationType = this.iterationType) {
|
|
986
922
|
if (this.isNIL(beginRoot))
|
|
987
|
-
return
|
|
923
|
+
return callback(undefined);
|
|
988
924
|
beginRoot = this.ensureNode(beginRoot);
|
|
989
925
|
if (!this.isRealNode(beginRoot))
|
|
990
|
-
return beginRoot;
|
|
926
|
+
return callback(beginRoot);
|
|
991
927
|
if (iterationType === 'RECURSIVE') {
|
|
992
928
|
const dfs = (cur) => {
|
|
993
929
|
if (!this.isRealNode(cur.left))
|
|
994
930
|
return cur;
|
|
995
931
|
return dfs(cur.left);
|
|
996
932
|
};
|
|
997
|
-
return dfs(beginRoot);
|
|
933
|
+
return callback(dfs(beginRoot));
|
|
998
934
|
}
|
|
999
935
|
else {
|
|
1000
936
|
// Indirect implementation of iteration using tail recursion optimization
|
|
@@ -1003,41 +939,45 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1003
939
|
return cur;
|
|
1004
940
|
return dfs.cont(cur.left);
|
|
1005
941
|
});
|
|
1006
|
-
return dfs(beginRoot);
|
|
942
|
+
return callback(dfs(beginRoot));
|
|
1007
943
|
}
|
|
1008
944
|
}
|
|
1009
|
-
/**
|
|
1010
|
-
* Time Complexity: O(log n)
|
|
1011
|
-
* Space Complexity: O(1)
|
|
1012
|
-
*/
|
|
1013
945
|
/**
|
|
1014
946
|
* Time Complexity: O(log n)
|
|
1015
947
|
* Space Complexity: O(1)
|
|
1016
948
|
*
|
|
1017
|
-
* The `getRightMost`
|
|
1018
|
-
*
|
|
1019
|
-
* @param {
|
|
1020
|
-
*
|
|
1021
|
-
*
|
|
1022
|
-
* @param {
|
|
1023
|
-
*
|
|
1024
|
-
*
|
|
1025
|
-
*
|
|
1026
|
-
|
|
1027
|
-
|
|
949
|
+
* The function `getRightMost` retrieves the rightmost node in a binary tree using either recursive
|
|
950
|
+
* or iterative traversal methods.
|
|
951
|
+
* @param {C} callback - The `callback` parameter is a function that will be called with the result
|
|
952
|
+
* of the operation. It has a generic type `C` which extends `BTNCallback<OptBTNOrNull<NODE>>`. The
|
|
953
|
+
* default value for `callback` is `this._DEFAULT_CALLBACK` if it is not provided.
|
|
954
|
+
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter in the
|
|
955
|
+
* `getRightMost` function represents the starting point for finding the rightmost node in a binary
|
|
956
|
+
* tree. It can be either a reference to the root node of the tree (`this.root`) or a specific key,
|
|
957
|
+
* node, or entry in the tree. If
|
|
958
|
+
* @param {IterationType} iterationType - The `iterationType` parameter in the `getRightMost`
|
|
959
|
+
* function specifies the type of iteration to be used when finding the rightmost node in a binary
|
|
960
|
+
* tree. It can have two possible values:
|
|
961
|
+
* @returns The `getRightMost` function returns the result of the callback function `C` applied to
|
|
962
|
+
* the rightmost node in the binary tree. The rightmost node is found either through a recursive
|
|
963
|
+
* depth-first search (if `iterationType` is 'RECURSIVE') or through an indirect implementation of
|
|
964
|
+
* iteration using tail recursion optimization. The result of the callback function applied to the
|
|
965
|
+
* rightmost node is returned
|
|
966
|
+
*/
|
|
967
|
+
getRightMost(callback = this._DEFAULT_CALLBACK, beginRoot = this.root, iterationType = this.iterationType) {
|
|
1028
968
|
if (this.isNIL(beginRoot))
|
|
1029
|
-
return
|
|
969
|
+
return callback(undefined);
|
|
1030
970
|
// TODO support get right most by passing key in
|
|
1031
971
|
beginRoot = this.ensureNode(beginRoot);
|
|
1032
972
|
if (!beginRoot)
|
|
1033
|
-
return beginRoot;
|
|
973
|
+
return callback(beginRoot);
|
|
1034
974
|
if (iterationType === 'RECURSIVE') {
|
|
1035
975
|
const dfs = (cur) => {
|
|
1036
976
|
if (!this.isRealNode(cur.right))
|
|
1037
977
|
return cur;
|
|
1038
978
|
return dfs(cur.right);
|
|
1039
979
|
};
|
|
1040
|
-
return dfs(beginRoot);
|
|
980
|
+
return callback(dfs(beginRoot));
|
|
1041
981
|
}
|
|
1042
982
|
else {
|
|
1043
983
|
// Indirect implementation of iteration using tail recursion optimization
|
|
@@ -1046,13 +986,9 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1046
986
|
return cur;
|
|
1047
987
|
return dfs.cont(cur.right);
|
|
1048
988
|
});
|
|
1049
|
-
return dfs(beginRoot);
|
|
989
|
+
return callback(dfs(beginRoot));
|
|
1050
990
|
}
|
|
1051
991
|
}
|
|
1052
|
-
/**
|
|
1053
|
-
* Time Complexity: O(log n)
|
|
1054
|
-
* Space Complexity: O(1)
|
|
1055
|
-
*/
|
|
1056
992
|
/**
|
|
1057
993
|
* Time Complexity: O(log n)
|
|
1058
994
|
* Space Complexity: O(1)
|
|
@@ -1076,10 +1012,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1076
1012
|
return node;
|
|
1077
1013
|
}
|
|
1078
1014
|
}
|
|
1079
|
-
/**
|
|
1080
|
-
* Time Complexity: O(log n)
|
|
1081
|
-
* Space Complexity: O(1)
|
|
1082
|
-
*/
|
|
1083
1015
|
/**
|
|
1084
1016
|
* Time Complexity: O(log n)
|
|
1085
1017
|
* Space Complexity: O(1)
|
|
@@ -1094,7 +1026,7 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1094
1026
|
if (!this.isRealNode(x))
|
|
1095
1027
|
return undefined;
|
|
1096
1028
|
if (this.isRealNode(x.right)) {
|
|
1097
|
-
return this.getLeftMost(x.right);
|
|
1029
|
+
return this.getLeftMost(node => node, x.right);
|
|
1098
1030
|
}
|
|
1099
1031
|
let y = x.parent;
|
|
1100
1032
|
while (this.isRealNode(y) && x === y.right) {
|
|
@@ -1103,10 +1035,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1103
1035
|
}
|
|
1104
1036
|
return y;
|
|
1105
1037
|
}
|
|
1106
|
-
/**
|
|
1107
|
-
* Time complexity: O(n)
|
|
1108
|
-
* Space complexity: O(n)
|
|
1109
|
-
*/
|
|
1110
1038
|
/**
|
|
1111
1039
|
* Time complexity: O(n)
|
|
1112
1040
|
* Space complexity: O(n)
|
|
@@ -1130,116 +1058,12 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1130
1058
|
* values will
|
|
1131
1059
|
* @returns an array of the return types of the callback function.
|
|
1132
1060
|
*/
|
|
1133
|
-
dfs(callback = this._DEFAULT_CALLBACK, pattern = 'IN', beginRoot = this.root, iterationType =
|
|
1061
|
+
dfs(callback = this._DEFAULT_CALLBACK, pattern = 'IN', beginRoot = this.root, iterationType = this.iterationType, includeNull = false) {
|
|
1134
1062
|
beginRoot = this.ensureNode(beginRoot);
|
|
1135
1063
|
if (!beginRoot)
|
|
1136
1064
|
return [];
|
|
1137
|
-
|
|
1138
|
-
if (iterationType === 'RECURSIVE') {
|
|
1139
|
-
const dfs = (node) => {
|
|
1140
|
-
switch (pattern) {
|
|
1141
|
-
case 'IN':
|
|
1142
|
-
if (includeNull) {
|
|
1143
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.left))
|
|
1144
|
-
dfs(node.left);
|
|
1145
|
-
this.isNodeOrNull(node) && ans.push(callback(node));
|
|
1146
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.right))
|
|
1147
|
-
dfs(node.right);
|
|
1148
|
-
}
|
|
1149
|
-
else {
|
|
1150
|
-
if (this.isRealNode(node) && this.isRealNode(node.left))
|
|
1151
|
-
dfs(node.left);
|
|
1152
|
-
this.isRealNode(node) && ans.push(callback(node));
|
|
1153
|
-
if (this.isRealNode(node) && this.isRealNode(node.right))
|
|
1154
|
-
dfs(node.right);
|
|
1155
|
-
}
|
|
1156
|
-
break;
|
|
1157
|
-
case 'PRE':
|
|
1158
|
-
if (includeNull) {
|
|
1159
|
-
this.isNodeOrNull(node) && ans.push(callback(node));
|
|
1160
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.left))
|
|
1161
|
-
dfs(node.left);
|
|
1162
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.right))
|
|
1163
|
-
dfs(node.right);
|
|
1164
|
-
}
|
|
1165
|
-
else {
|
|
1166
|
-
this.isRealNode(node) && ans.push(callback(node));
|
|
1167
|
-
if (this.isRealNode(node) && this.isRealNode(node.left))
|
|
1168
|
-
dfs(node.left);
|
|
1169
|
-
if (this.isRealNode(node) && this.isRealNode(node.right))
|
|
1170
|
-
dfs(node.right);
|
|
1171
|
-
}
|
|
1172
|
-
break;
|
|
1173
|
-
case 'POST':
|
|
1174
|
-
if (includeNull) {
|
|
1175
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.left))
|
|
1176
|
-
dfs(node.left);
|
|
1177
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.right))
|
|
1178
|
-
dfs(node.right);
|
|
1179
|
-
this.isNodeOrNull(node) && ans.push(callback(node));
|
|
1180
|
-
}
|
|
1181
|
-
else {
|
|
1182
|
-
if (this.isRealNode(node) && this.isRealNode(node.left))
|
|
1183
|
-
dfs(node.left);
|
|
1184
|
-
if (this.isRealNode(node) && this.isRealNode(node.right))
|
|
1185
|
-
dfs(node.right);
|
|
1186
|
-
this.isRealNode(node) && ans.push(callback(node));
|
|
1187
|
-
}
|
|
1188
|
-
break;
|
|
1189
|
-
}
|
|
1190
|
-
};
|
|
1191
|
-
dfs(beginRoot);
|
|
1192
|
-
}
|
|
1193
|
-
else {
|
|
1194
|
-
// 0: visit, 1: print
|
|
1195
|
-
const stack = [{ opt: 0, node: beginRoot }];
|
|
1196
|
-
while (stack.length > 0) {
|
|
1197
|
-
const cur = stack.pop();
|
|
1198
|
-
if (cur === undefined || this.isNIL(cur.node))
|
|
1199
|
-
continue;
|
|
1200
|
-
if (includeNull) {
|
|
1201
|
-
if (cur.node === undefined)
|
|
1202
|
-
continue;
|
|
1203
|
-
}
|
|
1204
|
-
else {
|
|
1205
|
-
if (cur.node === null || cur.node === undefined)
|
|
1206
|
-
continue;
|
|
1207
|
-
}
|
|
1208
|
-
if (cur.opt === 1) {
|
|
1209
|
-
ans.push(callback(cur.node));
|
|
1210
|
-
}
|
|
1211
|
-
else {
|
|
1212
|
-
switch (pattern) {
|
|
1213
|
-
case 'IN':
|
|
1214
|
-
cur.node && stack.push({ opt: 0, node: cur.node.right });
|
|
1215
|
-
stack.push({ opt: 1, node: cur.node });
|
|
1216
|
-
cur.node && stack.push({ opt: 0, node: cur.node.left });
|
|
1217
|
-
break;
|
|
1218
|
-
case 'PRE':
|
|
1219
|
-
cur.node && stack.push({ opt: 0, node: cur.node.right });
|
|
1220
|
-
cur.node && stack.push({ opt: 0, node: cur.node.left });
|
|
1221
|
-
stack.push({ opt: 1, node: cur.node });
|
|
1222
|
-
break;
|
|
1223
|
-
case 'POST':
|
|
1224
|
-
stack.push({ opt: 1, node: cur.node });
|
|
1225
|
-
cur.node && stack.push({ opt: 0, node: cur.node.right });
|
|
1226
|
-
cur.node && stack.push({ opt: 0, node: cur.node.left });
|
|
1227
|
-
break;
|
|
1228
|
-
default:
|
|
1229
|
-
cur.node && stack.push({ opt: 0, node: cur.node.right });
|
|
1230
|
-
stack.push({ opt: 1, node: cur.node });
|
|
1231
|
-
cur.node && stack.push({ opt: 0, node: cur.node.left });
|
|
1232
|
-
break;
|
|
1233
|
-
}
|
|
1234
|
-
}
|
|
1235
|
-
}
|
|
1236
|
-
}
|
|
1237
|
-
return ans;
|
|
1065
|
+
return this._dfs(callback, pattern, beginRoot, iterationType, includeNull);
|
|
1238
1066
|
}
|
|
1239
|
-
/**
|
|
1240
|
-
* Time complexity: O(n)
|
|
1241
|
-
* Space complexity: O(n)
|
|
1242
|
-
*/
|
|
1243
1067
|
/**
|
|
1244
1068
|
* Time complexity: O(n)
|
|
1245
1069
|
* Space complexity: O(n)
|
|
@@ -1275,9 +1099,9 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1275
1099
|
const current = queue.shift();
|
|
1276
1100
|
ans.push(callback(current));
|
|
1277
1101
|
if (includeNull) {
|
|
1278
|
-
if (current && this.
|
|
1102
|
+
if (current && this.isRealNodeOrNull(current.left))
|
|
1279
1103
|
queue.push(current.left);
|
|
1280
|
-
if (current && this.
|
|
1104
|
+
if (current && this.isRealNodeOrNull(current.right))
|
|
1281
1105
|
queue.push(current.right);
|
|
1282
1106
|
}
|
|
1283
1107
|
else {
|
|
@@ -1298,9 +1122,9 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1298
1122
|
const current = queue.shift();
|
|
1299
1123
|
ans.push(callback(current));
|
|
1300
1124
|
if (includeNull) {
|
|
1301
|
-
if (current && this.
|
|
1125
|
+
if (current && this.isRealNodeOrNull(current.left))
|
|
1302
1126
|
queue.push(current.left);
|
|
1303
|
-
if (current && this.
|
|
1127
|
+
if (current && this.isRealNodeOrNull(current.right))
|
|
1304
1128
|
queue.push(current.right);
|
|
1305
1129
|
}
|
|
1306
1130
|
else {
|
|
@@ -1317,7 +1141,55 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1317
1141
|
/**
|
|
1318
1142
|
* Time complexity: O(n)
|
|
1319
1143
|
* Space complexity: O(n)
|
|
1320
|
-
|
|
1144
|
+
*
|
|
1145
|
+
* The `leaves` function in TypeScript iterates through a binary tree to find and return the leaf
|
|
1146
|
+
* nodes based on a specified callback and iteration type.
|
|
1147
|
+
* @param {C} callback - The `callback` parameter is a function that will be called on each leaf node
|
|
1148
|
+
* in the binary tree. It is a generic type `C` that extends `BTNCallback<NODE | null>`, where `NODE`
|
|
1149
|
+
* represents a node in the binary tree. The default value for `callback` is
|
|
1150
|
+
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter in the `leaves`
|
|
1151
|
+
* method is used to specify the starting point for finding and processing the leaves of a binary
|
|
1152
|
+
* tree. It represents the root node of the binary tree or a specific key, node, or entry within the
|
|
1153
|
+
* tree from which the search for leaves should begin
|
|
1154
|
+
* @param {IterationType} iterationType - The `iterationType` parameter in the `leaves` method
|
|
1155
|
+
* specifies the type of iteration to be performed when collecting the leaves of a binary tree. It
|
|
1156
|
+
* can have two possible values:
|
|
1157
|
+
* @returns The `leaves` method returns an array of values that are the result of applying the
|
|
1158
|
+
* provided callback function to the leaf nodes in the binary tree structure.
|
|
1159
|
+
*/
|
|
1160
|
+
leaves(callback = this._DEFAULT_CALLBACK, beginRoot = this.root, iterationType = this.iterationType) {
|
|
1161
|
+
beginRoot = this.ensureNode(beginRoot);
|
|
1162
|
+
const leaves = [];
|
|
1163
|
+
if (!this.isRealNode(beginRoot)) {
|
|
1164
|
+
return [];
|
|
1165
|
+
}
|
|
1166
|
+
if (iterationType === 'RECURSIVE') {
|
|
1167
|
+
const dfs = (cur) => {
|
|
1168
|
+
if (this.isLeaf(cur)) {
|
|
1169
|
+
leaves.push(callback(cur));
|
|
1170
|
+
}
|
|
1171
|
+
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right))
|
|
1172
|
+
return;
|
|
1173
|
+
this.isRealNode(cur.left) && dfs(cur.left);
|
|
1174
|
+
this.isRealNode(cur.right) && dfs(cur.right);
|
|
1175
|
+
};
|
|
1176
|
+
dfs(beginRoot);
|
|
1177
|
+
}
|
|
1178
|
+
else {
|
|
1179
|
+
const queue = new Queue([beginRoot]);
|
|
1180
|
+
while (queue.size > 0) {
|
|
1181
|
+
const cur = queue.shift();
|
|
1182
|
+
if (this.isRealNode(cur)) {
|
|
1183
|
+
if (this.isLeaf(cur)) {
|
|
1184
|
+
leaves.push(callback(cur));
|
|
1185
|
+
}
|
|
1186
|
+
this.isRealNode(cur.left) && queue.push(cur.left);
|
|
1187
|
+
this.isRealNode(cur.right) && queue.push(cur.right);
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
return leaves;
|
|
1192
|
+
}
|
|
1321
1193
|
/**
|
|
1322
1194
|
* Time complexity: O(n)
|
|
1323
1195
|
* Space complexity: O(n)
|
|
@@ -1350,9 +1222,9 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1350
1222
|
levelsNodes[level] = [];
|
|
1351
1223
|
levelsNodes[level].push(callback(node));
|
|
1352
1224
|
if (includeNull) {
|
|
1353
|
-
if (node && this.
|
|
1225
|
+
if (node && this.isRealNodeOrNull(node.left))
|
|
1354
1226
|
_recursive(node.left, level + 1);
|
|
1355
|
-
if (node && this.
|
|
1227
|
+
if (node && this.isRealNodeOrNull(node.right))
|
|
1356
1228
|
_recursive(node.right, level + 1);
|
|
1357
1229
|
}
|
|
1358
1230
|
else {
|
|
@@ -1373,9 +1245,9 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1373
1245
|
levelsNodes[level] = [];
|
|
1374
1246
|
levelsNodes[level].push(callback(node));
|
|
1375
1247
|
if (includeNull) {
|
|
1376
|
-
if (node && this.
|
|
1248
|
+
if (node && this.isRealNodeOrNull(node.right))
|
|
1377
1249
|
stack.push([node.right, level + 1]);
|
|
1378
|
-
if (node && this.
|
|
1250
|
+
if (node && this.isRealNodeOrNull(node.left))
|
|
1379
1251
|
stack.push([node.left, level + 1]);
|
|
1380
1252
|
}
|
|
1381
1253
|
else {
|
|
@@ -1388,10 +1260,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1388
1260
|
}
|
|
1389
1261
|
return levelsNodes;
|
|
1390
1262
|
}
|
|
1391
|
-
/**
|
|
1392
|
-
* Time complexity: O(n)
|
|
1393
|
-
* Space complexity: O(n)
|
|
1394
|
-
*/
|
|
1395
1263
|
/**
|
|
1396
1264
|
* Time complexity: O(n)
|
|
1397
1265
|
* Space complexity: O(n)
|
|
@@ -1496,10 +1364,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1496
1364
|
}
|
|
1497
1365
|
return ans;
|
|
1498
1366
|
}
|
|
1499
|
-
/**
|
|
1500
|
-
* Time complexity: O(n)
|
|
1501
|
-
* Space complexity: O(n)
|
|
1502
|
-
*/
|
|
1503
1367
|
/**
|
|
1504
1368
|
* Time complexity: O(n)
|
|
1505
1369
|
* Space complexity: O(n)
|
|
@@ -1517,10 +1381,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1517
1381
|
}, this.root, this.iterationType, true);
|
|
1518
1382
|
return cloned;
|
|
1519
1383
|
}
|
|
1520
|
-
/**
|
|
1521
|
-
* Time Complexity: O(n)
|
|
1522
|
-
* Space Complexity: O(n)
|
|
1523
|
-
*/
|
|
1524
1384
|
/**
|
|
1525
1385
|
* Time Complexity: O(n)
|
|
1526
1386
|
* Space Complexity: O(n)
|
|
@@ -1546,10 +1406,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1546
1406
|
}
|
|
1547
1407
|
return newTree;
|
|
1548
1408
|
}
|
|
1549
|
-
/**
|
|
1550
|
-
* Time Complexity: O(n)
|
|
1551
|
-
* Space Complexity: O(n)
|
|
1552
|
-
*/
|
|
1553
1409
|
/**
|
|
1554
1410
|
* Time Complexity: O(n)
|
|
1555
1411
|
* Space Complexity: O(n)
|
|
@@ -1582,10 +1438,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1582
1438
|
// // return newTree;
|
|
1583
1439
|
// // }
|
|
1584
1440
|
//
|
|
1585
|
-
/**
|
|
1586
|
-
* Time Complexity: O(n)
|
|
1587
|
-
* Space Complexity: O(n)
|
|
1588
|
-
*/
|
|
1589
1441
|
/**
|
|
1590
1442
|
* Time Complexity: O(n)
|
|
1591
1443
|
* Space Complexity: O(n)
|
|
@@ -1603,29 +1455,163 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1603
1455
|
print(beginRoot = this.root, options) {
|
|
1604
1456
|
const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options };
|
|
1605
1457
|
beginRoot = this.ensureNode(beginRoot);
|
|
1458
|
+
let output = '';
|
|
1606
1459
|
if (!beginRoot)
|
|
1607
|
-
return;
|
|
1460
|
+
return output;
|
|
1608
1461
|
if (opts.isShowUndefined)
|
|
1609
|
-
|
|
1610
|
-
|
|
1462
|
+
output += `U for undefined
|
|
1463
|
+
`;
|
|
1611
1464
|
if (opts.isShowNull)
|
|
1612
|
-
|
|
1613
|
-
|
|
1465
|
+
output += `N for null
|
|
1466
|
+
`;
|
|
1614
1467
|
if (opts.isShowRedBlackNIL)
|
|
1615
|
-
|
|
1616
|
-
|
|
1468
|
+
output += `S for Sentinel Node(NIL)
|
|
1469
|
+
`;
|
|
1617
1470
|
const display = (root) => {
|
|
1618
1471
|
const [lines, , ,] = this._displayAux(root, opts);
|
|
1472
|
+
let paragraph = '';
|
|
1619
1473
|
for (const line of lines) {
|
|
1620
|
-
|
|
1474
|
+
paragraph += line + '\n';
|
|
1621
1475
|
}
|
|
1476
|
+
output += paragraph;
|
|
1622
1477
|
};
|
|
1623
1478
|
display(beginRoot);
|
|
1479
|
+
return output;
|
|
1624
1480
|
}
|
|
1625
1481
|
/**
|
|
1626
|
-
* Time
|
|
1627
|
-
* Space
|
|
1628
|
-
|
|
1482
|
+
* Time complexity: O(n)
|
|
1483
|
+
* Space complexity: O(n)
|
|
1484
|
+
*
|
|
1485
|
+
* The function `_dfs` performs a depth-first search traversal on a binary tree structure based on
|
|
1486
|
+
* the specified order pattern and callback function.
|
|
1487
|
+
* @param {C} callback - The `callback` parameter is a function that will be called on each node
|
|
1488
|
+
* visited during the depth-first search. It is of type `C`, which extends
|
|
1489
|
+
* `BTNCallback<OptBTNOrNull<NODE>>`. The default value is set to `this._DEFAULT_CALLBACK` if not
|
|
1490
|
+
* provided.
|
|
1491
|
+
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `_dfs` method specifies the
|
|
1492
|
+
* order in which the Depth-First Search (DFS) algorithm should traverse the nodes in a binary tree.
|
|
1493
|
+
* It can have one of the following values:
|
|
1494
|
+
* @param {R | BTNKeyOrNodeOrEntry<K, V, NODE>} beginRoot - The `beginRoot` parameter in the `_dfs`
|
|
1495
|
+
* method is used to specify the starting point for the depth-first search traversal in a binary
|
|
1496
|
+
* tree. It can be provided as either the root node of the tree or a key, node, or entry that exists
|
|
1497
|
+
* in the tree. If no specific `
|
|
1498
|
+
* @param {IterationType} iterationType - The `iterationType` parameter in the `_dfs` method
|
|
1499
|
+
* specifies the type of iteration to be performed during the Depth-First Search (DFS) traversal. It
|
|
1500
|
+
* can have two possible values:
|
|
1501
|
+
* @param [includeNull=false] - The `includeNull` parameter in the `_dfs` method is a boolean flag
|
|
1502
|
+
* that determines whether null nodes should be included in the depth-first search traversal. If
|
|
1503
|
+
* `includeNull` is set to `true`, the traversal will consider null nodes as valid nodes to visit and
|
|
1504
|
+
* process. If set to `
|
|
1505
|
+
* @param shouldVisitLeft - The `shouldVisitLeft` parameter is a function that takes a node as input
|
|
1506
|
+
* and returns a boolean value. It is used to determine whether the left child of a node should be
|
|
1507
|
+
* visited during the depth-first search traversal. By default, it checks if the node is truthy (not
|
|
1508
|
+
* null or undefined
|
|
1509
|
+
* @param shouldVisitRight - The `shouldVisitRight` parameter is a function that takes a node as
|
|
1510
|
+
* input and returns a boolean value. It is used to determine whether the right child of a node
|
|
1511
|
+
* should be visited during the depth-first search traversal. The default implementation checks if
|
|
1512
|
+
* the node is truthy before visiting the right child.
|
|
1513
|
+
* @param shouldVisitRoot - The `shouldVisitRoot` parameter is a function that takes a node as an
|
|
1514
|
+
* argument and returns a boolean value. It is used to determine whether a given node should be
|
|
1515
|
+
* visited during the depth-first search traversal based on certain conditions. The default
|
|
1516
|
+
* implementation checks if the node is a real node or null based
|
|
1517
|
+
* @param shouldProcessRoot - The `shouldProcessRoot` parameter is a function that takes a node as
|
|
1518
|
+
* input and returns a boolean value indicating whether the node should be processed during the
|
|
1519
|
+
* depth-first search traversal. The default implementation of this function simply returns `true`,
|
|
1520
|
+
* meaning that by default all nodes will be processed. However, you can
|
|
1521
|
+
* @returns The `_dfs` method returns an array of the return type of the callback function provided
|
|
1522
|
+
* as input.
|
|
1523
|
+
*/
|
|
1524
|
+
_dfs(callback = this._DEFAULT_CALLBACK, pattern = 'IN', beginRoot = this.root, iterationType = this.iterationType, includeNull = false, shouldVisitLeft = node => !!node, shouldVisitRight = node => !!node, shouldVisitRoot = node => {
|
|
1525
|
+
if (includeNull)
|
|
1526
|
+
return this.isRealNodeOrNull(node);
|
|
1527
|
+
return this.isRealNode(node);
|
|
1528
|
+
}, shouldProcessRoot = node => true) {
|
|
1529
|
+
beginRoot = this.ensureNode(beginRoot);
|
|
1530
|
+
if (!beginRoot)
|
|
1531
|
+
return [];
|
|
1532
|
+
const ans = [];
|
|
1533
|
+
if (iterationType === 'RECURSIVE') {
|
|
1534
|
+
const dfs = (node) => {
|
|
1535
|
+
if (!shouldVisitRoot(node))
|
|
1536
|
+
return;
|
|
1537
|
+
const visitLeft = () => {
|
|
1538
|
+
if (shouldVisitLeft(node))
|
|
1539
|
+
dfs(node?.left);
|
|
1540
|
+
};
|
|
1541
|
+
const visitRight = () => {
|
|
1542
|
+
if (shouldVisitRight(node))
|
|
1543
|
+
dfs(node?.right);
|
|
1544
|
+
};
|
|
1545
|
+
switch (pattern) {
|
|
1546
|
+
case 'IN':
|
|
1547
|
+
visitLeft();
|
|
1548
|
+
if (shouldProcessRoot(node))
|
|
1549
|
+
ans.push(callback(node));
|
|
1550
|
+
visitRight();
|
|
1551
|
+
break;
|
|
1552
|
+
case 'PRE':
|
|
1553
|
+
if (shouldProcessRoot(node))
|
|
1554
|
+
ans.push(callback(node));
|
|
1555
|
+
visitLeft();
|
|
1556
|
+
visitRight();
|
|
1557
|
+
break;
|
|
1558
|
+
case 'POST':
|
|
1559
|
+
visitLeft();
|
|
1560
|
+
visitRight();
|
|
1561
|
+
if (shouldProcessRoot(node))
|
|
1562
|
+
ans.push(callback(node));
|
|
1563
|
+
break;
|
|
1564
|
+
}
|
|
1565
|
+
};
|
|
1566
|
+
dfs(beginRoot);
|
|
1567
|
+
}
|
|
1568
|
+
else {
|
|
1569
|
+
const stack = [{ opt: DFSOperation.VISIT, node: beginRoot }];
|
|
1570
|
+
const pushLeft = (cur) => {
|
|
1571
|
+
if (shouldVisitLeft(cur.node))
|
|
1572
|
+
stack.push({ opt: DFSOperation.VISIT, node: cur.node?.left });
|
|
1573
|
+
};
|
|
1574
|
+
const pushRight = (cur) => {
|
|
1575
|
+
if (shouldVisitRight(cur.node))
|
|
1576
|
+
stack.push({ opt: DFSOperation.VISIT, node: cur.node?.right });
|
|
1577
|
+
};
|
|
1578
|
+
const pushRoot = (cur) => {
|
|
1579
|
+
if (shouldVisitRoot(cur.node))
|
|
1580
|
+
stack.push({ opt: DFSOperation.PROCESS, node: cur.node });
|
|
1581
|
+
};
|
|
1582
|
+
while (stack.length > 0) {
|
|
1583
|
+
const cur = stack.pop();
|
|
1584
|
+
if (cur === undefined)
|
|
1585
|
+
continue;
|
|
1586
|
+
if (!shouldVisitRoot(cur.node))
|
|
1587
|
+
continue;
|
|
1588
|
+
if (cur.opt === DFSOperation.PROCESS) {
|
|
1589
|
+
if (shouldProcessRoot(cur.node))
|
|
1590
|
+
ans.push(callback(cur.node));
|
|
1591
|
+
}
|
|
1592
|
+
else {
|
|
1593
|
+
switch (pattern) {
|
|
1594
|
+
case 'IN':
|
|
1595
|
+
pushRight(cur);
|
|
1596
|
+
pushRoot(cur);
|
|
1597
|
+
pushLeft(cur);
|
|
1598
|
+
break;
|
|
1599
|
+
case 'PRE':
|
|
1600
|
+
pushRight(cur);
|
|
1601
|
+
pushLeft(cur);
|
|
1602
|
+
pushRoot(cur);
|
|
1603
|
+
break;
|
|
1604
|
+
case 'POST':
|
|
1605
|
+
pushRoot(cur);
|
|
1606
|
+
pushRight(cur);
|
|
1607
|
+
pushLeft(cur);
|
|
1608
|
+
break;
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
return ans;
|
|
1614
|
+
}
|
|
1629
1615
|
/**
|
|
1630
1616
|
* Time Complexity: O(1)
|
|
1631
1617
|
* Space Complexity: O(1)
|
|
@@ -1664,10 +1650,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1664
1650
|
}
|
|
1665
1651
|
}
|
|
1666
1652
|
}
|
|
1667
|
-
/**
|
|
1668
|
-
* Time Complexity: O(n)
|
|
1669
|
-
* Space Complexity: O(n)
|
|
1670
|
-
*/
|
|
1671
1653
|
/**
|
|
1672
1654
|
* Time Complexity: O(n)
|
|
1673
1655
|
* Space Complexity: O(n)
|
|
@@ -1738,10 +1720,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1738
1720
|
}
|
|
1739
1721
|
}
|
|
1740
1722
|
_DEFAULT_CALLBACK = (node) => (node ? node.key : undefined);
|
|
1741
|
-
/**
|
|
1742
|
-
* Time Complexity: O(1)
|
|
1743
|
-
* Space Complexity: O(1)
|
|
1744
|
-
*/
|
|
1745
1723
|
/**
|
|
1746
1724
|
* Time Complexity: O(1)
|
|
1747
1725
|
* Space Complexity: O(1)
|
|
@@ -1771,10 +1749,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1771
1749
|
}
|
|
1772
1750
|
return undefined;
|
|
1773
1751
|
}
|
|
1774
|
-
/**
|
|
1775
|
-
* Time Complexity: O(1)
|
|
1776
|
-
* Space Complexity: O(1)
|
|
1777
|
-
*/
|
|
1778
1752
|
/**
|
|
1779
1753
|
* Time Complexity: O(1)
|
|
1780
1754
|
* Space Complexity: O(1)
|
|
@@ -1804,10 +1778,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1804
1778
|
}
|
|
1805
1779
|
return newNode;
|
|
1806
1780
|
}
|
|
1807
|
-
/**
|
|
1808
|
-
* Time Complexity: O(1)
|
|
1809
|
-
* Space Complexity: O(1)
|
|
1810
|
-
*/
|
|
1811
1781
|
/**
|
|
1812
1782
|
* Time Complexity: O(1)
|
|
1813
1783
|
* Space Complexity: O(1)
|
|
@@ -1823,10 +1793,6 @@ export class BinaryTree extends IterableEntryBase {
|
|
|
1823
1793
|
}
|
|
1824
1794
|
this._root = v;
|
|
1825
1795
|
}
|
|
1826
|
-
/**
|
|
1827
|
-
* Time Complexity: O(1)
|
|
1828
|
-
* Space Complexity: O(1)
|
|
1829
|
-
*/
|
|
1830
1796
|
/**
|
|
1831
1797
|
* Time Complexity: O(1)
|
|
1832
1798
|
* Space Complexity: O(1)
|