min-heap-typed 1.50.1 → 1.50.3
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/base/iterable-base.d.ts +120 -9
- package/dist/data-structures/base/iterable-base.js +143 -7
- package/dist/data-structures/binary-tree/avl-tree.d.ts +72 -47
- package/dist/data-structures/binary-tree/avl-tree.js +101 -72
- package/dist/data-structures/binary-tree/binary-indexed-tree.d.ts +22 -0
- package/dist/data-structures/binary-tree/binary-indexed-tree.js +22 -0
- package/dist/data-structures/binary-tree/binary-tree.d.ts +244 -199
- package/dist/data-structures/binary-tree/binary-tree.js +484 -376
- package/dist/data-structures/binary-tree/bst.d.ts +92 -79
- package/dist/data-structures/binary-tree/bst.js +68 -76
- package/dist/data-structures/binary-tree/rb-tree.d.ts +127 -57
- package/dist/data-structures/binary-tree/rb-tree.js +152 -99
- package/dist/data-structures/binary-tree/segment-tree.d.ts +99 -6
- package/dist/data-structures/binary-tree/segment-tree.js +127 -10
- package/dist/data-structures/binary-tree/tree-multimap.d.ts +72 -58
- package/dist/data-structures/binary-tree/tree-multimap.js +102 -85
- package/dist/data-structures/graph/abstract-graph.d.ts +1 -78
- package/dist/data-structures/graph/abstract-graph.js +3 -189
- package/dist/data-structures/graph/directed-graph.d.ts +73 -0
- package/dist/data-structures/graph/directed-graph.js +131 -0
- package/dist/data-structures/graph/map-graph.d.ts +8 -0
- package/dist/data-structures/graph/map-graph.js +14 -0
- package/dist/data-structures/graph/undirected-graph.d.ts +76 -7
- package/dist/data-structures/graph/undirected-graph.js +151 -18
- package/dist/data-structures/hash/hash-map.d.ts +254 -28
- package/dist/data-structures/hash/hash-map.js +347 -78
- package/dist/data-structures/heap/heap.d.ts +95 -25
- package/dist/data-structures/heap/heap.js +95 -26
- package/dist/data-structures/linked-list/doubly-linked-list.d.ts +126 -63
- package/dist/data-structures/linked-list/doubly-linked-list.js +141 -77
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +154 -106
- package/dist/data-structures/linked-list/singly-linked-list.js +164 -115
- package/dist/data-structures/linked-list/skip-linked-list.d.ts +63 -36
- package/dist/data-structures/linked-list/skip-linked-list.js +63 -36
- package/dist/data-structures/matrix/matrix.d.ts +35 -4
- package/dist/data-structures/matrix/matrix.js +50 -11
- package/dist/data-structures/priority-queue/max-priority-queue.d.ts +10 -0
- package/dist/data-structures/priority-queue/max-priority-queue.js +10 -0
- package/dist/data-structures/priority-queue/min-priority-queue.d.ts +11 -0
- package/dist/data-structures/priority-queue/min-priority-queue.js +11 -0
- package/dist/data-structures/priority-queue/priority-queue.d.ts +8 -0
- package/dist/data-structures/priority-queue/priority-queue.js +8 -0
- package/dist/data-structures/queue/deque.d.ts +139 -35
- package/dist/data-structures/queue/deque.js +200 -62
- package/dist/data-structures/queue/queue.d.ts +103 -49
- package/dist/data-structures/queue/queue.js +111 -49
- package/dist/data-structures/stack/stack.d.ts +51 -21
- package/dist/data-structures/stack/stack.js +58 -22
- package/dist/data-structures/tree/tree.d.ts +57 -3
- package/dist/data-structures/tree/tree.js +77 -11
- package/dist/data-structures/trie/trie.d.ts +135 -34
- package/dist/data-structures/trie/trie.js +153 -33
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
- package/dist/types/data-structures/hash/hash-map.d.ts +4 -3
- package/dist/types/utils/utils.d.ts +1 -0
- package/package.json +2 -2
- package/src/data-structures/base/iterable-base.ts +184 -19
- package/src/data-structures/binary-tree/avl-tree.ts +134 -100
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +22 -0
- package/src/data-structures/binary-tree/binary-tree.ts +674 -671
- package/src/data-structures/binary-tree/bst.ts +127 -136
- package/src/data-structures/binary-tree/rb-tree.ts +199 -166
- package/src/data-structures/binary-tree/segment-tree.ts +145 -11
- package/src/data-structures/binary-tree/tree-multimap.ts +138 -115
- package/src/data-structures/graph/abstract-graph.ts +4 -211
- package/src/data-structures/graph/directed-graph.ts +152 -0
- package/src/data-structures/graph/map-graph.ts +15 -0
- package/src/data-structures/graph/undirected-graph.ts +171 -19
- package/src/data-structures/hash/hash-map.ts +389 -96
- package/src/data-structures/heap/heap.ts +97 -26
- package/src/data-structures/linked-list/doubly-linked-list.ts +156 -83
- package/src/data-structures/linked-list/singly-linked-list.ts +174 -120
- package/src/data-structures/linked-list/skip-linked-list.ts +63 -37
- package/src/data-structures/matrix/matrix.ts +52 -12
- package/src/data-structures/priority-queue/max-priority-queue.ts +10 -0
- package/src/data-structures/priority-queue/min-priority-queue.ts +11 -0
- package/src/data-structures/priority-queue/priority-queue.ts +8 -0
- package/src/data-structures/queue/deque.ts +225 -70
- package/src/data-structures/queue/queue.ts +118 -49
- package/src/data-structures/stack/stack.ts +63 -23
- package/src/data-structures/tree/tree.ts +89 -15
- package/src/data-structures/trie/trie.ts +173 -38
- package/src/types/data-structures/binary-tree/binary-tree.ts +1 -1
- package/src/types/data-structures/hash/hash-map.ts +4 -3
- package/src/types/utils/utils.ts +2 -0
|
@@ -28,46 +28,74 @@ import { IterableEntryBase } from '../base';
|
|
|
28
28
|
/**
|
|
29
29
|
* Represents a node in a binary tree.
|
|
30
30
|
* @template V - The type of data stored in the node.
|
|
31
|
-
* @template
|
|
31
|
+
* @template NODE - The type of the family relationship in the binary tree.
|
|
32
32
|
*/
|
|
33
33
|
export class BinaryTreeNode<
|
|
34
34
|
K = any,
|
|
35
35
|
V = any,
|
|
36
|
-
|
|
36
|
+
NODE extends BinaryTreeNode<K, V, NODE> = BinaryTreeNode<K, V, BinaryTreeNodeNested<K, V>>
|
|
37
37
|
> {
|
|
38
38
|
key: K;
|
|
39
39
|
|
|
40
40
|
value?: V;
|
|
41
41
|
|
|
42
|
-
parent?:
|
|
42
|
+
parent?: NODE;
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* The constructor function initializes an object with a key and an optional value.
|
|
46
|
+
* @param {K} key - The "key" parameter is of type K, which represents the type of the key for the
|
|
47
|
+
* constructor. It is used to set the key property of the object being created.
|
|
48
|
+
* @param {V} [value] - The "value" parameter is an optional parameter of type V. It represents the
|
|
49
|
+
* value associated with the key in the constructor.
|
|
50
|
+
*/
|
|
44
51
|
constructor(key: K, value?: V) {
|
|
45
52
|
this.key = key;
|
|
46
53
|
this.value = value;
|
|
47
54
|
}
|
|
48
55
|
|
|
49
|
-
protected _left?:
|
|
56
|
+
protected _left?: NODE | null;
|
|
50
57
|
|
|
51
|
-
|
|
58
|
+
/**
|
|
59
|
+
* The function returns the value of the `_left` property, which can be of type `NODE`, `null`, or
|
|
60
|
+
* `undefined`.
|
|
61
|
+
* @returns The left node of the current node is being returned. It can be either a NODE object,
|
|
62
|
+
* null, or undefined.
|
|
63
|
+
*/
|
|
64
|
+
get left(): NODE | null | undefined {
|
|
52
65
|
return this._left;
|
|
53
66
|
}
|
|
54
67
|
|
|
55
|
-
|
|
68
|
+
/**
|
|
69
|
+
* The function sets the left child of a node and updates its parent reference.
|
|
70
|
+
* @param {NODE | null | undefined} v - The parameter `v` can be of type `NODE`, `null`, or
|
|
71
|
+
* `undefined`.
|
|
72
|
+
*/
|
|
73
|
+
set left(v: NODE | null | undefined) {
|
|
56
74
|
if (v) {
|
|
57
|
-
v.parent = this as unknown as
|
|
75
|
+
v.parent = this as unknown as NODE;
|
|
58
76
|
}
|
|
59
77
|
this._left = v;
|
|
60
78
|
}
|
|
61
79
|
|
|
62
|
-
protected _right?:
|
|
80
|
+
protected _right?: NODE | null;
|
|
63
81
|
|
|
64
|
-
|
|
82
|
+
/**
|
|
83
|
+
* The function returns the right node of a binary tree or null if it doesn't exist.
|
|
84
|
+
* @returns The method is returning the value of the `_right` property, which can be a `NODE` object,
|
|
85
|
+
* `null`, or `undefined`.
|
|
86
|
+
*/
|
|
87
|
+
get right(): NODE | null | undefined {
|
|
65
88
|
return this._right;
|
|
66
89
|
}
|
|
67
90
|
|
|
68
|
-
|
|
91
|
+
/**
|
|
92
|
+
* The function sets the right child of a node and updates its parent.
|
|
93
|
+
* @param {NODE | null | undefined} v - The parameter `v` can be of type `NODE`, `null`, or
|
|
94
|
+
* `undefined`.
|
|
95
|
+
*/
|
|
96
|
+
set right(v: NODE | null | undefined) {
|
|
69
97
|
if (v) {
|
|
70
|
-
v.parent = this as unknown as
|
|
98
|
+
v.parent = this as unknown as NODE;
|
|
71
99
|
}
|
|
72
100
|
this._right = v;
|
|
73
101
|
}
|
|
@@ -77,7 +105,7 @@ export class BinaryTreeNode<
|
|
|
77
105
|
* @returns {FamilyPosition} - The family position of the node.
|
|
78
106
|
*/
|
|
79
107
|
get familyPosition(): FamilyPosition {
|
|
80
|
-
const that = this as unknown as
|
|
108
|
+
const that = this as unknown as NODE;
|
|
81
109
|
if (!this.parent) {
|
|
82
110
|
return this.left || this.right ? FamilyPosition.ROOT : FamilyPosition.ISOLATED;
|
|
83
111
|
}
|
|
@@ -103,11 +131,11 @@ export class BinaryTreeNode<
|
|
|
103
131
|
export class BinaryTree<
|
|
104
132
|
K = any,
|
|
105
133
|
V = any,
|
|
106
|
-
|
|
107
|
-
TREE extends BinaryTree<K, V,
|
|
134
|
+
NODE extends BinaryTreeNode<K, V, NODE> = BinaryTreeNode<K, V, BinaryTreeNodeNested<K, V>>,
|
|
135
|
+
TREE extends BinaryTree<K, V, NODE, TREE> = BinaryTree<K, V, NODE, BinaryTreeNested<K, V, NODE>>
|
|
108
136
|
>
|
|
109
137
|
extends IterableEntryBase<K, V | undefined>
|
|
110
|
-
implements IBinaryTree<K, V,
|
|
138
|
+
implements IBinaryTree<K, V, NODE, TREE> {
|
|
111
139
|
iterationType = IterationType.ITERATIVE;
|
|
112
140
|
|
|
113
141
|
/**
|
|
@@ -119,7 +147,7 @@ export class BinaryTree<
|
|
|
119
147
|
* `Partial<BinaryTreeOptions>`, which means that not all properties of `BinaryTreeOptions` are
|
|
120
148
|
* required.
|
|
121
149
|
*/
|
|
122
|
-
constructor(keysOrNodesOrEntries: Iterable<KeyOrNodeOrEntry<K, V,
|
|
150
|
+
constructor(keysOrNodesOrEntries: Iterable<KeyOrNodeOrEntry<K, V, NODE>> = [], options?: BinaryTreeOptions<K>) {
|
|
123
151
|
super();
|
|
124
152
|
if (options) {
|
|
125
153
|
const { iterationType, extractor } = options;
|
|
@@ -134,18 +162,31 @@ export class BinaryTree<
|
|
|
134
162
|
|
|
135
163
|
protected _extractor = (key: K) => Number(key);
|
|
136
164
|
|
|
165
|
+
/**
|
|
166
|
+
* The function returns the value of the `_extractor` property.
|
|
167
|
+
* @returns The `_extractor` property is being returned.
|
|
168
|
+
*/
|
|
137
169
|
get extractor() {
|
|
138
170
|
return this._extractor;
|
|
139
171
|
}
|
|
140
172
|
|
|
141
|
-
protected _root?:
|
|
173
|
+
protected _root?: NODE | null;
|
|
142
174
|
|
|
143
|
-
|
|
175
|
+
/**
|
|
176
|
+
* The function returns the root node, which can be of type NODE, null, or undefined.
|
|
177
|
+
* @returns The method is returning the value of the `_root` property, which can be of type `NODE`,
|
|
178
|
+
* `null`, or `undefined`.
|
|
179
|
+
*/
|
|
180
|
+
get root(): NODE | null | undefined {
|
|
144
181
|
return this._root;
|
|
145
182
|
}
|
|
146
183
|
|
|
147
184
|
protected _size: number;
|
|
148
185
|
|
|
186
|
+
/**
|
|
187
|
+
* The function returns the size of an object.
|
|
188
|
+
* @returns The size of the object, which is a number.
|
|
189
|
+
*/
|
|
149
190
|
get size(): number {
|
|
150
191
|
return this._size;
|
|
151
192
|
}
|
|
@@ -154,10 +195,10 @@ export class BinaryTree<
|
|
|
154
195
|
* Creates a new instance of BinaryTreeNode with the given key and value.
|
|
155
196
|
* @param {K} key - The key for the new node.
|
|
156
197
|
* @param {V} value - The value for the new node.
|
|
157
|
-
* @returns {
|
|
198
|
+
* @returns {NODE} - The newly created BinaryTreeNode.
|
|
158
199
|
*/
|
|
159
|
-
createNode(key: K, value?: V):
|
|
160
|
-
return new BinaryTreeNode<K, V,
|
|
200
|
+
createNode(key: K, value?: V): NODE {
|
|
201
|
+
return new BinaryTreeNode<K, V, NODE>(key, value) as NODE;
|
|
161
202
|
}
|
|
162
203
|
|
|
163
204
|
/**
|
|
@@ -168,21 +209,21 @@ export class BinaryTree<
|
|
|
168
209
|
* @returns a new instance of a binary tree.
|
|
169
210
|
*/
|
|
170
211
|
createTree(options?: Partial<BinaryTreeOptions<K>>): TREE {
|
|
171
|
-
return new BinaryTree<K, V,
|
|
212
|
+
return new BinaryTree<K, V, NODE, TREE>([], { iterationType: this.iterationType, ...options }) as TREE;
|
|
172
213
|
}
|
|
173
214
|
|
|
174
215
|
/**
|
|
175
|
-
* The function `
|
|
176
|
-
* @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter is of type `KeyOrNodeOrEntry<K, V,
|
|
216
|
+
* The function `keyValueOrEntryToNode` converts an keyOrNodeOrEntry object into a node object.
|
|
217
|
+
* @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter is of type `KeyOrNodeOrEntry<K, V, NODE>`.
|
|
177
218
|
* @param {V} [value] - The `value` parameter is an optional value that can be passed to the
|
|
178
|
-
* `
|
|
219
|
+
* `keyValueOrEntryToNode` function. It represents the value associated with the keyOrNodeOrEntry node. If no value
|
|
179
220
|
* is provided, it will be `undefined`.
|
|
180
|
-
* @returns a value of type
|
|
221
|
+
* @returns a value of type NODE (node), or null, or undefined.
|
|
181
222
|
*/
|
|
182
|
-
|
|
223
|
+
keyValueOrEntryToNode(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>, value?: V): NODE | null | undefined {
|
|
183
224
|
if (keyOrNodeOrEntry === undefined) return;
|
|
184
225
|
|
|
185
|
-
let node:
|
|
226
|
+
let node: NODE | null | undefined;
|
|
186
227
|
if (keyOrNodeOrEntry === null) {
|
|
187
228
|
node = null;
|
|
188
229
|
} else if (this.isEntry(keyOrNodeOrEntry)) {
|
|
@@ -215,7 +256,7 @@ export class BinaryTree<
|
|
|
215
256
|
*
|
|
216
257
|
* The function `ensureNode` returns the node corresponding to the given key if it is a valid node
|
|
217
258
|
* key, otherwise it returns the key itself.
|
|
218
|
-
* @param {K |
|
|
259
|
+
* @param {K | NODE | null | undefined} keyOrNodeOrEntry - The `key` parameter can be of type `K`, `NODE`,
|
|
219
260
|
* `null`, or `undefined`. It represents a key used to identify a node in a binary tree.
|
|
220
261
|
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
|
|
221
262
|
* type of iteration to be used when searching for a node by key. It has a default value of
|
|
@@ -224,10 +265,10 @@ export class BinaryTree<
|
|
|
224
265
|
* itself if it is not a valid node key.
|
|
225
266
|
*/
|
|
226
267
|
ensureNode(
|
|
227
|
-
keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V,
|
|
268
|
+
keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>,
|
|
228
269
|
iterationType = IterationType.ITERATIVE
|
|
229
|
-
):
|
|
230
|
-
let res:
|
|
270
|
+
): NODE | null | undefined {
|
|
271
|
+
let res: NODE | null | undefined;
|
|
231
272
|
if (this.isRealNode(keyOrNodeOrEntry)) {
|
|
232
273
|
res = keyOrNodeOrEntry;
|
|
233
274
|
} else if (this.isEntry(keyOrNodeOrEntry)) {
|
|
@@ -242,35 +283,30 @@ export class BinaryTree<
|
|
|
242
283
|
|
|
243
284
|
/**
|
|
244
285
|
* The function "isNode" checks if an keyOrNodeOrEntry is an instance of the BinaryTreeNode class.
|
|
245
|
-
* @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter is a variable of type `KeyOrNodeOrEntry<K, V,
|
|
246
|
-
* @returns a boolean value indicating whether the keyOrNodeOrEntry is an instance of the class
|
|
286
|
+
* @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter is a variable of type `KeyOrNodeOrEntry<K, V,NODE>`.
|
|
287
|
+
* @returns a boolean value indicating whether the keyOrNodeOrEntry is an instance of the class NODE.
|
|
247
288
|
*/
|
|
248
|
-
isNode(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V,
|
|
289
|
+
isNode(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>): keyOrNodeOrEntry is NODE {
|
|
249
290
|
return keyOrNodeOrEntry instanceof BinaryTreeNode;
|
|
250
291
|
}
|
|
251
292
|
|
|
252
293
|
/**
|
|
253
294
|
* The function checks if a given value is an entry in a binary tree node.
|
|
254
|
-
* @param keyOrNodeOrEntry - KeyOrNodeOrEntry<K, V,
|
|
255
|
-
* two type parameters V and
|
|
295
|
+
* @param keyOrNodeOrEntry - KeyOrNodeOrEntry<K, V,NODE> - A generic type representing a node in a binary tree. It has
|
|
296
|
+
* two type parameters V and NODE, representing the value and node type respectively.
|
|
256
297
|
* @returns a boolean value.
|
|
257
298
|
*/
|
|
258
|
-
isEntry(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V,
|
|
299
|
+
isEntry(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>): keyOrNodeOrEntry is BTNEntry<K, V> {
|
|
259
300
|
return Array.isArray(keyOrNodeOrEntry) && keyOrNodeOrEntry.length === 2;
|
|
260
301
|
}
|
|
261
302
|
|
|
262
|
-
/**
|
|
263
|
-
* Time complexity: O(n)
|
|
264
|
-
* Space complexity: O(log n)
|
|
265
|
-
*/
|
|
266
|
-
|
|
267
303
|
/**
|
|
268
304
|
* The function checks if a given node is a real node by verifying if it is an instance of
|
|
269
305
|
* BinaryTreeNode and its key is not NaN.
|
|
270
306
|
* @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
|
|
271
307
|
* @returns a boolean value.
|
|
272
308
|
*/
|
|
273
|
-
isRealNode(node: KeyOrNodeOrEntry<K, V,
|
|
309
|
+
isRealNode(node: KeyOrNodeOrEntry<K, V, NODE>): node is NODE {
|
|
274
310
|
return node instanceof BinaryTreeNode && String(node.key) !== 'NaN';
|
|
275
311
|
}
|
|
276
312
|
|
|
@@ -279,7 +315,7 @@ export class BinaryTree<
|
|
|
279
315
|
* @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
|
|
280
316
|
* @returns a boolean value.
|
|
281
317
|
*/
|
|
282
|
-
isNIL(node: KeyOrNodeOrEntry<K, V,
|
|
318
|
+
isNIL(node: KeyOrNodeOrEntry<K, V, NODE>) {
|
|
283
319
|
return node instanceof BinaryTreeNode && String(node.key) === 'NaN';
|
|
284
320
|
}
|
|
285
321
|
|
|
@@ -288,27 +324,27 @@ export class BinaryTree<
|
|
|
288
324
|
* @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
|
|
289
325
|
* @returns a boolean value.
|
|
290
326
|
*/
|
|
291
|
-
isNodeOrNull(node: KeyOrNodeOrEntry<K, V,
|
|
327
|
+
isNodeOrNull(node: KeyOrNodeOrEntry<K, V, NODE>): node is NODE | null {
|
|
292
328
|
return this.isRealNode(node) || node === null;
|
|
293
329
|
}
|
|
294
330
|
|
|
295
331
|
/**
|
|
296
|
-
* Time Complexity O(
|
|
332
|
+
* Time Complexity O(n)
|
|
297
333
|
* Space Complexity O(1)
|
|
298
334
|
*/
|
|
299
335
|
|
|
300
336
|
/**
|
|
301
|
-
* Time Complexity O(
|
|
337
|
+
* Time Complexity O(n)
|
|
302
338
|
* Space Complexity O(1)
|
|
303
339
|
*
|
|
304
340
|
* The `add` function adds a new node to a binary tree, either by creating a new node or replacing an
|
|
305
341
|
* existing node with the same key.
|
|
306
342
|
* @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter can be one of the following:
|
|
307
343
|
* @param {V} [value] - The value to be inserted into the binary tree.
|
|
308
|
-
* @returns The function `add` returns either a node (`
|
|
344
|
+
* @returns The function `add` returns either a node (`NODE`), `null`, or `undefined`.
|
|
309
345
|
*/
|
|
310
|
-
add(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V,
|
|
311
|
-
const newNode = this.
|
|
346
|
+
add(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>, value?: V): boolean {
|
|
347
|
+
const newNode = this.keyValueOrEntryToNode(keyOrNodeOrEntry, value);
|
|
312
348
|
if (newNode === undefined) return false;
|
|
313
349
|
|
|
314
350
|
// If the tree is empty, directly set the new node as the root node
|
|
@@ -318,8 +354,8 @@ export class BinaryTree<
|
|
|
318
354
|
return true;
|
|
319
355
|
}
|
|
320
356
|
|
|
321
|
-
const queue = new Queue<
|
|
322
|
-
let potentialParent:
|
|
357
|
+
const queue = new Queue<NODE>([this.root]);
|
|
358
|
+
let potentialParent: NODE | undefined; // Record the parent node of the potential insertion location
|
|
323
359
|
|
|
324
360
|
while (queue.size > 0) {
|
|
325
361
|
const cur = queue.shift();
|
|
@@ -361,22 +397,22 @@ export class BinaryTree<
|
|
|
361
397
|
}
|
|
362
398
|
|
|
363
399
|
/**
|
|
364
|
-
* Time Complexity: O(k
|
|
400
|
+
* Time Complexity: O(k * n)
|
|
365
401
|
* Space Complexity: O(1)
|
|
366
402
|
* 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.
|
|
367
403
|
*/
|
|
368
404
|
|
|
369
405
|
/**
|
|
370
|
-
* Time Complexity: O(k
|
|
406
|
+
* Time Complexity: O(k * n)
|
|
371
407
|
* Space Complexity: O(1)
|
|
372
408
|
*
|
|
373
409
|
* The `addMany` function takes in a collection of keysOrNodesOrEntries and an optional collection of values, and
|
|
374
410
|
* adds each node with its corresponding value to the data structure.
|
|
375
411
|
* @param keysOrNodesOrEntries - An iterable collection of KeyOrNodeOrEntry objects.
|
|
376
412
|
* @param [values] - An optional iterable of values that will be assigned to each node being added.
|
|
377
|
-
* @returns The function `addMany` returns an array of `
|
|
413
|
+
* @returns The function `addMany` returns an array of `NODE`, `null`, or `undefined` values.
|
|
378
414
|
*/
|
|
379
|
-
addMany(keysOrNodesOrEntries: Iterable<KeyOrNodeOrEntry<K, V,
|
|
415
|
+
addMany(keysOrNodesOrEntries: Iterable<KeyOrNodeOrEntry<K, V, NODE>>, values?: Iterable<V | undefined>): boolean[] {
|
|
380
416
|
// TODO not sure addMany not be run multi times
|
|
381
417
|
const inserted: boolean[] = [];
|
|
382
418
|
|
|
@@ -413,30 +449,32 @@ export class BinaryTree<
|
|
|
413
449
|
*
|
|
414
450
|
* The `refill` function clears the current data and adds new key-value pairs to the data structure.
|
|
415
451
|
* @param keysOrNodesOrEntries - An iterable containing keys, nodes, or entries. These can be of type
|
|
416
|
-
* KeyOrNodeOrEntry<K, V,
|
|
452
|
+
* KeyOrNodeOrEntry<K, V, NODE>.
|
|
417
453
|
* @param [values] - The `values` parameter is an optional iterable that contains the values to be
|
|
418
454
|
* associated with the keys or nodes or entries in the `keysOrNodesOrEntries` parameter. If provided,
|
|
419
455
|
* the values will be associated with the corresponding keys or nodes or entries in the
|
|
420
456
|
* `keysOrNodesOrEntries` iterable
|
|
421
457
|
*/
|
|
422
|
-
refill(keysOrNodesOrEntries: Iterable<KeyOrNodeOrEntry<K, V,
|
|
458
|
+
refill(keysOrNodesOrEntries: Iterable<KeyOrNodeOrEntry<K, V, NODE>>, values?: Iterable<V | undefined>): void {
|
|
423
459
|
this.clear();
|
|
424
460
|
this.addMany(keysOrNodesOrEntries, values);
|
|
425
461
|
}
|
|
426
462
|
|
|
427
|
-
|
|
428
|
-
* Time Complexity: O(k * n)
|
|
429
|
-
* Space Complexity: O(1)
|
|
430
|
-
* "n" is the number of nodes in the tree, and "k" is the number of keys to be inserted.
|
|
431
|
-
*/
|
|
432
|
-
|
|
433
|
-
delete<C extends BTNCallback<N, K>>(identifier: K, callback?: C): BinaryTreeDeleteResult<N>[];
|
|
463
|
+
delete<C extends BTNCallback<NODE, K>>(identifier: K, callback?: C): BinaryTreeDeleteResult<NODE>[];
|
|
434
464
|
|
|
435
|
-
delete<C extends BTNCallback<
|
|
465
|
+
delete<C extends BTNCallback<NODE, NODE>>(
|
|
466
|
+
identifier: NODE | null | undefined,
|
|
467
|
+
callback?: C
|
|
468
|
+
): BinaryTreeDeleteResult<NODE>[];
|
|
436
469
|
|
|
437
|
-
delete<C extends BTNCallback<
|
|
470
|
+
delete<C extends BTNCallback<NODE>>(identifier: ReturnType<C>, callback: C): BinaryTreeDeleteResult<NODE>[];
|
|
438
471
|
|
|
439
472
|
/**
|
|
473
|
+
* Time Complexity: O(n)
|
|
474
|
+
* Space Complexity: O(1)
|
|
475
|
+
* /
|
|
476
|
+
|
|
477
|
+
/**
|
|
440
478
|
* Time Complexity: O(n)
|
|
441
479
|
* Space Complexity: O(1)
|
|
442
480
|
*
|
|
@@ -449,13 +487,13 @@ export class BinaryTree<
|
|
|
449
487
|
* @param {C} callback - The `callback` parameter is a function that is used to determine the
|
|
450
488
|
* identifier of the node to be deleted. It is optional and has a default value of
|
|
451
489
|
* `this._defaultOneParamCallback`. The `callback` function should return the identifier of the node.
|
|
452
|
-
* @returns an array of `BinaryTreeDeleteResult<
|
|
490
|
+
* @returns an array of `BinaryTreeDeleteResult<NODE>`.
|
|
453
491
|
*/
|
|
454
|
-
delete<C extends BTNCallback<
|
|
492
|
+
delete<C extends BTNCallback<NODE>>(
|
|
455
493
|
identifier: ReturnType<C> | null | undefined,
|
|
456
494
|
callback: C = this._defaultOneParamCallback as C
|
|
457
|
-
): BinaryTreeDeleteResult<
|
|
458
|
-
const deletedResult: BinaryTreeDeleteResult<
|
|
495
|
+
): BinaryTreeDeleteResult<NODE>[] {
|
|
496
|
+
const deletedResult: BinaryTreeDeleteResult<NODE>[] = [];
|
|
459
497
|
if (!this.root) return deletedResult;
|
|
460
498
|
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
461
499
|
callback = (node => node) as C;
|
|
@@ -463,240 +501,75 @@ export class BinaryTree<
|
|
|
463
501
|
const curr = this.getNode(identifier, callback);
|
|
464
502
|
if (!curr) return deletedResult;
|
|
465
503
|
|
|
466
|
-
const parent:
|
|
467
|
-
let needBalanced:
|
|
468
|
-
let orgCurrent:
|
|
469
|
-
|
|
470
|
-
if (!curr.left) {
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
504
|
+
const parent: NODE | undefined = curr?.parent;
|
|
505
|
+
let needBalanced: NODE | undefined;
|
|
506
|
+
let orgCurrent: NODE | undefined = curr;
|
|
507
|
+
|
|
508
|
+
if (!curr.left && !curr.right && !parent) {
|
|
509
|
+
this._setRoot(undefined);
|
|
510
|
+
} else if (curr.left) {
|
|
511
|
+
const leftSubTreeRightMost = this.getRightMost(curr.left);
|
|
512
|
+
if (leftSubTreeRightMost) {
|
|
513
|
+
const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
|
|
514
|
+
orgCurrent = this._swapProperties(curr, leftSubTreeRightMost);
|
|
515
|
+
if (parentOfLeftSubTreeMax) {
|
|
516
|
+
if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost)
|
|
517
|
+
parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
|
|
518
|
+
else parentOfLeftSubTreeMax.left = leftSubTreeRightMost.left;
|
|
519
|
+
needBalanced = parentOfLeftSubTreeMax;
|
|
480
520
|
}
|
|
481
|
-
needBalanced = parent;
|
|
482
521
|
}
|
|
483
|
-
} else {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
if (parentOfLeftSubTreeMax) {
|
|
490
|
-
if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost)
|
|
491
|
-
parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
|
|
492
|
-
else parentOfLeftSubTreeMax.left = leftSubTreeRightMost.left;
|
|
493
|
-
needBalanced = parentOfLeftSubTreeMax;
|
|
494
|
-
}
|
|
495
|
-
}
|
|
522
|
+
} else if (parent) {
|
|
523
|
+
const { familyPosition: fp } = curr;
|
|
524
|
+
if (fp === FamilyPosition.LEFT || fp === FamilyPosition.ROOT_LEFT) {
|
|
525
|
+
parent.left = curr.right;
|
|
526
|
+
} else if (fp === FamilyPosition.RIGHT || fp === FamilyPosition.ROOT_RIGHT) {
|
|
527
|
+
parent.right = curr.right;
|
|
496
528
|
}
|
|
529
|
+
needBalanced = parent;
|
|
530
|
+
} else {
|
|
531
|
+
this._setRoot(curr.right);
|
|
532
|
+
curr.right = undefined;
|
|
497
533
|
}
|
|
534
|
+
|
|
498
535
|
this._size = this.size - 1;
|
|
499
536
|
|
|
500
537
|
deletedResult.push({ deleted: orgCurrent, needBalanced });
|
|
501
538
|
return deletedResult;
|
|
502
539
|
}
|
|
503
540
|
|
|
504
|
-
|
|
505
|
-
* Time Complexity: O(n)
|
|
506
|
-
* Space Complexity: O(1)
|
|
507
|
-
*/
|
|
508
|
-
|
|
509
|
-
/**
|
|
510
|
-
* Time Complexity: O(n)
|
|
511
|
-
* Space Complexity: O(1)
|
|
512
|
-
*
|
|
513
|
-
* The function calculates the depth of a given node in a binary tree.
|
|
514
|
-
* @param {K | N | null | undefined} dist - The `dist` parameter represents the node in
|
|
515
|
-
* the binary tree whose depth we want to find. It can be of type `K`, `N`, `null`, or
|
|
516
|
-
* `undefined`.
|
|
517
|
-
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node
|
|
518
|
-
* from which we want to calculate the depth. It can be either a `K` (binary tree node key) or
|
|
519
|
-
* `N` (binary tree node) or `null` or `undefined`. If no value is provided for `beginRoot
|
|
520
|
-
* @returns the depth of the `dist` relative to the `beginRoot`.
|
|
521
|
-
*/
|
|
522
|
-
getDepth(dist: KeyOrNodeOrEntry<K, V, N>, beginRoot: KeyOrNodeOrEntry<K, V, N> = this.root): number {
|
|
523
|
-
dist = this.ensureNode(dist);
|
|
524
|
-
beginRoot = this.ensureNode(beginRoot);
|
|
525
|
-
let depth = 0;
|
|
526
|
-
while (dist?.parent) {
|
|
527
|
-
if (dist === beginRoot) {
|
|
528
|
-
return depth;
|
|
529
|
-
}
|
|
530
|
-
depth++;
|
|
531
|
-
dist = dist.parent;
|
|
532
|
-
}
|
|
533
|
-
return depth;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
/**
|
|
537
|
-
* Time Complexity: O(n)
|
|
538
|
-
* Space Complexity: O(1)
|
|
539
|
-
*/
|
|
540
|
-
|
|
541
|
-
/**
|
|
542
|
-
* Time Complexity: O(n)
|
|
543
|
-
* Space Complexity: O(log n)
|
|
544
|
-
*
|
|
545
|
-
* The function `getHeight` calculates the maximum height of a binary tree using either recursive or
|
|
546
|
-
* iterative traversal.
|
|
547
|
-
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
548
|
-
* starting node of the binary tree from which we want to calculate the height. It can be of type
|
|
549
|
-
* `K`, `N`, `null`, or `undefined`. If not provided, it defaults to `this.root`.
|
|
550
|
-
* @param iterationType - The `iterationType` parameter is used to determine whether to calculate the
|
|
551
|
-
* height of the tree using a recursive approach or an iterative approach. It can have two possible
|
|
552
|
-
* values:
|
|
553
|
-
* @returns the height of the binary tree.
|
|
554
|
-
*/
|
|
555
|
-
getHeight(beginRoot: KeyOrNodeOrEntry<K, V, N> = this.root, iterationType = this.iterationType): number {
|
|
556
|
-
beginRoot = this.ensureNode(beginRoot);
|
|
557
|
-
if (!beginRoot) return -1;
|
|
558
|
-
|
|
559
|
-
if (iterationType === IterationType.RECURSIVE) {
|
|
560
|
-
const _getMaxHeight = (cur: N | null | undefined): number => {
|
|
561
|
-
if (!cur) return -1;
|
|
562
|
-
const leftHeight = _getMaxHeight(cur.left);
|
|
563
|
-
const rightHeight = _getMaxHeight(cur.right);
|
|
564
|
-
return Math.max(leftHeight, rightHeight) + 1;
|
|
565
|
-
};
|
|
566
|
-
|
|
567
|
-
return _getMaxHeight(beginRoot);
|
|
568
|
-
} else {
|
|
569
|
-
const stack: { node: N; depth: number }[] = [{ node: beginRoot, depth: 0 }];
|
|
570
|
-
let maxHeight = 0;
|
|
571
|
-
|
|
572
|
-
while (stack.length > 0) {
|
|
573
|
-
const { node, depth } = stack.pop()!;
|
|
574
|
-
|
|
575
|
-
if (node.left) stack.push({ node: node.left, depth: depth + 1 });
|
|
576
|
-
if (node.right) stack.push({ node: node.right, depth: depth + 1 });
|
|
577
|
-
|
|
578
|
-
maxHeight = Math.max(maxHeight, depth);
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
return maxHeight;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
/**
|
|
586
|
-
* Time Complexity: O(n)
|
|
587
|
-
* Space Complexity: O(log n)
|
|
588
|
-
* Best Case - O(log n) (when using recursive iterationType), Worst Case - O(n) (when using iterative iterationType)
|
|
589
|
-
*/
|
|
590
|
-
|
|
591
|
-
/**
|
|
592
|
-
* Time Complexity: O(n)
|
|
593
|
-
* Space Complexity: O(log n)
|
|
594
|
-
*
|
|
595
|
-
* The `getMinHeight` function calculates the minimum height of a binary tree using either a
|
|
596
|
-
* recursive or iterative approach.
|
|
597
|
-
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
598
|
-
* starting node of the binary tree from which we want to calculate the minimum height. It can be of
|
|
599
|
-
* type `K`, `N`, `null`, or `undefined`. If no value is provided, it defaults to `this.root`.
|
|
600
|
-
* @param iterationType - The `iterationType` parameter is used to determine the method of iteration
|
|
601
|
-
* to calculate the minimum height of a binary tree. It can have two possible values:
|
|
602
|
-
* @returns The function `getMinHeight` returns the minimum height of a binary tree.
|
|
603
|
-
*/
|
|
604
|
-
getMinHeight(beginRoot: KeyOrNodeOrEntry<K, V, N> = this.root, iterationType = this.iterationType): number {
|
|
605
|
-
beginRoot = this.ensureNode(beginRoot);
|
|
606
|
-
if (!beginRoot) return -1;
|
|
607
|
-
|
|
608
|
-
if (iterationType === IterationType.RECURSIVE) {
|
|
609
|
-
const _getMinHeight = (cur: N | null | undefined): number => {
|
|
610
|
-
if (!cur) return 0;
|
|
611
|
-
if (!cur.left && !cur.right) return 0;
|
|
612
|
-
const leftMinHeight = _getMinHeight(cur.left);
|
|
613
|
-
const rightMinHeight = _getMinHeight(cur.right);
|
|
614
|
-
return Math.min(leftMinHeight, rightMinHeight) + 1;
|
|
615
|
-
};
|
|
616
|
-
|
|
617
|
-
return _getMinHeight(beginRoot);
|
|
618
|
-
} else {
|
|
619
|
-
const stack: N[] = [];
|
|
620
|
-
let node: N | null | undefined = beginRoot,
|
|
621
|
-
last: N | null | undefined = null;
|
|
622
|
-
const depths: Map<N, number> = new Map();
|
|
623
|
-
|
|
624
|
-
while (stack.length > 0 || node) {
|
|
625
|
-
if (node) {
|
|
626
|
-
stack.push(node);
|
|
627
|
-
node = node.left;
|
|
628
|
-
} else {
|
|
629
|
-
node = stack[stack.length - 1];
|
|
630
|
-
if (!node.right || last === node.right) {
|
|
631
|
-
node = stack.pop();
|
|
632
|
-
if (node) {
|
|
633
|
-
const leftMinHeight = node.left ? depths.get(node.left) ?? -1 : -1;
|
|
634
|
-
const rightMinHeight = node.right ? depths.get(node.right) ?? -1 : -1;
|
|
635
|
-
depths.set(node, 1 + Math.min(leftMinHeight, rightMinHeight));
|
|
636
|
-
last = node;
|
|
637
|
-
node = null;
|
|
638
|
-
}
|
|
639
|
-
} else node = node.right;
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
return depths.get(beginRoot) ?? -1;
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
/**
|
|
648
|
-
* Time Complexity: O(n)
|
|
649
|
-
* Space Complexity: O(log n)
|
|
650
|
-
* Best Case - O(log n) (when using recursive iterationType), Worst Case - O(n) (when using iterative iterationType)
|
|
651
|
-
*/
|
|
652
|
-
|
|
653
|
-
/**
|
|
654
|
-
* Time Complexity: O(n)
|
|
655
|
-
* Space Complexity: O(log n)
|
|
656
|
-
*
|
|
657
|
-
* The function checks if a binary tree is perfectly balanced by comparing the minimum height and the
|
|
658
|
-
* height of the tree.
|
|
659
|
-
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
|
|
660
|
-
* for calculating the height and minimum height of a binary tree. It can be either a `K` (a key
|
|
661
|
-
* value of a binary tree node), `N` (a node of a binary tree), `null`, or `undefined`. If
|
|
662
|
-
* @returns a boolean value.
|
|
663
|
-
*/
|
|
664
|
-
isPerfectlyBalanced(beginRoot: KeyOrNodeOrEntry<K, V, N> = this.root): boolean {
|
|
665
|
-
return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
/**
|
|
669
|
-
* Time Complexity: O(n)
|
|
670
|
-
* Space Complexity: O(log n)
|
|
671
|
-
*/
|
|
672
|
-
|
|
673
|
-
getNodes<C extends BTNCallback<N, K>>(
|
|
541
|
+
getNodes<C extends BTNCallback<NODE, K>>(
|
|
674
542
|
identifier: K,
|
|
675
543
|
callback?: C,
|
|
676
544
|
onlyOne?: boolean,
|
|
677
|
-
beginRoot?: KeyOrNodeOrEntry<K, V,
|
|
545
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
678
546
|
iterationType?: IterationType
|
|
679
|
-
):
|
|
547
|
+
): NODE[];
|
|
680
548
|
|
|
681
|
-
getNodes<C extends BTNCallback<
|
|
682
|
-
identifier:
|
|
549
|
+
getNodes<C extends BTNCallback<NODE, NODE>>(
|
|
550
|
+
identifier: NODE | null | undefined,
|
|
683
551
|
callback?: C,
|
|
684
552
|
onlyOne?: boolean,
|
|
685
|
-
beginRoot?: KeyOrNodeOrEntry<K, V,
|
|
553
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
686
554
|
iterationType?: IterationType
|
|
687
|
-
):
|
|
555
|
+
): NODE[];
|
|
688
556
|
|
|
689
|
-
getNodes<C extends BTNCallback<
|
|
557
|
+
getNodes<C extends BTNCallback<NODE>>(
|
|
690
558
|
identifier: ReturnType<C>,
|
|
691
559
|
callback: C,
|
|
692
560
|
onlyOne?: boolean,
|
|
693
|
-
beginRoot?: KeyOrNodeOrEntry<K, V,
|
|
561
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
694
562
|
iterationType?: IterationType
|
|
695
|
-
):
|
|
563
|
+
): NODE[];
|
|
696
564
|
|
|
697
565
|
/**
|
|
698
566
|
* Time Complexity: O(n)
|
|
699
|
-
* Space Complexity: O(log n)
|
|
567
|
+
* Space Complexity: O(k + log n)
|
|
568
|
+
*/
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* Time Complexity: O(n)
|
|
572
|
+
* Space Complexity: O(k + log n).
|
|
700
573
|
*
|
|
701
574
|
* The function `getNodes` retrieves nodes from a binary tree based on a given identifier and
|
|
702
575
|
* callback function.
|
|
@@ -704,7 +577,7 @@ export class BinaryTree<
|
|
|
704
577
|
* that you want to search for in the binary tree. It can be of any type that is returned by the
|
|
705
578
|
* callback function `C`. It can also be `null` or `undefined` if you don't want to search for a
|
|
706
579
|
* specific value.
|
|
707
|
-
* @param {C} callback - The `callback` parameter is a function that takes a node of type `
|
|
580
|
+
* @param {C} callback - The `callback` parameter is a function that takes a node of type `NODE` as
|
|
708
581
|
* input and returns a value of type `C`. It is used to determine if a node matches the given
|
|
709
582
|
* identifier. If no callback is provided, the `_defaultOneParamCallback` function is used as the
|
|
710
583
|
* default
|
|
@@ -712,29 +585,29 @@ export class BinaryTree<
|
|
|
712
585
|
* matches the identifier. If set to true, the function will stop iterating once it finds a matching
|
|
713
586
|
* node and return that node. If set to false (default), the function will continue iterating and
|
|
714
587
|
* return all nodes that match the identifier.
|
|
715
|
-
* @param {K |
|
|
588
|
+
* @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
716
589
|
* starting node for the traversal. It can be either a key, a node object, or `null`/`undefined`. If
|
|
717
590
|
* it is `null` or `undefined`, an empty array will be returned.
|
|
718
591
|
* @param iterationType - The `iterationType` parameter determines the type of iteration used to
|
|
719
592
|
* traverse the binary tree. It can have two possible values:
|
|
720
|
-
* @returns an array of nodes of type `
|
|
593
|
+
* @returns an array of nodes of type `NODE`.
|
|
721
594
|
*/
|
|
722
|
-
getNodes<C extends BTNCallback<
|
|
595
|
+
getNodes<C extends BTNCallback<NODE>>(
|
|
723
596
|
identifier: ReturnType<C> | null | undefined,
|
|
724
597
|
callback: C = this._defaultOneParamCallback as C,
|
|
725
598
|
onlyOne = false,
|
|
726
|
-
beginRoot: KeyOrNodeOrEntry<K, V,
|
|
599
|
+
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
727
600
|
iterationType = this.iterationType
|
|
728
|
-
):
|
|
601
|
+
): NODE[] {
|
|
729
602
|
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
730
603
|
callback = (node => node) as C;
|
|
731
604
|
beginRoot = this.ensureNode(beginRoot);
|
|
732
605
|
if (!beginRoot) return [];
|
|
733
606
|
|
|
734
|
-
const ans:
|
|
607
|
+
const ans: NODE[] = [];
|
|
735
608
|
|
|
736
609
|
if (iterationType === IterationType.RECURSIVE) {
|
|
737
|
-
const _traverse = (cur:
|
|
610
|
+
const _traverse = (cur: NODE) => {
|
|
738
611
|
if (callback(cur) === identifier) {
|
|
739
612
|
ans.push(cur);
|
|
740
613
|
if (onlyOne) return;
|
|
@@ -746,7 +619,7 @@ export class BinaryTree<
|
|
|
746
619
|
|
|
747
620
|
_traverse(beginRoot);
|
|
748
621
|
} else {
|
|
749
|
-
const queue = new Queue<
|
|
622
|
+
const queue = new Queue<NODE>([beginRoot]);
|
|
750
623
|
while (queue.size > 0) {
|
|
751
624
|
const cur = queue.shift();
|
|
752
625
|
if (cur) {
|
|
@@ -763,91 +636,32 @@ export class BinaryTree<
|
|
|
763
636
|
return ans;
|
|
764
637
|
}
|
|
765
638
|
|
|
766
|
-
|
|
767
|
-
* Time Complexity: O(n)
|
|
768
|
-
* Space Complexity: O(log n).
|
|
769
|
-
*/
|
|
770
|
-
|
|
771
|
-
has<C extends BTNCallback<N, K>>(
|
|
639
|
+
getNode<C extends BTNCallback<NODE, K>>(
|
|
772
640
|
identifier: K,
|
|
773
641
|
callback?: C,
|
|
774
|
-
beginRoot?: KeyOrNodeOrEntry<K, V,
|
|
642
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
775
643
|
iterationType?: IterationType
|
|
776
|
-
):
|
|
644
|
+
): NODE | null | undefined;
|
|
777
645
|
|
|
778
|
-
|
|
779
|
-
identifier:
|
|
646
|
+
getNode<C extends BTNCallback<NODE, NODE>>(
|
|
647
|
+
identifier: NODE | null | undefined,
|
|
780
648
|
callback?: C,
|
|
781
|
-
beginRoot?: KeyOrNodeOrEntry<K, V,
|
|
649
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
782
650
|
iterationType?: IterationType
|
|
783
|
-
):
|
|
651
|
+
): NODE | null | undefined;
|
|
784
652
|
|
|
785
|
-
|
|
786
|
-
identifier: ReturnType<C
|
|
653
|
+
getNode<C extends BTNCallback<NODE>>(
|
|
654
|
+
identifier: ReturnType<C>,
|
|
787
655
|
callback: C,
|
|
788
|
-
beginRoot?: KeyOrNodeOrEntry<K, V,
|
|
656
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
789
657
|
iterationType?: IterationType
|
|
790
|
-
):
|
|
791
|
-
|
|
792
|
-
/**
|
|
793
|
-
* Time Complexity: O(n)
|
|
794
|
-
* Space Complexity: O(log n).
|
|
795
|
-
*
|
|
796
|
-
* The function checks if a Binary Tree Node with a specific identifier exists in the tree.
|
|
797
|
-
* @param {ReturnType<C> | null | undefined} identifier - The `identifier` parameter is the value
|
|
798
|
-
* that you want to search for in the binary tree. It can be of any type that is returned by the
|
|
799
|
-
* callback function `C`. It can also be `null` or `undefined` if you don't want to specify a
|
|
800
|
-
* specific identifier.
|
|
801
|
-
* @param {C} callback - The `callback` parameter is a function that will be called for each node in
|
|
802
|
-
* the binary tree. It is used to filter the nodes based on certain conditions. The `callback`
|
|
803
|
-
* function should return a boolean value indicating whether the node should be included in the
|
|
804
|
-
* result or not.
|
|
805
|
-
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
|
|
806
|
-
* for the search in the binary tree. It can be specified as a `K` (a unique identifier for a
|
|
807
|
-
* node in the binary tree), a node object (`N`), or `null`/`undefined` to start the search from
|
|
808
|
-
* @param iterationType - The `iterationType` parameter is a variable that determines the type of
|
|
809
|
-
* iteration to be performed on the binary tree. It is used to specify whether the iteration should
|
|
810
|
-
* be performed in a pre-order, in-order, or post-order manner.
|
|
811
|
-
* @returns a boolean value.
|
|
812
|
-
*/
|
|
813
|
-
has<C extends BTNCallback<N>>(
|
|
814
|
-
identifier: ReturnType<C> | null | undefined,
|
|
815
|
-
callback: C = this._defaultOneParamCallback as C,
|
|
816
|
-
beginRoot: KeyOrNodeOrEntry<K, V, N> = this.root,
|
|
817
|
-
iterationType = this.iterationType
|
|
818
|
-
): boolean {
|
|
819
|
-
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
820
|
-
callback = (node => node) as C;
|
|
821
|
-
|
|
822
|
-
return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0;
|
|
823
|
-
}
|
|
658
|
+
): NODE | null | undefined;
|
|
824
659
|
|
|
825
660
|
/**
|
|
826
661
|
* Time Complexity: O(n)
|
|
827
662
|
* Space Complexity: O(log n).
|
|
828
663
|
*/
|
|
829
664
|
|
|
830
|
-
getNode<C extends BTNCallback<N, K>>(
|
|
831
|
-
identifier: K,
|
|
832
|
-
callback?: C,
|
|
833
|
-
beginRoot?: KeyOrNodeOrEntry<K, V, N>,
|
|
834
|
-
iterationType?: IterationType
|
|
835
|
-
): N | null | undefined;
|
|
836
|
-
|
|
837
|
-
getNode<C extends BTNCallback<N, N>>(
|
|
838
|
-
identifier: N | null | undefined,
|
|
839
|
-
callback?: C,
|
|
840
|
-
beginRoot?: KeyOrNodeOrEntry<K, V, N>,
|
|
841
|
-
iterationType?: IterationType
|
|
842
|
-
): N | null | undefined;
|
|
843
|
-
|
|
844
|
-
getNode<C extends BTNCallback<N>>(
|
|
845
|
-
identifier: ReturnType<C>,
|
|
846
|
-
callback: C,
|
|
847
|
-
beginRoot?: KeyOrNodeOrEntry<K, V, N>,
|
|
848
|
-
iterationType?: IterationType
|
|
849
|
-
): N | null | undefined;
|
|
850
|
-
|
|
851
665
|
/**
|
|
852
666
|
* Time Complexity: O(n)
|
|
853
667
|
* Space Complexity: O(log n)
|
|
@@ -860,21 +674,21 @@ export class BinaryTree<
|
|
|
860
674
|
* identifier.
|
|
861
675
|
* @param {C} callback - The `callback` parameter is a function that will be called for each node in
|
|
862
676
|
* the binary tree. It is used to determine if a node matches the given identifier. The `callback`
|
|
863
|
-
* function should take a single parameter of type `
|
|
864
|
-
* @param {K |
|
|
677
|
+
* function should take a single parameter of type `NODE` (the type of the nodes in the binary tree) and
|
|
678
|
+
* @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
|
|
865
679
|
* for searching the binary tree. It can be either a key value, a node object, or `null`/`undefined`.
|
|
866
680
|
* If `null` or `undefined` is passed, the search will start from the root of the binary tree.
|
|
867
681
|
* @param iterationType - The `iterationType` parameter is used to specify the type of iteration to
|
|
868
682
|
* be performed when searching for nodes in the binary tree. It determines the order in which the
|
|
869
683
|
* nodes are visited during the search.
|
|
870
|
-
* @returns a value of type `
|
|
684
|
+
* @returns a value of type `NODE | null | undefined`.
|
|
871
685
|
*/
|
|
872
|
-
getNode<C extends BTNCallback<
|
|
686
|
+
getNode<C extends BTNCallback<NODE>>(
|
|
873
687
|
identifier: ReturnType<C> | null | undefined,
|
|
874
688
|
callback: C = this._defaultOneParamCallback as C,
|
|
875
|
-
beginRoot: KeyOrNodeOrEntry<K, V,
|
|
689
|
+
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
876
690
|
iterationType = this.iterationType
|
|
877
|
-
):
|
|
691
|
+
): NODE | null | undefined {
|
|
878
692
|
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
879
693
|
callback = (node => node) as C;
|
|
880
694
|
|
|
@@ -897,13 +711,13 @@ export class BinaryTree<
|
|
|
897
711
|
* @param iterationType - The `iterationType` parameter is used to determine whether the search for
|
|
898
712
|
* the node with the given key should be performed iteratively or recursively. It has two possible
|
|
899
713
|
* values:
|
|
900
|
-
* @returns The function `getNodeByKey` returns a node (`
|
|
714
|
+
* @returns The function `getNodeByKey` returns a node (`NODE`) if a node with the specified key is
|
|
901
715
|
* found in the binary tree. If no node is found, it returns `undefined`.
|
|
902
716
|
*/
|
|
903
|
-
getNodeByKey(key: K, iterationType = IterationType.ITERATIVE):
|
|
717
|
+
getNodeByKey(key: K, iterationType = IterationType.ITERATIVE): NODE | undefined {
|
|
904
718
|
if (!this.root) return undefined;
|
|
905
719
|
if (iterationType === IterationType.RECURSIVE) {
|
|
906
|
-
const _dfs = (cur:
|
|
720
|
+
const _dfs = (cur: NODE): NODE | undefined => {
|
|
907
721
|
if (cur.key === key) return cur;
|
|
908
722
|
|
|
909
723
|
if (!cur.left && !cur.right) return;
|
|
@@ -913,7 +727,7 @@ export class BinaryTree<
|
|
|
913
727
|
|
|
914
728
|
return _dfs(this.root);
|
|
915
729
|
} else {
|
|
916
|
-
const queue = new Queue<
|
|
730
|
+
const queue = new Queue<NODE>([this.root]);
|
|
917
731
|
while (queue.size > 0) {
|
|
918
732
|
const cur = queue.shift();
|
|
919
733
|
if (cur) {
|
|
@@ -925,27 +739,32 @@ export class BinaryTree<
|
|
|
925
739
|
}
|
|
926
740
|
}
|
|
927
741
|
|
|
928
|
-
get<C extends BTNCallback<
|
|
742
|
+
override get<C extends BTNCallback<NODE, K>>(
|
|
929
743
|
identifier: K,
|
|
930
744
|
callback?: C,
|
|
931
|
-
beginRoot?: KeyOrNodeOrEntry<K, V,
|
|
745
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
932
746
|
iterationType?: IterationType
|
|
933
747
|
): V | undefined;
|
|
934
748
|
|
|
935
|
-
get<C extends BTNCallback<
|
|
936
|
-
identifier:
|
|
749
|
+
override get<C extends BTNCallback<NODE, NODE>>(
|
|
750
|
+
identifier: NODE | null | undefined,
|
|
937
751
|
callback?: C,
|
|
938
|
-
beginRoot?: KeyOrNodeOrEntry<K, V,
|
|
752
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
939
753
|
iterationType?: IterationType
|
|
940
754
|
): V | undefined;
|
|
941
755
|
|
|
942
|
-
get<C extends BTNCallback<
|
|
756
|
+
override get<C extends BTNCallback<NODE>>(
|
|
943
757
|
identifier: ReturnType<C>,
|
|
944
758
|
callback: C,
|
|
945
|
-
beginRoot?: KeyOrNodeOrEntry<K, V,
|
|
759
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
946
760
|
iterationType?: IterationType
|
|
947
761
|
): V | undefined;
|
|
948
762
|
|
|
763
|
+
/**
|
|
764
|
+
* Time Complexity: O(n)
|
|
765
|
+
* Space Complexity: O(log n)
|
|
766
|
+
*/
|
|
767
|
+
|
|
949
768
|
/**
|
|
950
769
|
* Time Complexity: O(n)
|
|
951
770
|
* Space Complexity: O(log n)
|
|
@@ -959,19 +778,19 @@ export class BinaryTree<
|
|
|
959
778
|
* the binary tree. It is used to determine whether a node matches the given identifier. The callback
|
|
960
779
|
* function should return a value that can be compared to the identifier to determine if it is a
|
|
961
780
|
* match.
|
|
962
|
-
* @param {K |
|
|
781
|
+
* @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
|
|
963
782
|
* for the search in the binary tree. It can be specified as a `K` (a unique identifier for a
|
|
964
|
-
* node), a node object of type `
|
|
783
|
+
* node), a node object of type `NODE`, or `null`/`undefined` to start the search from the root of
|
|
965
784
|
* @param iterationType - The `iterationType` parameter is used to specify the type of iteration to
|
|
966
785
|
* be performed when searching for a node in the binary tree. It is an optional parameter with a
|
|
967
786
|
* default value specified by `this.iterationType`.
|
|
968
787
|
* @returns The value of the node with the given identifier is being returned. If the node is not
|
|
969
788
|
* found, `undefined` is returned.
|
|
970
789
|
*/
|
|
971
|
-
get<C extends BTNCallback<
|
|
790
|
+
override get<C extends BTNCallback<NODE>>(
|
|
972
791
|
identifier: ReturnType<C> | null | undefined,
|
|
973
792
|
callback: C = this._defaultOneParamCallback as C,
|
|
974
|
-
beginRoot: KeyOrNodeOrEntry<K, V,
|
|
793
|
+
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
975
794
|
iterationType = this.iterationType
|
|
976
795
|
): V | undefined {
|
|
977
796
|
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
@@ -980,55 +799,339 @@ export class BinaryTree<
|
|
|
980
799
|
return this.getNode(identifier, callback, beginRoot, iterationType)?.value ?? undefined;
|
|
981
800
|
}
|
|
982
801
|
|
|
802
|
+
override has<C extends BTNCallback<NODE, K>>(
|
|
803
|
+
identifier: K,
|
|
804
|
+
callback?: C,
|
|
805
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
806
|
+
iterationType?: IterationType
|
|
807
|
+
): boolean;
|
|
808
|
+
|
|
809
|
+
override has<C extends BTNCallback<NODE, NODE>>(
|
|
810
|
+
identifier: NODE | null | undefined,
|
|
811
|
+
callback?: C,
|
|
812
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
813
|
+
iterationType?: IterationType
|
|
814
|
+
): boolean;
|
|
815
|
+
|
|
816
|
+
override has<C extends BTNCallback<NODE>>(
|
|
817
|
+
identifier: ReturnType<C> | null | undefined,
|
|
818
|
+
callback: C,
|
|
819
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
820
|
+
iterationType?: IterationType
|
|
821
|
+
): boolean;
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Time Complexity: O(n)
|
|
825
|
+
* Space Complexity: O(log n).
|
|
826
|
+
*/
|
|
827
|
+
|
|
828
|
+
/**
|
|
829
|
+
* Time Complexity: O(n)
|
|
830
|
+
* Space Complexity: O(log n).
|
|
831
|
+
*
|
|
832
|
+
* The function checks if a Binary Tree Node with a specific identifier exists in the tree.
|
|
833
|
+
* @param {ReturnType<C> | null | undefined} identifier - The `identifier` parameter is the value
|
|
834
|
+
* that you want to search for in the binary tree. It can be of any type that is returned by the
|
|
835
|
+
* callback function `C`. It can also be `null` or `undefined` if you don't want to specify a
|
|
836
|
+
* specific identifier.
|
|
837
|
+
* @param {C} callback - The `callback` parameter is a function that will be called for each node in
|
|
838
|
+
* the binary tree. It is used to filter the nodes based on certain conditions. The `callback`
|
|
839
|
+
* function should return a boolean value indicating whether the node should be included in the
|
|
840
|
+
* result or not.
|
|
841
|
+
* @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
|
|
842
|
+
* for the search in the binary tree. It can be specified as a `K` (a unique identifier for a
|
|
843
|
+
* node in the binary tree), a node object (`NODE`), or `null`/`undefined` to start the search from
|
|
844
|
+
* @param iterationType - The `iterationType` parameter is a variable that determines the type of
|
|
845
|
+
* iteration to be performed on the binary tree. It is used to specify whether the iteration should
|
|
846
|
+
* be performed in a pre-order, in-order, or post-order manner.
|
|
847
|
+
* @returns a boolean value.
|
|
848
|
+
*/
|
|
849
|
+
override has<C extends BTNCallback<NODE>>(
|
|
850
|
+
identifier: ReturnType<C> | null | undefined,
|
|
851
|
+
callback: C = this._defaultOneParamCallback as C,
|
|
852
|
+
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
853
|
+
iterationType = this.iterationType
|
|
854
|
+
): boolean {
|
|
855
|
+
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
856
|
+
callback = (node => node) as C;
|
|
857
|
+
|
|
858
|
+
return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* Time Complexity: O(1)
|
|
863
|
+
* Space Complexity: O(1)
|
|
864
|
+
*/
|
|
865
|
+
|
|
866
|
+
/**
|
|
867
|
+
* Time Complexity: O(1)
|
|
868
|
+
* Space Complexity: O(1)
|
|
869
|
+
*
|
|
870
|
+
* Clear the binary tree, removing all nodes.
|
|
871
|
+
*/
|
|
872
|
+
clear() {
|
|
873
|
+
this._setRoot(undefined);
|
|
874
|
+
this._size = 0;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
/**
|
|
878
|
+
* Time Complexity: O(1)
|
|
879
|
+
* Space Complexity: O(1)
|
|
880
|
+
*/
|
|
881
|
+
|
|
882
|
+
/**
|
|
883
|
+
* Time Complexity: O(1)
|
|
884
|
+
* Space Complexity: O(1)
|
|
885
|
+
*
|
|
886
|
+
* Check if the binary tree is empty.
|
|
887
|
+
* @returns {boolean} - True if the binary tree is empty, false otherwise.
|
|
888
|
+
*/
|
|
889
|
+
isEmpty(): boolean {
|
|
890
|
+
return this.size === 0;
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
/**
|
|
894
|
+
* Time Complexity: O(n)
|
|
895
|
+
* Space Complexity: O(log n)
|
|
896
|
+
*/
|
|
897
|
+
|
|
898
|
+
/**
|
|
899
|
+
* Time Complexity: O(n)
|
|
900
|
+
* Space Complexity: O(log n)
|
|
901
|
+
*
|
|
902
|
+
* The function checks if a binary tree is perfectly balanced by comparing the minimum height and the
|
|
903
|
+
* height of the tree.
|
|
904
|
+
* @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
|
|
905
|
+
* for calculating the height and minimum height of a binary tree. It can be either a `K` (a key
|
|
906
|
+
* value of a binary tree node), `NODE` (a node of a binary tree), `null`, or `undefined`. If
|
|
907
|
+
* @returns a boolean value.
|
|
908
|
+
*/
|
|
909
|
+
isPerfectlyBalanced(beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root): boolean {
|
|
910
|
+
return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
/**
|
|
914
|
+
* Time Complexity: O(n)
|
|
915
|
+
* Space Complexity: O(1)
|
|
916
|
+
*/
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* Time Complexity: O(n)
|
|
920
|
+
* Space Complexity: O(1)
|
|
921
|
+
*
|
|
922
|
+
* The function `isSubtreeBST` checks if a given binary tree is a valid binary search tree.
|
|
923
|
+
* @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter represents the root
|
|
924
|
+
* node of the binary search tree (BST) that you want to check if it is a subtree of another BST.
|
|
925
|
+
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
|
|
926
|
+
* type of iteration to use when checking if a subtree is a binary search tree (BST). It can have two
|
|
927
|
+
* possible values:
|
|
928
|
+
* @returns a boolean value.
|
|
929
|
+
*/
|
|
930
|
+
isBST(beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root, iterationType = this.iterationType): boolean {
|
|
931
|
+
// TODO there is a bug
|
|
932
|
+
beginRoot = this.ensureNode(beginRoot);
|
|
933
|
+
if (!beginRoot) return true;
|
|
934
|
+
|
|
935
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
936
|
+
const dfs = (cur: NODE | null | undefined, min: number, max: number): boolean => {
|
|
937
|
+
if (!cur) return true;
|
|
938
|
+
const numKey = this.extractor(cur.key);
|
|
939
|
+
if (numKey <= min || numKey >= max) return false;
|
|
940
|
+
return dfs(cur.left, min, numKey) && dfs(cur.right, numKey, max);
|
|
941
|
+
};
|
|
942
|
+
|
|
943
|
+
const isStandardBST = dfs(beginRoot, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
|
|
944
|
+
const isInverseBST = dfs(beginRoot, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER);
|
|
945
|
+
return isStandardBST || isInverseBST;
|
|
946
|
+
} else {
|
|
947
|
+
const checkBST = (checkMax = false) => {
|
|
948
|
+
const stack = [];
|
|
949
|
+
let prev = checkMax ? Number.MAX_SAFE_INTEGER : Number.MIN_SAFE_INTEGER;
|
|
950
|
+
// @ts-ignore
|
|
951
|
+
let curr: NODE | null | undefined = beginRoot;
|
|
952
|
+
while (curr || stack.length > 0) {
|
|
953
|
+
while (curr) {
|
|
954
|
+
stack.push(curr);
|
|
955
|
+
curr = curr.left;
|
|
956
|
+
}
|
|
957
|
+
curr = stack.pop()!;
|
|
958
|
+
const numKey = this.extractor(curr.key);
|
|
959
|
+
if (!curr || (!checkMax && prev >= numKey) || (checkMax && prev <= numKey)) return false;
|
|
960
|
+
prev = numKey;
|
|
961
|
+
curr = curr.right;
|
|
962
|
+
}
|
|
963
|
+
return true;
|
|
964
|
+
};
|
|
965
|
+
const isStandardBST = checkBST(false),
|
|
966
|
+
isInverseBST = checkBST(true);
|
|
967
|
+
return isStandardBST || isInverseBST;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
/**
|
|
972
|
+
* Time Complexity: O(n)
|
|
973
|
+
* Space Complexity: O(1)
|
|
974
|
+
*/
|
|
975
|
+
|
|
976
|
+
/**
|
|
977
|
+
* Time Complexity: O(n)
|
|
978
|
+
* Space Complexity: O(1)
|
|
979
|
+
*
|
|
980
|
+
* The function calculates the depth of a given node in a binary tree.
|
|
981
|
+
* @param {K | NODE | null | undefined} dist - The `dist` parameter represents the node in
|
|
982
|
+
* the binary tree whose depth we want to find. It can be of type `K`, `NODE`, `null`, or
|
|
983
|
+
* `undefined`.
|
|
984
|
+
* @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter is the starting node
|
|
985
|
+
* from which we want to calculate the depth. It can be either a `K` (binary tree node key) or
|
|
986
|
+
* `NODE` (binary tree node) or `null` or `undefined`. If no value is provided for `beginRoot
|
|
987
|
+
* @returns the depth of the `dist` relative to the `beginRoot`.
|
|
988
|
+
*/
|
|
989
|
+
getDepth(dist: KeyOrNodeOrEntry<K, V, NODE>, beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root): number {
|
|
990
|
+
dist = this.ensureNode(dist);
|
|
991
|
+
beginRoot = this.ensureNode(beginRoot);
|
|
992
|
+
let depth = 0;
|
|
993
|
+
while (dist?.parent) {
|
|
994
|
+
if (dist === beginRoot) {
|
|
995
|
+
return depth;
|
|
996
|
+
}
|
|
997
|
+
depth++;
|
|
998
|
+
dist = dist.parent;
|
|
999
|
+
}
|
|
1000
|
+
return depth;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
983
1003
|
/**
|
|
984
|
-
* Time Complexity: O(
|
|
1004
|
+
* Time Complexity: O(n)
|
|
985
1005
|
* Space Complexity: O(1)
|
|
986
1006
|
*/
|
|
987
1007
|
|
|
988
1008
|
/**
|
|
989
|
-
* Time Complexity: O(
|
|
990
|
-
* Space Complexity: O(
|
|
1009
|
+
* Time Complexity: O(n)
|
|
1010
|
+
* Space Complexity: O(log n)
|
|
991
1011
|
*
|
|
992
|
-
*
|
|
1012
|
+
* The function `getHeight` calculates the maximum height of a binary tree using either recursive or
|
|
1013
|
+
* iterative traversal.
|
|
1014
|
+
* @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
1015
|
+
* starting node of the binary tree from which we want to calculate the height. It can be of type
|
|
1016
|
+
* `K`, `NODE`, `null`, or `undefined`. If not provided, it defaults to `this.root`.
|
|
1017
|
+
* @param iterationType - The `iterationType` parameter is used to determine whether to calculate the
|
|
1018
|
+
* height of the tree using a recursive approach or an iterative approach. It can have two possible
|
|
1019
|
+
* values:
|
|
1020
|
+
* @returns the height of the binary tree.
|
|
993
1021
|
*/
|
|
994
|
-
|
|
995
|
-
this.
|
|
996
|
-
|
|
1022
|
+
getHeight(beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root, iterationType = this.iterationType): number {
|
|
1023
|
+
beginRoot = this.ensureNode(beginRoot);
|
|
1024
|
+
if (!beginRoot) return -1;
|
|
1025
|
+
|
|
1026
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
1027
|
+
const _getMaxHeight = (cur: NODE | null | undefined): number => {
|
|
1028
|
+
if (!cur) return -1;
|
|
1029
|
+
const leftHeight = _getMaxHeight(cur.left);
|
|
1030
|
+
const rightHeight = _getMaxHeight(cur.right);
|
|
1031
|
+
return Math.max(leftHeight, rightHeight) + 1;
|
|
1032
|
+
};
|
|
1033
|
+
|
|
1034
|
+
return _getMaxHeight(beginRoot);
|
|
1035
|
+
} else {
|
|
1036
|
+
const stack: { node: NODE; depth: number }[] = [{ node: beginRoot, depth: 0 }];
|
|
1037
|
+
let maxHeight = 0;
|
|
1038
|
+
|
|
1039
|
+
while (stack.length > 0) {
|
|
1040
|
+
const { node, depth } = stack.pop()!;
|
|
1041
|
+
|
|
1042
|
+
if (node.left) stack.push({ node: node.left, depth: depth + 1 });
|
|
1043
|
+
if (node.right) stack.push({ node: node.right, depth: depth + 1 });
|
|
1044
|
+
|
|
1045
|
+
maxHeight = Math.max(maxHeight, depth);
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
return maxHeight;
|
|
1049
|
+
}
|
|
997
1050
|
}
|
|
998
1051
|
|
|
999
1052
|
/**
|
|
1000
|
-
* Time Complexity: O(
|
|
1001
|
-
* Space Complexity: O(
|
|
1053
|
+
* Time Complexity: O(n)
|
|
1054
|
+
* Space Complexity: O(log n)
|
|
1002
1055
|
*/
|
|
1003
1056
|
|
|
1004
1057
|
/**
|
|
1005
|
-
* Time Complexity: O(
|
|
1006
|
-
* Space Complexity: O(
|
|
1058
|
+
* Time Complexity: O(n)
|
|
1059
|
+
* Space Complexity: O(log n)
|
|
1007
1060
|
*
|
|
1008
|
-
*
|
|
1009
|
-
*
|
|
1061
|
+
* The `getMinHeight` function calculates the minimum height of a binary tree using either a
|
|
1062
|
+
* recursive or iterative approach.
|
|
1063
|
+
* @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
1064
|
+
* starting node of the binary tree from which we want to calculate the minimum height. It can be of
|
|
1065
|
+
* type `K`, `NODE`, `null`, or `undefined`. If no value is provided, it defaults to `this.root`.
|
|
1066
|
+
* @param iterationType - The `iterationType` parameter is used to determine the method of iteration
|
|
1067
|
+
* to calculate the minimum height of a binary tree. It can have two possible values:
|
|
1068
|
+
* @returns The function `getMinHeight` returns the minimum height of a binary tree.
|
|
1010
1069
|
*/
|
|
1011
|
-
|
|
1012
|
-
|
|
1070
|
+
getMinHeight(beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root, iterationType = this.iterationType): number {
|
|
1071
|
+
beginRoot = this.ensureNode(beginRoot);
|
|
1072
|
+
if (!beginRoot) return -1;
|
|
1073
|
+
|
|
1074
|
+
if (iterationType === IterationType.RECURSIVE) {
|
|
1075
|
+
const _getMinHeight = (cur: NODE | null | undefined): number => {
|
|
1076
|
+
if (!cur) return 0;
|
|
1077
|
+
if (!cur.left && !cur.right) return 0;
|
|
1078
|
+
const leftMinHeight = _getMinHeight(cur.left);
|
|
1079
|
+
const rightMinHeight = _getMinHeight(cur.right);
|
|
1080
|
+
return Math.min(leftMinHeight, rightMinHeight) + 1;
|
|
1081
|
+
};
|
|
1082
|
+
|
|
1083
|
+
return _getMinHeight(beginRoot);
|
|
1084
|
+
} else {
|
|
1085
|
+
const stack: NODE[] = [];
|
|
1086
|
+
let node: NODE | null | undefined = beginRoot,
|
|
1087
|
+
last: NODE | null | undefined = null;
|
|
1088
|
+
const depths: Map<NODE, number> = new Map();
|
|
1089
|
+
|
|
1090
|
+
while (stack.length > 0 || node) {
|
|
1091
|
+
if (node) {
|
|
1092
|
+
stack.push(node);
|
|
1093
|
+
node = node.left;
|
|
1094
|
+
} else {
|
|
1095
|
+
node = stack[stack.length - 1];
|
|
1096
|
+
if (!node.right || last === node.right) {
|
|
1097
|
+
node = stack.pop();
|
|
1098
|
+
if (node) {
|
|
1099
|
+
const leftMinHeight = node.left ? depths.get(node.left) ?? -1 : -1;
|
|
1100
|
+
const rightMinHeight = node.right ? depths.get(node.right) ?? -1 : -1;
|
|
1101
|
+
depths.set(node, 1 + Math.min(leftMinHeight, rightMinHeight));
|
|
1102
|
+
last = node;
|
|
1103
|
+
node = null;
|
|
1104
|
+
}
|
|
1105
|
+
} else node = node.right;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
return depths.get(beginRoot) ?? -1;
|
|
1110
|
+
}
|
|
1013
1111
|
}
|
|
1014
1112
|
|
|
1015
1113
|
/**
|
|
1114
|
+
* Time Complexity: O(log n)
|
|
1115
|
+
* Space Complexity: O(log n)
|
|
1116
|
+
* /
|
|
1117
|
+
|
|
1118
|
+
/**
|
|
1016
1119
|
* Time Complexity: O(log n)
|
|
1017
1120
|
* Space Complexity: O(log n)
|
|
1018
1121
|
*
|
|
1019
1122
|
* The function `getPathToRoot` returns an array of nodes from a given node to the root of a tree
|
|
1020
1123
|
* structure, with the option to reverse the order of the nodes.
|
|
1021
|
-
* @param {K |
|
|
1022
|
-
* starting node from which you want to find the path to the root. It can be of type `K`, `
|
|
1124
|
+
* @param {K | NODE | null | undefined} beginNode - The `beginRoot` parameter represents the
|
|
1125
|
+
* starting node from which you want to find the path to the root. It can be of type `K`, `NODE`,
|
|
1023
1126
|
* `null`, or `undefined`.
|
|
1024
1127
|
* @param [isReverse=true] - The `isReverse` parameter is a boolean flag that determines whether the
|
|
1025
1128
|
* resulting path should be reversed or not. If `isReverse` is set to `true`, the path will be
|
|
1026
1129
|
* reversed before returning it. If `isReverse` is set to `false`, the path will be returned as is
|
|
1027
|
-
* @returns The function `getPathToRoot` returns an array of nodes (`
|
|
1130
|
+
* @returns The function `getPathToRoot` returns an array of nodes (`NODE[]`).
|
|
1028
1131
|
*/
|
|
1029
|
-
getPathToRoot(beginNode: KeyOrNodeOrEntry<K, V,
|
|
1132
|
+
getPathToRoot(beginNode: KeyOrNodeOrEntry<K, V, NODE>, isReverse = true): NODE[] {
|
|
1030
1133
|
// TODO to support get path through passing key
|
|
1031
|
-
const result:
|
|
1134
|
+
const result: NODE[] = [];
|
|
1032
1135
|
beginNode = this.ensureNode(beginNode);
|
|
1033
1136
|
|
|
1034
1137
|
if (!beginNode) return result;
|
|
@@ -1054,24 +1157,24 @@ export class BinaryTree<
|
|
|
1054
1157
|
*
|
|
1055
1158
|
* The function `getLeftMost` returns the leftmost node in a binary tree, either recursively or
|
|
1056
1159
|
* iteratively.
|
|
1057
|
-
* @param {K |
|
|
1058
|
-
* for finding the leftmost node in a binary tree. It can be either a `K` (a key value), `
|
|
1160
|
+
* @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
|
|
1161
|
+
* for finding the leftmost node in a binary tree. It can be either a `K` (a key value), `NODE` (a
|
|
1059
1162
|
* node), `null`, or `undefined`. If not provided, it defaults to `this.root`,
|
|
1060
1163
|
* @param iterationType - The `iterationType` parameter is used to determine the type of iteration to
|
|
1061
1164
|
* be performed when finding the leftmost node in a binary tree. It can have two possible values:
|
|
1062
|
-
* @returns The function `getLeftMost` returns the leftmost node (`
|
|
1165
|
+
* @returns The function `getLeftMost` returns the leftmost node (`NODE`) in the binary tree. If there
|
|
1063
1166
|
* is no leftmost node, it returns `null` or `undefined` depending on the input.
|
|
1064
1167
|
*/
|
|
1065
1168
|
getLeftMost(
|
|
1066
|
-
beginRoot: KeyOrNodeOrEntry<K, V,
|
|
1169
|
+
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1067
1170
|
iterationType = this.iterationType
|
|
1068
|
-
):
|
|
1171
|
+
): NODE | null | undefined {
|
|
1069
1172
|
beginRoot = this.ensureNode(beginRoot);
|
|
1070
1173
|
|
|
1071
1174
|
if (!beginRoot) return beginRoot;
|
|
1072
1175
|
|
|
1073
1176
|
if (iterationType === IterationType.RECURSIVE) {
|
|
1074
|
-
const _traverse = (cur:
|
|
1177
|
+
const _traverse = (cur: NODE): NODE => {
|
|
1075
1178
|
if (!this.isRealNode(cur.left)) return cur;
|
|
1076
1179
|
return _traverse(cur.left);
|
|
1077
1180
|
};
|
|
@@ -1079,7 +1182,7 @@ export class BinaryTree<
|
|
|
1079
1182
|
return _traverse(beginRoot);
|
|
1080
1183
|
} else {
|
|
1081
1184
|
// Indirect implementation of iteration using tail recursion optimization
|
|
1082
|
-
const _traverse = trampoline((cur:
|
|
1185
|
+
const _traverse = trampoline((cur: NODE) => {
|
|
1083
1186
|
if (!this.isRealNode(cur.left)) return cur;
|
|
1084
1187
|
return _traverse.cont(cur.left);
|
|
1085
1188
|
});
|
|
@@ -1099,25 +1202,25 @@ export class BinaryTree<
|
|
|
1099
1202
|
*
|
|
1100
1203
|
* The function `getRightMost` returns the rightmost node in a binary tree, either recursively or
|
|
1101
1204
|
* iteratively.
|
|
1102
|
-
* @param {K |
|
|
1103
|
-
* starting node from which we want to find the rightmost node. It can be of type `K`, `
|
|
1205
|
+
* @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
1206
|
+
* starting node from which we want to find the rightmost node. It can be of type `K`, `NODE`,
|
|
1104
1207
|
* `null`, or `undefined`. If not provided, it defaults to `this.root`, which is a property of the
|
|
1105
1208
|
* current object.
|
|
1106
1209
|
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
|
|
1107
1210
|
* type of iteration to use when finding the rightmost node. It can have one of two values:
|
|
1108
|
-
* @returns The function `getRightMost` returns the rightmost node (`
|
|
1211
|
+
* @returns The function `getRightMost` returns the rightmost node (`NODE`) in a binary tree. If there
|
|
1109
1212
|
* is no rightmost node, it returns `null` or `undefined`, depending on the input.
|
|
1110
1213
|
*/
|
|
1111
1214
|
getRightMost(
|
|
1112
|
-
beginRoot: KeyOrNodeOrEntry<K, V,
|
|
1215
|
+
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1113
1216
|
iterationType = this.iterationType
|
|
1114
|
-
):
|
|
1217
|
+
): NODE | null | undefined {
|
|
1115
1218
|
// TODO support get right most by passing key in
|
|
1116
1219
|
beginRoot = this.ensureNode(beginRoot);
|
|
1117
1220
|
if (!beginRoot) return beginRoot;
|
|
1118
1221
|
|
|
1119
1222
|
if (iterationType === IterationType.RECURSIVE) {
|
|
1120
|
-
const _traverse = (cur:
|
|
1223
|
+
const _traverse = (cur: NODE): NODE => {
|
|
1121
1224
|
if (!this.isRealNode(cur.right)) return cur;
|
|
1122
1225
|
return _traverse(cur.right);
|
|
1123
1226
|
};
|
|
@@ -1125,7 +1228,7 @@ export class BinaryTree<
|
|
|
1125
1228
|
return _traverse(beginRoot);
|
|
1126
1229
|
} else {
|
|
1127
1230
|
// Indirect implementation of iteration using tail recursion optimization
|
|
1128
|
-
const _traverse = trampoline((cur:
|
|
1231
|
+
const _traverse = trampoline((cur: NODE) => {
|
|
1129
1232
|
if (!this.isRealNode(cur.right)) return cur;
|
|
1130
1233
|
return _traverse.cont(cur.right);
|
|
1131
1234
|
});
|
|
@@ -1140,164 +1243,80 @@ export class BinaryTree<
|
|
|
1140
1243
|
*/
|
|
1141
1244
|
|
|
1142
1245
|
/**
|
|
1143
|
-
* Time Complexity: O(n)
|
|
1246
|
+
* Time Complexity: O(log n)
|
|
1144
1247
|
* Space Complexity: O(1)
|
|
1145
1248
|
*
|
|
1146
|
-
* The function
|
|
1147
|
-
* @param {
|
|
1148
|
-
*
|
|
1149
|
-
* @
|
|
1150
|
-
* type of iteration to use when checking if a subtree is a binary search tree (BST). It can have two
|
|
1151
|
-
* possible values:
|
|
1152
|
-
* @returns a boolean value.
|
|
1249
|
+
* The function returns the predecessor of a given node in a tree.
|
|
1250
|
+
* @param {NODE} node - The parameter `node` is of type `RedBlackTreeNode`, which represents a node in a
|
|
1251
|
+
* tree.
|
|
1252
|
+
* @returns the predecessor of the given 'node'.
|
|
1153
1253
|
*/
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1254
|
+
getPredecessor(node: NODE): NODE {
|
|
1255
|
+
if (this.isRealNode(node.left)) {
|
|
1256
|
+
let predecessor: NODE | null | undefined = node.left;
|
|
1257
|
+
while (!this.isRealNode(predecessor) || (this.isRealNode(predecessor.right) && predecessor.right !== node)) {
|
|
1258
|
+
if (this.isRealNode(predecessor)) {
|
|
1259
|
+
predecessor = predecessor.right;
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
return predecessor;
|
|
1263
|
+
} else {
|
|
1264
|
+
return node;
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1158
1267
|
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
if (numKey <= min || numKey >= max) return false;
|
|
1164
|
-
return dfs(cur.left, min, numKey) && dfs(cur.right, numKey, max);
|
|
1165
|
-
};
|
|
1268
|
+
/**
|
|
1269
|
+
* Time Complexity: O(log n)
|
|
1270
|
+
* Space Complexity: O(1)
|
|
1271
|
+
*/
|
|
1166
1272
|
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
};
|
|
1189
|
-
const isStandardBST = checkBST(false),
|
|
1190
|
-
isInverseBST = checkBST(true);
|
|
1191
|
-
return isStandardBST || isInverseBST;
|
|
1273
|
+
/**
|
|
1274
|
+
* Time Complexity: O(log n)
|
|
1275
|
+
* Space Complexity: O(1)
|
|
1276
|
+
*
|
|
1277
|
+
* The function `getSuccessor` returns the next node in a binary tree given a current node.
|
|
1278
|
+
* @param {K | NODE | null} [x] - The parameter `x` can be of type `K`, `NODE`, or `null`.
|
|
1279
|
+
* @returns the successor of the given node or key. The successor is the node that comes immediately
|
|
1280
|
+
* after the given node in the inorder traversal of the binary tree.
|
|
1281
|
+
*/
|
|
1282
|
+
getSuccessor(x?: K | NODE | null): NODE | null | undefined {
|
|
1283
|
+
x = this.ensureNode(x);
|
|
1284
|
+
if (!this.isRealNode(x)) return undefined;
|
|
1285
|
+
|
|
1286
|
+
if (this.isRealNode(x.right)) {
|
|
1287
|
+
return this.getLeftMost(x.right);
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
let y: NODE | null | undefined = x.parent;
|
|
1291
|
+
while (this.isRealNode(y) && x === y.right) {
|
|
1292
|
+
x = y;
|
|
1293
|
+
y = y.parent;
|
|
1192
1294
|
}
|
|
1295
|
+
return y;
|
|
1193
1296
|
}
|
|
1194
1297
|
|
|
1195
|
-
|
|
1196
|
-
// * Time complexity: O(n)
|
|
1197
|
-
// * Space complexity: O(log n)
|
|
1198
|
-
// */
|
|
1199
|
-
//
|
|
1200
|
-
// subTreeTraverse<C extends BTNCallback<N>>(
|
|
1201
|
-
// callback?: C,
|
|
1202
|
-
// beginRoot?: KeyOrNodeOrEntry<K, V, N>,
|
|
1203
|
-
// iterationType?: IterationType,
|
|
1204
|
-
// includeNull?: false
|
|
1205
|
-
// ): ReturnType<C>[];
|
|
1206
|
-
//
|
|
1207
|
-
// subTreeTraverse<C extends BTNCallback<N | null>>(
|
|
1208
|
-
// callback?: C,
|
|
1209
|
-
// beginRoot?: KeyOrNodeOrEntry<K, V, N>,
|
|
1210
|
-
// iterationType?: IterationType,
|
|
1211
|
-
// includeNull?: true
|
|
1212
|
-
// ): ReturnType<C>[];
|
|
1213
|
-
//
|
|
1214
|
-
// /**
|
|
1215
|
-
// * Time complexity: O(n)
|
|
1216
|
-
// * Space complexity: O(log n)
|
|
1217
|
-
// *
|
|
1218
|
-
// * The function `subTreeTraverse` traverses a binary tree and applies a callback function to each
|
|
1219
|
-
// * node, either recursively or iteratively.
|
|
1220
|
-
// * @param {C} callback - The `callback` parameter is a function that will be called for each node in
|
|
1221
|
-
// * the subtree traversal. It takes a single parameter, which is the current node being traversed, and
|
|
1222
|
-
// * returns a value of any type.
|
|
1223
|
-
// * @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
1224
|
-
// * starting node or key from which the subtree traversal should begin. It can be of type `K`,
|
|
1225
|
-
// * `N`, `null`, or `undefined`. If not provided, the `root` property of the current object is used as
|
|
1226
|
-
// * the default value.
|
|
1227
|
-
// * @param iterationType - The `iterationType` parameter determines the type of traversal to be
|
|
1228
|
-
// * performed on the subtree. It can have two possible values:
|
|
1229
|
-
// * @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines
|
|
1230
|
-
// * whether to include null values in the traversal. If `includeNull` is set to `true`, the
|
|
1231
|
-
// * traversal will include null values, otherwise it will skip them.
|
|
1232
|
-
// * @returns The function `subTreeTraverse` returns an array of values that are the result of invoking
|
|
1233
|
-
// * the `callback` function on each node in the subtree. The type of the array nodes is determined
|
|
1234
|
-
// * by the return type of the `callback` function.
|
|
1235
|
-
// */
|
|
1236
|
-
// subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
|
|
1237
|
-
// callback: C = this._defaultOneParamCallback as C,
|
|
1238
|
-
// beginRoot: KeyOrNodeOrEntry<K, V, N> = this.root,
|
|
1239
|
-
// iterationType = this.iterationType,
|
|
1240
|
-
// includeNull = false
|
|
1241
|
-
// ): ReturnType<C>[] {
|
|
1242
|
-
// console.warn('subTreeTraverse is unnecessary, since the dfs method can substitute it.');
|
|
1243
|
-
//
|
|
1244
|
-
// beginRoot = this.ensureNode(beginRoot);
|
|
1245
|
-
//
|
|
1246
|
-
// const ans: (ReturnType<BTNCallback<N>> | null | undefined)[] = [];
|
|
1247
|
-
// if (!beginRoot) return ans;
|
|
1248
|
-
//
|
|
1249
|
-
// if (iterationType === IterationType.RECURSIVE) {
|
|
1250
|
-
// const _traverse = (cur: N | null | undefined) => {
|
|
1251
|
-
// if (cur !== undefined) {
|
|
1252
|
-
// ans.push(callback(cur));
|
|
1253
|
-
// if (includeNull) {
|
|
1254
|
-
// cur && this.isNodeOrNull(cur.left) && _traverse(cur.left);
|
|
1255
|
-
// cur && this.isNodeOrNull(cur.right) && _traverse(cur.right);
|
|
1256
|
-
// } else {
|
|
1257
|
-
// cur && cur.left && _traverse(cur.left);
|
|
1258
|
-
// cur && cur.right && _traverse(cur.right);
|
|
1259
|
-
// }
|
|
1260
|
-
// }
|
|
1261
|
-
// };
|
|
1262
|
-
//
|
|
1263
|
-
// _traverse(beginRoot);
|
|
1264
|
-
// } else {
|
|
1265
|
-
// const stack: (N | null | undefined)[] = [beginRoot];
|
|
1266
|
-
//
|
|
1267
|
-
// while (stack.length > 0) {
|
|
1268
|
-
// const cur = stack.pop();
|
|
1269
|
-
// if (cur !== undefined) {
|
|
1270
|
-
// ans.push(callback(cur));
|
|
1271
|
-
// if (includeNull) {
|
|
1272
|
-
// cur && this.isNodeOrNull(cur.right) && stack.push(cur.right);
|
|
1273
|
-
// cur && this.isNodeOrNull(cur.left) && stack.push(cur.left);
|
|
1274
|
-
// } else {
|
|
1275
|
-
// cur && cur.right && stack.push(cur.right);
|
|
1276
|
-
// cur && cur.left && stack.push(cur.left);
|
|
1277
|
-
// }
|
|
1278
|
-
// }
|
|
1279
|
-
// }
|
|
1280
|
-
// }
|
|
1281
|
-
// return ans;
|
|
1282
|
-
// }
|
|
1283
|
-
|
|
1284
|
-
dfs<C extends BTNCallback<N>>(
|
|
1298
|
+
dfs<C extends BTNCallback<NODE>>(
|
|
1285
1299
|
callback?: C,
|
|
1286
1300
|
pattern?: DFSOrderPattern,
|
|
1287
|
-
beginRoot?: KeyOrNodeOrEntry<K, V,
|
|
1301
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
1288
1302
|
iterationType?: IterationType,
|
|
1289
1303
|
includeNull?: false
|
|
1290
1304
|
): ReturnType<C>[];
|
|
1291
1305
|
|
|
1292
|
-
dfs<C extends BTNCallback<
|
|
1306
|
+
dfs<C extends BTNCallback<NODE | null>>(
|
|
1293
1307
|
callback?: C,
|
|
1294
1308
|
pattern?: DFSOrderPattern,
|
|
1295
|
-
beginRoot?: KeyOrNodeOrEntry<K, V,
|
|
1309
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
1296
1310
|
iterationType?: IterationType,
|
|
1297
1311
|
includeNull?: true
|
|
1298
1312
|
): ReturnType<C>[];
|
|
1299
1313
|
|
|
1300
1314
|
/**
|
|
1315
|
+
* Time complexity: O(n)
|
|
1316
|
+
* Space complexity: O(n)
|
|
1317
|
+
* /
|
|
1318
|
+
|
|
1319
|
+
/**
|
|
1301
1320
|
* Time complexity: O(n)
|
|
1302
1321
|
* Space complexity: O(n)
|
|
1303
1322
|
*
|
|
@@ -1305,11 +1324,11 @@ export class BinaryTree<
|
|
|
1305
1324
|
* specified pattern and iteration type, and returns an array of values obtained from applying a
|
|
1306
1325
|
* callback function to each visited node.
|
|
1307
1326
|
* @param {C} callback - The `callback` parameter is a function that will be called for each node in
|
|
1308
|
-
* the tree during the depth-first search. It takes a single parameter, which can be of type `
|
|
1327
|
+
* the tree during the depth-first search. It takes a single parameter, which can be of type `NODE`,
|
|
1309
1328
|
* `null`, or `undefined`, and returns a value of any type. The default value for this parameter is
|
|
1310
1329
|
* @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter determines the order in which the
|
|
1311
1330
|
* nodes are traversed during the depth-first search. It can have one of the following values:
|
|
1312
|
-
* @param {K |
|
|
1331
|
+
* @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter is the starting node
|
|
1313
1332
|
* for the depth-first search traversal. It can be specified as a key, a node object, or
|
|
1314
1333
|
* `null`/`undefined`. If not provided, the `beginRoot` will default to the root node of the tree.
|
|
1315
1334
|
* @param {IterationType} iterationType - The `iterationType` parameter determines the type of
|
|
@@ -1320,10 +1339,10 @@ export class BinaryTree<
|
|
|
1320
1339
|
* `false`, null or undefined
|
|
1321
1340
|
* @returns an array of values that are the return values of the callback function.
|
|
1322
1341
|
*/
|
|
1323
|
-
dfs<C extends BTNCallback<
|
|
1342
|
+
dfs<C extends BTNCallback<NODE | null | undefined>>(
|
|
1324
1343
|
callback: C = this._defaultOneParamCallback as C,
|
|
1325
1344
|
pattern: DFSOrderPattern = 'in',
|
|
1326
|
-
beginRoot: KeyOrNodeOrEntry<K, V,
|
|
1345
|
+
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1327
1346
|
iterationType: IterationType = IterationType.ITERATIVE,
|
|
1328
1347
|
includeNull = false
|
|
1329
1348
|
): ReturnType<C>[] {
|
|
@@ -1331,7 +1350,7 @@ export class BinaryTree<
|
|
|
1331
1350
|
if (!beginRoot) return [];
|
|
1332
1351
|
const ans: ReturnType<C>[] = [];
|
|
1333
1352
|
if (iterationType === IterationType.RECURSIVE) {
|
|
1334
|
-
const _traverse = (node:
|
|
1353
|
+
const _traverse = (node: NODE | null | undefined) => {
|
|
1335
1354
|
switch (pattern) {
|
|
1336
1355
|
case 'in':
|
|
1337
1356
|
if (includeNull) {
|
|
@@ -1373,7 +1392,7 @@ export class BinaryTree<
|
|
|
1373
1392
|
_traverse(beginRoot);
|
|
1374
1393
|
} else {
|
|
1375
1394
|
// 0: visit, 1: print
|
|
1376
|
-
const stack: { opt: 0 | 1; node:
|
|
1395
|
+
const stack: { opt: 0 | 1; node: NODE | null | undefined }[] = [{ opt: 0, node: beginRoot }];
|
|
1377
1396
|
|
|
1378
1397
|
while (stack.length > 0) {
|
|
1379
1398
|
const cur = stack.pop();
|
|
@@ -1415,25 +1434,25 @@ export class BinaryTree<
|
|
|
1415
1434
|
return ans;
|
|
1416
1435
|
}
|
|
1417
1436
|
|
|
1418
|
-
|
|
1419
|
-
* Time complexity: O(n)
|
|
1420
|
-
* Space complexity: O(n)
|
|
1421
|
-
*/
|
|
1422
|
-
|
|
1423
|
-
bfs<C extends BTNCallback<N>>(
|
|
1437
|
+
bfs<C extends BTNCallback<NODE>>(
|
|
1424
1438
|
callback?: C,
|
|
1425
|
-
beginRoot?: KeyOrNodeOrEntry<K, V,
|
|
1439
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
1426
1440
|
iterationType?: IterationType,
|
|
1427
1441
|
includeNull?: false
|
|
1428
1442
|
): ReturnType<C>[];
|
|
1429
1443
|
|
|
1430
|
-
bfs<C extends BTNCallback<
|
|
1444
|
+
bfs<C extends BTNCallback<NODE | null>>(
|
|
1431
1445
|
callback?: C,
|
|
1432
|
-
beginRoot?: KeyOrNodeOrEntry<K, V,
|
|
1446
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
1433
1447
|
iterationType?: IterationType,
|
|
1434
1448
|
includeNull?: true
|
|
1435
1449
|
): ReturnType<C>[];
|
|
1436
1450
|
|
|
1451
|
+
/**
|
|
1452
|
+
* Time complexity: O(n)
|
|
1453
|
+
* Space complexity: O(n)
|
|
1454
|
+
*/
|
|
1455
|
+
|
|
1437
1456
|
/**
|
|
1438
1457
|
* Time complexity: O(n)
|
|
1439
1458
|
* Space complexity: O(n)
|
|
@@ -1443,7 +1462,7 @@ export class BinaryTree<
|
|
|
1443
1462
|
* @param {C} callback - The `callback` parameter is a function that will be called for each node in
|
|
1444
1463
|
* the breadth-first search traversal. It takes a single parameter, which is the current node being
|
|
1445
1464
|
* visited, and returns a value of any type.
|
|
1446
|
-
* @param {K |
|
|
1465
|
+
* @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
1447
1466
|
* starting node for the breadth-first search traversal. It can be specified as a key, a node object,
|
|
1448
1467
|
* or `null`/`undefined` to indicate the root of the tree. If not provided, the `root` property of
|
|
1449
1468
|
* the class is used as
|
|
@@ -1455,19 +1474,19 @@ export class BinaryTree<
|
|
|
1455
1474
|
* @returns an array of values that are the result of invoking the callback function on each node in
|
|
1456
1475
|
* the breadth-first traversal of a binary tree.
|
|
1457
1476
|
*/
|
|
1458
|
-
bfs<C extends BTNCallback<
|
|
1477
|
+
bfs<C extends BTNCallback<NODE | null>>(
|
|
1459
1478
|
callback: C = this._defaultOneParamCallback as C,
|
|
1460
|
-
beginRoot: KeyOrNodeOrEntry<K, V,
|
|
1479
|
+
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1461
1480
|
iterationType = this.iterationType,
|
|
1462
1481
|
includeNull = false
|
|
1463
1482
|
): ReturnType<C>[] {
|
|
1464
1483
|
beginRoot = this.ensureNode(beginRoot);
|
|
1465
1484
|
if (!beginRoot) return [];
|
|
1466
1485
|
|
|
1467
|
-
const ans: ReturnType<BTNCallback<
|
|
1486
|
+
const ans: ReturnType<BTNCallback<NODE>>[] = [];
|
|
1468
1487
|
|
|
1469
1488
|
if (iterationType === IterationType.RECURSIVE) {
|
|
1470
|
-
const queue: Queue<
|
|
1489
|
+
const queue: Queue<NODE | null | undefined> = new Queue<NODE | null | undefined>([beginRoot]);
|
|
1471
1490
|
|
|
1472
1491
|
const traverse = (level: number) => {
|
|
1473
1492
|
if (queue.size === 0) return;
|
|
@@ -1488,7 +1507,7 @@ export class BinaryTree<
|
|
|
1488
1507
|
|
|
1489
1508
|
traverse(0);
|
|
1490
1509
|
} else {
|
|
1491
|
-
const queue = new Queue<
|
|
1510
|
+
const queue = new Queue<NODE | null | undefined>([beginRoot]);
|
|
1492
1511
|
while (queue.size > 0) {
|
|
1493
1512
|
const levelSize = queue.size;
|
|
1494
1513
|
|
|
@@ -1509,25 +1528,25 @@ export class BinaryTree<
|
|
|
1509
1528
|
return ans;
|
|
1510
1529
|
}
|
|
1511
1530
|
|
|
1512
|
-
|
|
1513
|
-
* Time complexity: O(n)
|
|
1514
|
-
* Space complexity: O(n)
|
|
1515
|
-
*/
|
|
1516
|
-
|
|
1517
|
-
listLevels<C extends BTNCallback<N>>(
|
|
1531
|
+
listLevels<C extends BTNCallback<NODE>>(
|
|
1518
1532
|
callback?: C,
|
|
1519
|
-
beginRoot?: KeyOrNodeOrEntry<K, V,
|
|
1533
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
1520
1534
|
iterationType?: IterationType,
|
|
1521
1535
|
includeNull?: false
|
|
1522
1536
|
): ReturnType<C>[][];
|
|
1523
1537
|
|
|
1524
|
-
listLevels<C extends BTNCallback<
|
|
1538
|
+
listLevels<C extends BTNCallback<NODE | null>>(
|
|
1525
1539
|
callback?: C,
|
|
1526
|
-
beginRoot?: KeyOrNodeOrEntry<K, V,
|
|
1540
|
+
beginRoot?: KeyOrNodeOrEntry<K, V, NODE>,
|
|
1527
1541
|
iterationType?: IterationType,
|
|
1528
1542
|
includeNull?: true
|
|
1529
1543
|
): ReturnType<C>[][];
|
|
1530
1544
|
|
|
1545
|
+
/**
|
|
1546
|
+
* Time complexity: O(n)
|
|
1547
|
+
* Space complexity: O(n)
|
|
1548
|
+
*/
|
|
1549
|
+
|
|
1531
1550
|
/**
|
|
1532
1551
|
* Time complexity: O(n)
|
|
1533
1552
|
* Space complexity: O(n)
|
|
@@ -1536,10 +1555,10 @@ export class BinaryTree<
|
|
|
1536
1555
|
* a binary tree and contains the values returned by a callback function applied to the nodes at that
|
|
1537
1556
|
* level.
|
|
1538
1557
|
* @param {C} callback - The `callback` parameter is a function that will be called for each node in
|
|
1539
|
-
* the tree. It takes a single parameter, which can be of type `
|
|
1558
|
+
* the tree. It takes a single parameter, which can be of type `NODE`, `null`, or `undefined`, and
|
|
1540
1559
|
* returns a value of any type.
|
|
1541
|
-
* @param {K |
|
|
1542
|
-
* starting node for traversing the tree. It can be either a node object (`
|
|
1560
|
+
* @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
1561
|
+
* starting node for traversing the tree. It can be either a node object (`NODE`), a key value
|
|
1543
1562
|
* (`K`), `null`, or `undefined`. If not provided, it defaults to the root node of the tree.
|
|
1544
1563
|
* @param iterationType - The `iterationType` parameter determines the type of iteration to be
|
|
1545
1564
|
* performed on the tree. It can have two possible values:
|
|
@@ -1549,9 +1568,9 @@ export class BinaryTree<
|
|
|
1549
1568
|
* be excluded
|
|
1550
1569
|
* @returns The function `listLevels` returns a two-dimensional array of type `ReturnType<C>[][]`.
|
|
1551
1570
|
*/
|
|
1552
|
-
listLevels<C extends BTNCallback<
|
|
1571
|
+
listLevels<C extends BTNCallback<NODE | null>>(
|
|
1553
1572
|
callback: C = this._defaultOneParamCallback as C,
|
|
1554
|
-
beginRoot: KeyOrNodeOrEntry<K, V,
|
|
1573
|
+
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1555
1574
|
iterationType = this.iterationType,
|
|
1556
1575
|
includeNull = false
|
|
1557
1576
|
): ReturnType<C>[][] {
|
|
@@ -1560,7 +1579,7 @@ export class BinaryTree<
|
|
|
1560
1579
|
if (!beginRoot) return levelsNodes;
|
|
1561
1580
|
|
|
1562
1581
|
if (iterationType === IterationType.RECURSIVE) {
|
|
1563
|
-
const _recursive = (node:
|
|
1582
|
+
const _recursive = (node: NODE | null, level: number) => {
|
|
1564
1583
|
if (!levelsNodes[level]) levelsNodes[level] = [];
|
|
1565
1584
|
levelsNodes[level].push(callback(node));
|
|
1566
1585
|
if (includeNull) {
|
|
@@ -1574,7 +1593,7 @@ export class BinaryTree<
|
|
|
1574
1593
|
|
|
1575
1594
|
_recursive(beginRoot, 0);
|
|
1576
1595
|
} else {
|
|
1577
|
-
const stack: [
|
|
1596
|
+
const stack: [NODE | null, number][] = [[beginRoot, 0]];
|
|
1578
1597
|
|
|
1579
1598
|
while (stack.length > 0) {
|
|
1580
1599
|
const head = stack.pop()!;
|
|
@@ -1596,56 +1615,6 @@ export class BinaryTree<
|
|
|
1596
1615
|
return levelsNodes;
|
|
1597
1616
|
}
|
|
1598
1617
|
|
|
1599
|
-
/**
|
|
1600
|
-
* Time Complexity: O(log n)
|
|
1601
|
-
* Space Complexity: O(1)
|
|
1602
|
-
*/
|
|
1603
|
-
|
|
1604
|
-
/**
|
|
1605
|
-
* Time Complexity: O(log n)
|
|
1606
|
-
* Space Complexity: O(1)
|
|
1607
|
-
*
|
|
1608
|
-
* The function returns the predecessor of a given node in a tree.
|
|
1609
|
-
* @param {N} node - The parameter `node` is of type `RedBlackTreeNode`, which represents a node in a
|
|
1610
|
-
* tree.
|
|
1611
|
-
* @returns the predecessor of the given 'node'.
|
|
1612
|
-
*/
|
|
1613
|
-
getPredecessor(node: N): N {
|
|
1614
|
-
if (this.isRealNode(node.left)) {
|
|
1615
|
-
let predecessor: N | null | undefined = node.left;
|
|
1616
|
-
while (!this.isRealNode(predecessor) || (this.isRealNode(predecessor.right) && predecessor.right !== node)) {
|
|
1617
|
-
if (this.isRealNode(predecessor)) {
|
|
1618
|
-
predecessor = predecessor.right;
|
|
1619
|
-
}
|
|
1620
|
-
}
|
|
1621
|
-
return predecessor;
|
|
1622
|
-
} else {
|
|
1623
|
-
return node;
|
|
1624
|
-
}
|
|
1625
|
-
}
|
|
1626
|
-
|
|
1627
|
-
/**
|
|
1628
|
-
* The function `getSuccessor` returns the next node in a binary tree given a current node.
|
|
1629
|
-
* @param {K | N | null} [x] - The parameter `x` can be of type `K`, `N`, or `null`.
|
|
1630
|
-
* @returns the successor of the given node or key. The successor is the node that comes immediately
|
|
1631
|
-
* after the given node in the inorder traversal of the binary tree.
|
|
1632
|
-
*/
|
|
1633
|
-
getSuccessor(x?: K | N | null): N | null | undefined {
|
|
1634
|
-
x = this.ensureNode(x);
|
|
1635
|
-
if (!this.isRealNode(x)) return undefined;
|
|
1636
|
-
|
|
1637
|
-
if (this.isRealNode(x.right)) {
|
|
1638
|
-
return this.getLeftMost(x.right);
|
|
1639
|
-
}
|
|
1640
|
-
|
|
1641
|
-
let y: N | null | undefined = x.parent;
|
|
1642
|
-
while (this.isRealNode(y) && x === y.right) {
|
|
1643
|
-
x = y;
|
|
1644
|
-
y = y.parent;
|
|
1645
|
-
}
|
|
1646
|
-
return y;
|
|
1647
|
-
}
|
|
1648
|
-
|
|
1649
1618
|
/**
|
|
1650
1619
|
* Time complexity: O(n)
|
|
1651
1620
|
* Space complexity: O(n)
|
|
@@ -1658,31 +1627,31 @@ export class BinaryTree<
|
|
|
1658
1627
|
* The `morris` function performs a depth-first traversal on a binary tree using the Morris traversal
|
|
1659
1628
|
* algorithm.
|
|
1660
1629
|
* @param {C} callback - The `callback` parameter is a function that will be called for each node in
|
|
1661
|
-
* the tree. It takes a single parameter of type `
|
|
1630
|
+
* the tree. It takes a single parameter of type `NODE` (the type of the nodes in the tree) and returns
|
|
1662
1631
|
* a value of any type.
|
|
1663
1632
|
* @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter in the `morris` function
|
|
1664
1633
|
* determines the order in which the nodes of a binary tree are traversed. It can have one of the
|
|
1665
1634
|
* following values:
|
|
1666
|
-
* @param {K |
|
|
1635
|
+
* @param {K | NODE | null | undefined} beginRoot - The `beginRoot` parameter is the starting node
|
|
1667
1636
|
* for the traversal. It can be specified as a key, a node object, or `null`/`undefined` to indicate
|
|
1668
1637
|
* the root of the tree. If no value is provided, the default value is the root of the tree.
|
|
1669
1638
|
* @returns The function `morris` returns an array of values that are the result of invoking the
|
|
1670
1639
|
* `callback` function on each node in the binary tree. The type of the array nodes is determined
|
|
1671
1640
|
* by the return type of the `callback` function.
|
|
1672
1641
|
*/
|
|
1673
|
-
morris<C extends BTNCallback<
|
|
1642
|
+
morris<C extends BTNCallback<NODE>>(
|
|
1674
1643
|
callback: C = this._defaultOneParamCallback as C,
|
|
1675
1644
|
pattern: DFSOrderPattern = 'in',
|
|
1676
|
-
beginRoot: KeyOrNodeOrEntry<K, V,
|
|
1645
|
+
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root
|
|
1677
1646
|
): ReturnType<C>[] {
|
|
1678
1647
|
beginRoot = this.ensureNode(beginRoot);
|
|
1679
1648
|
if (beginRoot === null) return [];
|
|
1680
|
-
const ans: ReturnType<BTNCallback<
|
|
1649
|
+
const ans: ReturnType<BTNCallback<NODE>>[] = [];
|
|
1681
1650
|
|
|
1682
|
-
let cur:
|
|
1683
|
-
const _reverseEdge = (node:
|
|
1684
|
-
let pre:
|
|
1685
|
-
let next:
|
|
1651
|
+
let cur: NODE | null | undefined = beginRoot;
|
|
1652
|
+
const _reverseEdge = (node: NODE | null | undefined) => {
|
|
1653
|
+
let pre: NODE | null | undefined = null;
|
|
1654
|
+
let next: NODE | null | undefined = null;
|
|
1686
1655
|
while (node) {
|
|
1687
1656
|
next = node.right;
|
|
1688
1657
|
node.right = pre;
|
|
@@ -1691,9 +1660,9 @@ export class BinaryTree<
|
|
|
1691
1660
|
}
|
|
1692
1661
|
return pre;
|
|
1693
1662
|
};
|
|
1694
|
-
const _printEdge = (node:
|
|
1695
|
-
const tail:
|
|
1696
|
-
let cur:
|
|
1663
|
+
const _printEdge = (node: NODE | null | undefined) => {
|
|
1664
|
+
const tail: NODE | null | undefined = _reverseEdge(node);
|
|
1665
|
+
let cur: NODE | null | undefined = tail;
|
|
1697
1666
|
while (cur) {
|
|
1698
1667
|
ans.push(callback(cur));
|
|
1699
1668
|
cur = cur.right;
|
|
@@ -1771,7 +1740,15 @@ export class BinaryTree<
|
|
|
1771
1740
|
*/
|
|
1772
1741
|
clone(): TREE {
|
|
1773
1742
|
const cloned = this.createTree();
|
|
1774
|
-
this.bfs(
|
|
1743
|
+
this.bfs(
|
|
1744
|
+
node => {
|
|
1745
|
+
if (node === null) cloned.add(null);
|
|
1746
|
+
else cloned.add([node.key, node.value]);
|
|
1747
|
+
},
|
|
1748
|
+
this.root,
|
|
1749
|
+
this.iterationType,
|
|
1750
|
+
true
|
|
1751
|
+
);
|
|
1775
1752
|
return cloned;
|
|
1776
1753
|
}
|
|
1777
1754
|
|
|
@@ -1855,12 +1832,12 @@ export class BinaryTree<
|
|
|
1855
1832
|
* Space Complexity: O(n)
|
|
1856
1833
|
*
|
|
1857
1834
|
* The `print` function is used to display a binary tree structure in a visually appealing way.
|
|
1858
|
-
* @param {K |
|
|
1835
|
+
* @param {K | NODE | null | undefined} [beginRoot=this.root] - The `root` parameter is of type `K | NODE | null |
|
|
1859
1836
|
* undefined`. It represents the root node of a binary tree. The root node can have one of the
|
|
1860
1837
|
* following types:
|
|
1861
1838
|
* @param {BinaryTreePrintOptions} [options={ isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false}] - Options object that controls printing behavior. You can specify whether to display undefined, null, or sentinel nodes.
|
|
1862
1839
|
*/
|
|
1863
|
-
print(beginRoot: KeyOrNodeOrEntry<K, V,
|
|
1840
|
+
print(beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root, options?: BinaryTreePrintOptions): void {
|
|
1864
1841
|
const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options };
|
|
1865
1842
|
beginRoot = this.ensureNode(beginRoot);
|
|
1866
1843
|
if (!beginRoot) return;
|
|
@@ -1869,13 +1846,13 @@ export class BinaryTree<
|
|
|
1869
1846
|
console.log(`U for undefined
|
|
1870
1847
|
`);
|
|
1871
1848
|
if (opts.isShowNull)
|
|
1872
|
-
console.log(`
|
|
1849
|
+
console.log(`NODE for null
|
|
1873
1850
|
`);
|
|
1874
1851
|
if (opts.isShowRedBlackNIL)
|
|
1875
1852
|
console.log(`S for Sentinel Node
|
|
1876
1853
|
`);
|
|
1877
1854
|
|
|
1878
|
-
const display = (root:
|
|
1855
|
+
const display = (root: NODE | null | undefined): void => {
|
|
1879
1856
|
const [lines, , ,] = this._displayAux(root, opts);
|
|
1880
1857
|
for (const line of lines) {
|
|
1881
1858
|
console.log(line);
|
|
@@ -1885,12 +1862,21 @@ export class BinaryTree<
|
|
|
1885
1862
|
display(beginRoot);
|
|
1886
1863
|
}
|
|
1887
1864
|
|
|
1865
|
+
/**
|
|
1866
|
+
* The function `_getIterator` is a protected generator function that returns an iterator for the
|
|
1867
|
+
* key-value pairs in a binary search tree.
|
|
1868
|
+
* @param node - The `node` parameter represents the current node in the binary search tree. It is an
|
|
1869
|
+
* optional parameter with a default value of `this.root`, which means if no node is provided, the
|
|
1870
|
+
* root node of the tree will be used as the starting point for iteration.
|
|
1871
|
+
* @returns The function `_getIterator` returns an `IterableIterator` of key-value pairs `[K, V |
|
|
1872
|
+
* undefined]`.
|
|
1873
|
+
*/
|
|
1888
1874
|
protected* _getIterator(node = this.root): IterableIterator<[K, V | undefined]> {
|
|
1889
1875
|
if (!node) return;
|
|
1890
1876
|
|
|
1891
1877
|
if (this.iterationType === IterationType.ITERATIVE) {
|
|
1892
|
-
const stack: (
|
|
1893
|
-
let current:
|
|
1878
|
+
const stack: (NODE | null | undefined)[] = [];
|
|
1879
|
+
let current: NODE | null | undefined = node;
|
|
1894
1880
|
|
|
1895
1881
|
while (current || stack.length > 0) {
|
|
1896
1882
|
while (current && !isNaN(this.extractor(current.key))) {
|
|
@@ -1916,7 +1902,21 @@ export class BinaryTree<
|
|
|
1916
1902
|
}
|
|
1917
1903
|
}
|
|
1918
1904
|
|
|
1919
|
-
|
|
1905
|
+
/**
|
|
1906
|
+
* The `_displayAux` function is responsible for generating the display layout of a binary tree node,
|
|
1907
|
+
* taking into account various options such as whether to show null, undefined, or NaN nodes.
|
|
1908
|
+
* @param {NODE | null | undefined} node - The `node` parameter represents a node in a binary tree.
|
|
1909
|
+
* It can be of type `NODE`, `null`, or `undefined`.
|
|
1910
|
+
* @param {BinaryTreePrintOptions} options - The `options` parameter is an object that contains the
|
|
1911
|
+
* following properties:
|
|
1912
|
+
* @returns The function `_displayAux` returns a `NodeDisplayLayout` which is an array containing the
|
|
1913
|
+
* following elements:
|
|
1914
|
+
* 1. `mergedLines`: An array of strings representing the lines of the node display.
|
|
1915
|
+
* 2. `totalWidth`: The total width of the node display.
|
|
1916
|
+
* 3. `totalHeight`: The total height of the node display.
|
|
1917
|
+
* 4. `middleIndex`: The index of the middle character
|
|
1918
|
+
*/
|
|
1919
|
+
protected _displayAux(node: NODE | null | undefined, options: BinaryTreePrintOptions): NodeDisplayLayout {
|
|
1920
1920
|
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
1921
1921
|
const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];
|
|
1922
1922
|
|
|
@@ -1942,7 +1942,7 @@ export class BinaryTree<
|
|
|
1942
1942
|
);
|
|
1943
1943
|
} else {
|
|
1944
1944
|
// For cases where none of the conditions are met, null, undefined, and NaN nodes are not displayed
|
|
1945
|
-
const line = node === undefined ? 'U' : '
|
|
1945
|
+
const line = node === undefined ? 'U' : 'NODE',
|
|
1946
1946
|
width = line.length;
|
|
1947
1947
|
|
|
1948
1948
|
return _buildNodeDisplay(line, width, [[''], 1, 0, 0], [[''], 1, 0, 0]);
|
|
@@ -1984,15 +1984,18 @@ export class BinaryTree<
|
|
|
1984
1984
|
}
|
|
1985
1985
|
}
|
|
1986
1986
|
|
|
1987
|
-
protected _defaultOneParamCallback = (node:
|
|
1987
|
+
protected _defaultOneParamCallback = (node: NODE | null | undefined) => (node ? node.key : undefined);
|
|
1988
1988
|
|
|
1989
1989
|
/**
|
|
1990
1990
|
* Swap the data of two nodes in the binary tree.
|
|
1991
|
-
* @param {
|
|
1992
|
-
* @param {
|
|
1993
|
-
* @returns {
|
|
1994
|
-
*/
|
|
1995
|
-
protected _swapProperties(
|
|
1991
|
+
* @param {NODE} srcNode - The source node to swap.
|
|
1992
|
+
* @param {NODE} destNode - The destination node to swap.
|
|
1993
|
+
* @returns {NODE} - The destination node after the swap.
|
|
1994
|
+
*/
|
|
1995
|
+
protected _swapProperties(
|
|
1996
|
+
srcNode: KeyOrNodeOrEntry<K, V, NODE>,
|
|
1997
|
+
destNode: KeyOrNodeOrEntry<K, V, NODE>
|
|
1998
|
+
): NODE | undefined {
|
|
1996
1999
|
srcNode = this.ensureNode(srcNode);
|
|
1997
2000
|
destNode = this.ensureNode(destNode);
|
|
1998
2001
|
|
|
@@ -2015,13 +2018,13 @@ export class BinaryTree<
|
|
|
2015
2018
|
|
|
2016
2019
|
/**
|
|
2017
2020
|
* The function replaces an old node with a new node in a binary tree.
|
|
2018
|
-
* @param {
|
|
2021
|
+
* @param {NODE} oldNode - The oldNode parameter represents the node that needs to be replaced in the
|
|
2019
2022
|
* tree.
|
|
2020
|
-
* @param {
|
|
2023
|
+
* @param {NODE} newNode - The `newNode` parameter is the node that will replace the `oldNode` in the
|
|
2021
2024
|
* tree.
|
|
2022
2025
|
* @returns The method is returning the newNode.
|
|
2023
2026
|
*/
|
|
2024
|
-
protected _replaceNode(oldNode:
|
|
2027
|
+
protected _replaceNode(oldNode: NODE, newNode: NODE): NODE {
|
|
2025
2028
|
if (oldNode.parent) {
|
|
2026
2029
|
if (oldNode.parent.left === oldNode) {
|
|
2027
2030
|
oldNode.parent.left = newNode;
|
|
@@ -2042,10 +2045,10 @@ export class BinaryTree<
|
|
|
2042
2045
|
/**
|
|
2043
2046
|
* The function sets the root property of an object to a given value, and if the value is not null,
|
|
2044
2047
|
* it also sets the parent property of the value to undefined.
|
|
2045
|
-
* @param {
|
|
2046
|
-
* type `
|
|
2048
|
+
* @param {NODE | null | undefined} v - The parameter `v` is of type `NODE | null | undefined`, which means it can either be of
|
|
2049
|
+
* type `NODE` or `null`.
|
|
2047
2050
|
*/
|
|
2048
|
-
protected _setRoot(v:
|
|
2051
|
+
protected _setRoot(v: NODE | null | undefined) {
|
|
2049
2052
|
if (v) {
|
|
2050
2053
|
v.parent = undefined;
|
|
2051
2054
|
}
|