graph-typed 1.52.8 → 1.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +22 -22
- package/dist/data-structures/binary-tree/avl-tree-multi-map.js +64 -47
- package/dist/data-structures/binary-tree/avl-tree.d.ts +20 -20
- package/dist/data-structures/binary-tree/avl-tree.js +28 -26
- package/dist/data-structures/binary-tree/binary-tree.d.ts +240 -141
- package/dist/data-structures/binary-tree/binary-tree.js +395 -269
- package/dist/data-structures/binary-tree/bst.d.ts +56 -56
- package/dist/data-structures/binary-tree/bst.js +114 -91
- package/dist/data-structures/binary-tree/rb-tree.d.ts +13 -13
- package/dist/data-structures/binary-tree/rb-tree.js +35 -31
- package/dist/data-structures/binary-tree/tree-multi-map.d.ts +22 -23
- package/dist/data-structures/binary-tree/tree-multi-map.js +59 -48
- package/dist/data-structures/trie/trie.js +3 -3
- package/dist/interfaces/binary-tree.d.ts +5 -5
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +13 -13
- package/dist/types/data-structures/binary-tree/bst.d.ts +3 -3
- package/package.json +2 -2
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +60 -55
- package/src/data-structures/binary-tree/avl-tree.ts +31 -35
- package/src/data-structures/binary-tree/binary-tree.ts +461 -385
- package/src/data-structures/binary-tree/bst.ts +155 -128
- package/src/data-structures/binary-tree/rb-tree.ts +37 -39
- package/src/data-structures/binary-tree/tree-multi-map.ts +57 -60
- package/src/data-structures/trie/trie.ts +3 -3
- package/src/interfaces/binary-tree.ts +6 -6
- package/src/types/data-structures/binary-tree/binary-tree.ts +14 -15
- package/src/types/data-structures/binary-tree/bst.ts +4 -4
|
@@ -6,23 +6,24 @@
|
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import
|
|
9
|
+
import {
|
|
10
10
|
BinaryTreeDeleteResult,
|
|
11
11
|
BinaryTreeNested,
|
|
12
12
|
BinaryTreeNodeNested,
|
|
13
13
|
BinaryTreeOptions,
|
|
14
14
|
BinaryTreePrintOptions,
|
|
15
|
-
BTNCallback,
|
|
16
15
|
BTNEntry,
|
|
17
|
-
|
|
18
|
-
BTNPredicate,
|
|
16
|
+
BTNRep,
|
|
19
17
|
DFSOrderPattern,
|
|
20
18
|
DFSStackItem,
|
|
21
19
|
EntryCallback,
|
|
22
20
|
FamilyPosition,
|
|
23
21
|
IterationType,
|
|
22
|
+
NodeCallback,
|
|
24
23
|
NodeDisplayLayout,
|
|
25
|
-
|
|
24
|
+
NodePredicate,
|
|
25
|
+
OptNodeOrNull,
|
|
26
|
+
ToEntryFn
|
|
26
27
|
} from '../../types';
|
|
27
28
|
import { IBinaryTree } from '../../interfaces';
|
|
28
29
|
import { isComparable, trampoline } from '../../utils';
|
|
@@ -51,26 +52,26 @@ export class BinaryTreeNode<
|
|
|
51
52
|
this.value = value;
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
protected _left?:
|
|
55
|
+
protected _left?: OptNodeOrNull<NODE>;
|
|
55
56
|
|
|
56
|
-
get left():
|
|
57
|
+
get left(): OptNodeOrNull<NODE> {
|
|
57
58
|
return this._left;
|
|
58
59
|
}
|
|
59
60
|
|
|
60
|
-
set left(v:
|
|
61
|
+
set left(v: OptNodeOrNull<NODE>) {
|
|
61
62
|
if (v) {
|
|
62
63
|
v.parent = this as unknown as NODE;
|
|
63
64
|
}
|
|
64
65
|
this._left = v;
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
protected _right?:
|
|
68
|
+
protected _right?: OptNodeOrNull<NODE>;
|
|
68
69
|
|
|
69
|
-
get right():
|
|
70
|
+
get right(): OptNodeOrNull<NODE> {
|
|
70
71
|
return this._right;
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
set right(v:
|
|
74
|
+
set right(v: OptNodeOrNull<NODE>) {
|
|
74
75
|
if (v) {
|
|
75
76
|
v.parent = this as unknown as NODE;
|
|
76
77
|
}
|
|
@@ -103,7 +104,7 @@ export class BinaryTreeNode<
|
|
|
103
104
|
export class BinaryTree<
|
|
104
105
|
K = any,
|
|
105
106
|
V = any,
|
|
106
|
-
R =
|
|
107
|
+
R = object,
|
|
107
108
|
NODE extends BinaryTreeNode<K, V, NODE> = BinaryTreeNode<K, V, BinaryTreeNodeNested<K, V>>,
|
|
108
109
|
TREE extends BinaryTree<K, V, R, NODE, TREE> = BinaryTree<K, V, R, NODE, BinaryTreeNested<K, V, R, NODE>>
|
|
109
110
|
>
|
|
@@ -115,30 +116,40 @@ export class BinaryTree<
|
|
|
115
116
|
/**
|
|
116
117
|
* The constructor initializes a binary tree with optional options and adds keys, nodes, entries, or
|
|
117
118
|
* raw data if provided.
|
|
118
|
-
* @param
|
|
119
|
-
* is an iterable that can contain elements of type `
|
|
119
|
+
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor
|
|
120
|
+
* is an iterable that can contain elements of type `BTNRep<K, V, NODE>` or `R`. It is
|
|
120
121
|
* initialized with an empty array `[]` by default.
|
|
121
122
|
* @param [options] - The `options` parameter in the constructor is an object that can contain the
|
|
122
123
|
* following properties:
|
|
123
124
|
*/
|
|
124
|
-
constructor(
|
|
125
|
-
keysOrNodesOrEntriesOrRaws: Iterable<BTNKeyOrNodeOrEntry<K, V, NODE> | R> = [],
|
|
126
|
-
options?: BinaryTreeOptions<K, V, R>
|
|
127
|
-
) {
|
|
125
|
+
constructor(keysNodesEntriesOrRaws: Iterable<BTNRep<K, V, NODE> | R> = [], options?: BinaryTreeOptions<K, V, R>) {
|
|
128
126
|
super();
|
|
129
127
|
if (options) {
|
|
130
|
-
const { iterationType, toEntryFn } = options;
|
|
128
|
+
const { iterationType, toEntryFn, isMapMode } = options;
|
|
131
129
|
if (iterationType) this.iterationType = iterationType;
|
|
130
|
+
if (isMapMode !== undefined) this._isMapMode = isMapMode;
|
|
132
131
|
if (typeof toEntryFn === 'function') this._toEntryFn = toEntryFn;
|
|
133
132
|
else if (toEntryFn) throw TypeError('toEntryFn must be a function type');
|
|
134
133
|
}
|
|
135
134
|
|
|
136
|
-
if (
|
|
135
|
+
if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);
|
|
137
136
|
}
|
|
138
137
|
|
|
139
|
-
protected
|
|
138
|
+
protected _isMapMode = false;
|
|
140
139
|
|
|
141
|
-
get
|
|
140
|
+
get isMapMode() {
|
|
141
|
+
return this._isMapMode;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
protected _store = new Map<K, V | undefined>();
|
|
145
|
+
|
|
146
|
+
get store() {
|
|
147
|
+
return this._store;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
protected _root?: OptNodeOrNull<NODE>;
|
|
151
|
+
|
|
152
|
+
get root(): OptNodeOrNull<NODE> {
|
|
142
153
|
return this._root;
|
|
143
154
|
}
|
|
144
155
|
|
|
@@ -154,7 +165,7 @@ export class BinaryTree<
|
|
|
154
165
|
return this._NIL;
|
|
155
166
|
}
|
|
156
167
|
|
|
157
|
-
protected _toEntryFn?:
|
|
168
|
+
protected _toEntryFn?: ToEntryFn<K, V, R>;
|
|
158
169
|
|
|
159
170
|
get toEntryFn() {
|
|
160
171
|
return this._toEntryFn;
|
|
@@ -184,51 +195,56 @@ export class BinaryTree<
|
|
|
184
195
|
createTree(options?: BinaryTreeOptions<K, V, R>): TREE {
|
|
185
196
|
return new BinaryTree<K, V, R, NODE, TREE>([], {
|
|
186
197
|
iterationType: this.iterationType,
|
|
198
|
+
isMapMode: this._isMapMode,
|
|
187
199
|
toEntryFn: this._toEntryFn,
|
|
188
200
|
...options
|
|
189
201
|
}) as TREE;
|
|
190
202
|
}
|
|
191
203
|
|
|
192
204
|
/**
|
|
193
|
-
* The function `
|
|
205
|
+
* The function `keyValueNodeEntryRawToNodeAndValue` converts various input types into a node object
|
|
194
206
|
* or returns null.
|
|
195
|
-
* @param {
|
|
196
|
-
* `
|
|
197
|
-
* can be of type `
|
|
207
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The
|
|
208
|
+
* `keyValueNodeEntryRawToNodeAndValue` function takes in a parameter `keyNodeEntryOrRaw`, which
|
|
209
|
+
* can be of type `BTNRep<K, V, NODE>` or `R`. This parameter represents either a key, a
|
|
198
210
|
* node, an entry
|
|
199
|
-
* @param {V} [value] - The `value` parameter in the `
|
|
211
|
+
* @param {V} [value] - The `value` parameter in the `keyValueNodeEntryRawToNodeAndValue` function is
|
|
200
212
|
* an optional parameter of type `V`. It represents the value associated with the key in the node
|
|
201
213
|
* being created. If a `value` is provided, it will be used when creating the node. If
|
|
202
|
-
* @returns The `
|
|
203
|
-
* (`
|
|
204
|
-
* input parameter (`
|
|
214
|
+
* @returns The `keyValueNodeEntryRawToNodeAndValue` function returns an optional node
|
|
215
|
+
* (`OptNodeOrNull<NODE>`) based on the input parameters provided. The function checks the type of the
|
|
216
|
+
* input parameter (`keyNodeEntryOrRaw`) and processes it accordingly to return a node or null
|
|
205
217
|
* value.
|
|
206
218
|
*/
|
|
207
|
-
|
|
208
|
-
|
|
219
|
+
keyValueNodeEntryRawToNodeAndValue(
|
|
220
|
+
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
|
|
209
221
|
value?: V
|
|
210
|
-
):
|
|
211
|
-
if (
|
|
212
|
-
if (
|
|
213
|
-
|
|
214
|
-
if (this.isNode(
|
|
215
|
-
|
|
216
|
-
if (this.isEntry(
|
|
217
|
-
const [key, entryValue] =
|
|
218
|
-
if (key === undefined) return;
|
|
219
|
-
else if (key === null) return null;
|
|
220
|
-
|
|
222
|
+
): [OptNodeOrNull<NODE>, V | undefined] {
|
|
223
|
+
if (keyNodeEntryOrRaw === undefined) return [undefined, undefined];
|
|
224
|
+
if (keyNodeEntryOrRaw === null) return [null, undefined];
|
|
225
|
+
|
|
226
|
+
if (this.isNode(keyNodeEntryOrRaw)) return [keyNodeEntryOrRaw, value];
|
|
227
|
+
|
|
228
|
+
if (this.isEntry(keyNodeEntryOrRaw)) {
|
|
229
|
+
const [key, entryValue] = keyNodeEntryOrRaw;
|
|
230
|
+
if (key === undefined) return [undefined, undefined];
|
|
231
|
+
else if (key === null) return [null, undefined];
|
|
232
|
+
const finalValue = value ?? entryValue;
|
|
233
|
+
return [this.createNode(key, finalValue), finalValue];
|
|
221
234
|
}
|
|
222
235
|
|
|
223
|
-
if (this.
|
|
224
|
-
const [key, entryValue] = this._toEntryFn(keyOrNodeOrEntryOrRaw as R);
|
|
225
|
-
if (this.isKey(key)) return this.createNode(key, value ?? entryValue);
|
|
226
|
-
else return;
|
|
227
|
-
}
|
|
236
|
+
if (this.isKey(keyNodeEntryOrRaw)) return [this.createNode(keyNodeEntryOrRaw, value), value];
|
|
228
237
|
|
|
229
|
-
if (this.
|
|
238
|
+
if (this.isRaw(keyNodeEntryOrRaw)) {
|
|
239
|
+
if (this._toEntryFn) {
|
|
240
|
+
const [key, entryValue] = this._toEntryFn(keyNodeEntryOrRaw);
|
|
241
|
+
const finalValue = value ?? entryValue;
|
|
242
|
+
if (this.isKey(key)) return [this.createNode(key, finalValue), finalValue];
|
|
243
|
+
}
|
|
244
|
+
return [undefined, undefined];
|
|
245
|
+
}
|
|
230
246
|
|
|
231
|
-
return;
|
|
247
|
+
return [undefined, undefined];
|
|
232
248
|
}
|
|
233
249
|
|
|
234
250
|
/**
|
|
@@ -237,8 +253,8 @@ export class BinaryTree<
|
|
|
237
253
|
*
|
|
238
254
|
* The function `ensureNode` in TypeScript checks if a given input is a node, entry, key, or raw
|
|
239
255
|
* value and returns the corresponding node or null.
|
|
240
|
-
* @param {
|
|
241
|
-
* parameter in the `ensureNode` function can be of type `
|
|
256
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The `keyNodeEntryOrRaw`
|
|
257
|
+
* parameter in the `ensureNode` function can be of type `BTNRep<K, V, NODE>` or `R`. It
|
|
242
258
|
* is used to determine whether the input is a key, node, entry, or raw data. The
|
|
243
259
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `ensureNode` function
|
|
244
260
|
* is used to specify the type of iteration to be performed. It has a default value of
|
|
@@ -247,114 +263,117 @@ export class BinaryTree<
|
|
|
247
263
|
* conditions specified in the code snippet.
|
|
248
264
|
*/
|
|
249
265
|
ensureNode(
|
|
250
|
-
|
|
266
|
+
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
|
|
251
267
|
iterationType: IterationType = this.iterationType
|
|
252
|
-
):
|
|
253
|
-
if (
|
|
254
|
-
if (
|
|
255
|
-
if (
|
|
256
|
-
if (this.isNode(
|
|
257
|
-
|
|
258
|
-
if (this.isEntry(
|
|
259
|
-
const key =
|
|
268
|
+
): OptNodeOrNull<NODE> {
|
|
269
|
+
if (keyNodeEntryOrRaw === null) return null;
|
|
270
|
+
if (keyNodeEntryOrRaw === undefined) return;
|
|
271
|
+
if (keyNodeEntryOrRaw === this._NIL) return;
|
|
272
|
+
if (this.isNode(keyNodeEntryOrRaw)) return keyNodeEntryOrRaw;
|
|
273
|
+
|
|
274
|
+
if (this.isEntry(keyNodeEntryOrRaw)) {
|
|
275
|
+
const key = keyNodeEntryOrRaw[0];
|
|
260
276
|
if (key === null) return null;
|
|
261
277
|
if (key === undefined) return;
|
|
262
278
|
return this.getNodeByKey(key, iterationType);
|
|
263
279
|
}
|
|
264
280
|
|
|
265
281
|
if (this._toEntryFn) {
|
|
266
|
-
const [key] = this._toEntryFn(
|
|
282
|
+
const [key] = this._toEntryFn(keyNodeEntryOrRaw as R);
|
|
267
283
|
if (this.isKey(key)) return this.getNodeByKey(key);
|
|
268
284
|
}
|
|
269
285
|
|
|
270
|
-
if (this.isKey(
|
|
286
|
+
if (this.isKey(keyNodeEntryOrRaw)) return this.getNodeByKey(keyNodeEntryOrRaw, iterationType);
|
|
271
287
|
return;
|
|
272
288
|
}
|
|
273
289
|
|
|
274
290
|
/**
|
|
275
291
|
* The function isNode checks if the input is an instance of BinaryTreeNode.
|
|
276
|
-
* @param {
|
|
277
|
-
* `
|
|
292
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
|
|
293
|
+
* `keyNodeEntryOrRaw` can be either a key, a node, an entry, or raw data. The function is
|
|
278
294
|
* checking if the input is an instance of a `BinaryTreeNode` and returning a boolean value
|
|
279
295
|
* accordingly.
|
|
280
|
-
* @returns The function `isNode` is checking if the input `
|
|
296
|
+
* @returns The function `isNode` is checking if the input `keyNodeEntryOrRaw` is an instance of
|
|
281
297
|
* `BinaryTreeNode`. If it is, the function returns `true`, indicating that the input is a node. If
|
|
282
298
|
* it is not an instance of `BinaryTreeNode`, the function returns `false`, indicating that the input
|
|
283
299
|
* is not a node.
|
|
284
300
|
*/
|
|
285
|
-
isNode(
|
|
286
|
-
return
|
|
301
|
+
isNode(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): keyNodeEntryOrRaw is NODE {
|
|
302
|
+
return keyNodeEntryOrRaw instanceof BinaryTreeNode;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
isRaw(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): keyNodeEntryOrRaw is R {
|
|
306
|
+
return typeof keyNodeEntryOrRaw === 'object';
|
|
287
307
|
}
|
|
288
308
|
|
|
289
309
|
/**
|
|
290
310
|
* The function `isRealNode` checks if a given input is a valid node in a binary tree.
|
|
291
|
-
* @param {
|
|
292
|
-
* parameter in the `isRealNode` function can be of type `
|
|
311
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The `keyNodeEntryOrRaw`
|
|
312
|
+
* parameter in the `isRealNode` function can be of type `BTNRep<K, V, NODE>` or `R`.
|
|
293
313
|
* The function checks if the input parameter is a `NODE` type by verifying if it is not equal
|
|
294
|
-
* @returns The function `isRealNode` is checking if the input `
|
|
314
|
+
* @returns The function `isRealNode` is checking if the input `keyNodeEntryOrRaw` is a valid
|
|
295
315
|
* node by comparing it to `this._NIL`, `null`, and `undefined`. If the input is not one of these
|
|
296
316
|
* values, it then calls the `isNode` method to further determine if the input is a node. The
|
|
297
317
|
* function will return a boolean value indicating whether the
|
|
298
318
|
*/
|
|
299
|
-
isRealNode(
|
|
300
|
-
if (
|
|
301
|
-
|
|
302
|
-
return this.isNode(keyOrNodeOrEntryOrRaw);
|
|
319
|
+
isRealNode(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): keyNodeEntryOrRaw is NODE {
|
|
320
|
+
if (keyNodeEntryOrRaw === this._NIL || keyNodeEntryOrRaw === null || keyNodeEntryOrRaw === undefined) return false;
|
|
321
|
+
return this.isNode(keyNodeEntryOrRaw);
|
|
303
322
|
}
|
|
304
323
|
|
|
305
324
|
/**
|
|
306
325
|
* The function checks if a given input is a valid node or null.
|
|
307
|
-
* @param {
|
|
308
|
-
* `
|
|
326
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
|
|
327
|
+
* `keyNodeEntryOrRaw` in the `isRealNodeOrNull` function can be of type `BTNRep<K,
|
|
309
328
|
* V, NODE>` or `R`. It is a union type that can either be a key, a node, an entry, or
|
|
310
329
|
* @returns The function `isRealNodeOrNull` is returning a boolean value. It checks if the input
|
|
311
|
-
* `
|
|
330
|
+
* `keyNodeEntryOrRaw` is either `null` or a real node, and returns `true` if it is a node or
|
|
312
331
|
* `null`, and `false` otherwise.
|
|
313
332
|
*/
|
|
314
|
-
isRealNodeOrNull(
|
|
315
|
-
return
|
|
333
|
+
isRealNodeOrNull(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): keyNodeEntryOrRaw is NODE | null {
|
|
334
|
+
return keyNodeEntryOrRaw === null || this.isRealNode(keyNodeEntryOrRaw);
|
|
316
335
|
}
|
|
317
336
|
|
|
318
337
|
/**
|
|
319
338
|
* The function isNIL checks if a given key, node, entry, or raw value is equal to the _NIL value.
|
|
320
|
-
* @param {
|
|
339
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - BTNRep<K, V,
|
|
321
340
|
* NODE> | R
|
|
322
|
-
* @returns The function is checking if the `
|
|
341
|
+
* @returns The function is checking if the `keyNodeEntryOrRaw` parameter is equal to the `_NIL`
|
|
323
342
|
* property of the current object and returning a boolean value based on that comparison.
|
|
324
343
|
*/
|
|
325
|
-
isNIL(
|
|
326
|
-
return
|
|
344
|
+
isNIL(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): boolean {
|
|
345
|
+
return keyNodeEntryOrRaw === this._NIL;
|
|
327
346
|
}
|
|
328
347
|
|
|
329
348
|
/**
|
|
330
349
|
* The function determines whether a given key, node, entry, or raw data is a leaf node in a binary
|
|
331
350
|
* tree.
|
|
332
|
-
* @param {
|
|
333
|
-
* `
|
|
351
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
|
|
352
|
+
* `keyNodeEntryOrRaw` can be of type `BTNRep<K, V, NODE>` or `R`. It represents a
|
|
334
353
|
* key, node, entry, or raw data in a binary tree structure. The function `isLeaf` checks whether the
|
|
335
354
|
* provided
|
|
336
355
|
* @returns The function `isLeaf` returns a boolean value indicating whether the input
|
|
337
|
-
* `
|
|
356
|
+
* `keyNodeEntryOrRaw` is a leaf node in a binary tree.
|
|
338
357
|
*/
|
|
339
|
-
isLeaf(
|
|
340
|
-
|
|
341
|
-
if (
|
|
342
|
-
if (
|
|
343
|
-
return !this.isRealNode(
|
|
358
|
+
isLeaf(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): boolean {
|
|
359
|
+
keyNodeEntryOrRaw = this.ensureNode(keyNodeEntryOrRaw);
|
|
360
|
+
if (keyNodeEntryOrRaw === undefined) return false;
|
|
361
|
+
if (keyNodeEntryOrRaw === null) return true;
|
|
362
|
+
return !this.isRealNode(keyNodeEntryOrRaw.left) && !this.isRealNode(keyNodeEntryOrRaw.right);
|
|
344
363
|
}
|
|
345
364
|
|
|
346
365
|
/**
|
|
347
366
|
* The function `isEntry` checks if the input is a BTNEntry object by verifying if it is an array
|
|
348
367
|
* with a length of 2.
|
|
349
|
-
* @param {
|
|
350
|
-
* parameter in the `isEntry` function can be of type `
|
|
351
|
-
* The function checks if the provided `
|
|
352
|
-
* @returns The `isEntry` function is checking if the `
|
|
368
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The `keyNodeEntryOrRaw`
|
|
369
|
+
* parameter in the `isEntry` function can be of type `BTNRep<K, V, NODE>` or type `R`.
|
|
370
|
+
* The function checks if the provided `keyNodeEntryOrRaw` is of type `BTN
|
|
371
|
+
* @returns The `isEntry` function is checking if the `keyNodeEntryOrRaw` parameter is an array
|
|
353
372
|
* with a length of 2. If it is, then it returns `true`, indicating that the parameter is of type
|
|
354
373
|
* `BTNEntry<K, V>`. If the condition is not met, it returns `false`.
|
|
355
374
|
*/
|
|
356
|
-
isEntry(
|
|
357
|
-
return Array.isArray(
|
|
375
|
+
isEntry(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): keyNodeEntryOrRaw is BTNEntry<K, V> {
|
|
376
|
+
return Array.isArray(keyNodeEntryOrRaw) && keyNodeEntryOrRaw.length === 2;
|
|
358
377
|
}
|
|
359
378
|
|
|
360
379
|
/**
|
|
@@ -379,8 +398,8 @@ export class BinaryTree<
|
|
|
379
398
|
*
|
|
380
399
|
* The `add` function in TypeScript adds a new node to a binary tree while handling duplicate keys
|
|
381
400
|
* and finding the correct insertion position.
|
|
382
|
-
* @param {
|
|
383
|
-
* seems to be for adding a new node to a binary tree structure. The `
|
|
401
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The `add` method you provided
|
|
402
|
+
* seems to be for adding a new node to a binary tree structure. The `keyNodeEntryOrRaw`
|
|
384
403
|
* parameter in the method can accept different types of values:
|
|
385
404
|
* @param {V} [value] - The `value` parameter in the `add` method represents the value associated
|
|
386
405
|
* with the key that you want to add to the binary tree. When adding a key-value pair to the binary
|
|
@@ -390,13 +409,14 @@ export class BinaryTree<
|
|
|
390
409
|
* node was successful, and `false` if the insertion position could not be found or if a duplicate
|
|
391
410
|
* key was found and the node was replaced instead of inserted.
|
|
392
411
|
*/
|
|
393
|
-
add(
|
|
394
|
-
const newNode = this.
|
|
412
|
+
add(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V): boolean {
|
|
413
|
+
const [newNode, newValue] = this.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
|
|
395
414
|
if (newNode === undefined) return false;
|
|
396
415
|
|
|
397
416
|
// If the tree is empty, directly set the new node as the root node
|
|
398
417
|
if (!this._root) {
|
|
399
418
|
this._setRoot(newNode);
|
|
419
|
+
if (this._isMapMode) this._setValue(newNode?.key, newValue);
|
|
400
420
|
this._size = 1;
|
|
401
421
|
return true;
|
|
402
422
|
}
|
|
@@ -412,6 +432,7 @@ export class BinaryTree<
|
|
|
412
432
|
// Check for duplicate keys when newNode is not null
|
|
413
433
|
if (newNode !== null && cur.key === newNode.key) {
|
|
414
434
|
this._replaceNode(cur, newNode);
|
|
435
|
+
if (this._isMapMode) this._setValue(cur.key, newValue);
|
|
415
436
|
return true; // If duplicate keys are found, no insertion is performed
|
|
416
437
|
}
|
|
417
438
|
|
|
@@ -436,6 +457,7 @@ export class BinaryTree<
|
|
|
436
457
|
} else if (potentialParent.right === undefined) {
|
|
437
458
|
potentialParent.right = newNode;
|
|
438
459
|
}
|
|
460
|
+
if (this._isMapMode) this._setValue(newNode?.key, newValue);
|
|
439
461
|
this._size++;
|
|
440
462
|
return true;
|
|
441
463
|
}
|
|
@@ -450,21 +472,18 @@ export class BinaryTree<
|
|
|
450
472
|
* The `addMany` function takes in multiple keys or nodes or entries or raw values along with
|
|
451
473
|
* optional values, and adds them to a data structure while returning an array indicating whether
|
|
452
474
|
* each insertion was successful.
|
|
453
|
-
* @param
|
|
475
|
+
* @param keysNodesEntriesOrRaws - `keysNodesEntriesOrRaws` is an iterable that can contain a
|
|
454
476
|
* mix of keys, nodes, entries, or raw values. Each element in this iterable can be of type
|
|
455
|
-
* `
|
|
477
|
+
* `BTNRep<K, V, NODE>` or `R`.
|
|
456
478
|
* @param [values] - The `values` parameter in the `addMany` function is an optional parameter that
|
|
457
479
|
* accepts an iterable of values. These values correspond to the keys or nodes being added in the
|
|
458
|
-
* `
|
|
480
|
+
* `keysNodesEntriesOrRaws` parameter. If provided, the function will iterate over the values and
|
|
459
481
|
* assign them
|
|
460
482
|
* @returns The `addMany` method returns an array of boolean values indicating whether each key,
|
|
461
483
|
* node, entry, or raw value was successfully added to the data structure. Each boolean value
|
|
462
484
|
* corresponds to the success of adding the corresponding key or value in the input iterable.
|
|
463
485
|
*/
|
|
464
|
-
addMany(
|
|
465
|
-
keysOrNodesOrEntriesOrRaws: Iterable<BTNKeyOrNodeOrEntry<K, V, NODE> | R>,
|
|
466
|
-
values?: Iterable<V | undefined>
|
|
467
|
-
): boolean[] {
|
|
486
|
+
addMany(keysNodesEntriesOrRaws: Iterable<BTNRep<K, V, NODE> | R>, values?: Iterable<V | undefined>): boolean[] {
|
|
468
487
|
// TODO not sure addMany not be run multi times
|
|
469
488
|
const inserted: boolean[] = [];
|
|
470
489
|
|
|
@@ -473,7 +492,7 @@ export class BinaryTree<
|
|
|
473
492
|
valuesIterator = values[Symbol.iterator]();
|
|
474
493
|
}
|
|
475
494
|
|
|
476
|
-
for (const
|
|
495
|
+
for (const keyNodeEntryOrRaw of keysNodesEntriesOrRaws) {
|
|
477
496
|
let value: V | undefined | null = undefined;
|
|
478
497
|
|
|
479
498
|
if (valuesIterator) {
|
|
@@ -483,7 +502,7 @@ export class BinaryTree<
|
|
|
483
502
|
}
|
|
484
503
|
}
|
|
485
504
|
|
|
486
|
-
inserted.push(this.add(
|
|
505
|
+
inserted.push(this.add(keyNodeEntryOrRaw, value));
|
|
487
506
|
}
|
|
488
507
|
|
|
489
508
|
return inserted;
|
|
@@ -495,18 +514,15 @@ export class BinaryTree<
|
|
|
495
514
|
*
|
|
496
515
|
* The `refill` function clears the existing data structure and then adds new key-value pairs based
|
|
497
516
|
* on the provided input.
|
|
498
|
-
* @param
|
|
499
|
-
* method can accept an iterable containing a mix of `
|
|
517
|
+
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the `refill`
|
|
518
|
+
* method can accept an iterable containing a mix of `BTNRep<K, V, NODE>` objects or `R`
|
|
500
519
|
* objects.
|
|
501
520
|
* @param [values] - The `values` parameter in the `refill` method is an optional parameter that
|
|
502
521
|
* accepts an iterable of values of type `V` or `undefined`.
|
|
503
522
|
*/
|
|
504
|
-
refill(
|
|
505
|
-
keysOrNodesOrEntriesOrRaws: Iterable<BTNKeyOrNodeOrEntry<K, V, NODE> | R>,
|
|
506
|
-
values?: Iterable<V | undefined>
|
|
507
|
-
): void {
|
|
523
|
+
refill(keysNodesEntriesOrRaws: Iterable<BTNRep<K, V, NODE> | R>, values?: Iterable<V | undefined>): void {
|
|
508
524
|
this.clear();
|
|
509
|
-
this.addMany(
|
|
525
|
+
this.addMany(keysNodesEntriesOrRaws, values);
|
|
510
526
|
}
|
|
511
527
|
|
|
512
528
|
/**
|
|
@@ -515,22 +531,20 @@ export class BinaryTree<
|
|
|
515
531
|
*
|
|
516
532
|
* The function `delete` in TypeScript implements the deletion of a node in a binary tree and returns
|
|
517
533
|
* the deleted node along with information for tree balancing.
|
|
518
|
-
* @param {
|
|
534
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw
|
|
519
535
|
* - The `delete` method you provided is used to delete a node from a binary tree based on the key,
|
|
520
|
-
* node, entry
|
|
536
|
+
* node, entry or raw data. The method returns an array of
|
|
521
537
|
* `BinaryTreeDeleteResult` objects containing information about the deleted node and whether
|
|
522
538
|
* balancing is needed.
|
|
523
539
|
* @returns The `delete` method returns an array of `BinaryTreeDeleteResult` objects. Each object in
|
|
524
540
|
* the array contains information about the node that was deleted (`deleted`) and the node that may
|
|
525
541
|
* need to be balanced (`needBalanced`).
|
|
526
542
|
*/
|
|
527
|
-
delete(
|
|
528
|
-
keyOrNodeOrEntryOrRawOrPredicate: BTNKeyOrNodeOrEntry<K, V, NODE> | R | BTNPredicate<NODE>
|
|
529
|
-
): BinaryTreeDeleteResult<NODE>[] {
|
|
543
|
+
delete(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): BinaryTreeDeleteResult<NODE>[] {
|
|
530
544
|
const deletedResult: BinaryTreeDeleteResult<NODE>[] = [];
|
|
531
545
|
if (!this._root) return deletedResult;
|
|
532
546
|
|
|
533
|
-
const curr = this.getNode(
|
|
547
|
+
const curr = this.getNode(keyNodeEntryOrRaw);
|
|
534
548
|
if (!curr) return deletedResult;
|
|
535
549
|
|
|
536
550
|
const parent: NODE | undefined = curr?.parent;
|
|
@@ -567,6 +581,7 @@ export class BinaryTree<
|
|
|
567
581
|
this._size = this._size - 1;
|
|
568
582
|
|
|
569
583
|
deletedResult.push({ deleted: orgCurrent, needBalanced });
|
|
584
|
+
if (this._isMapMode && orgCurrent) this._store.delete(orgCurrent.key);
|
|
570
585
|
return deletedResult;
|
|
571
586
|
}
|
|
572
587
|
|
|
@@ -576,12 +591,12 @@ export class BinaryTree<
|
|
|
576
591
|
*
|
|
577
592
|
* The function `getNodes` retrieves nodes from a binary tree based on a key, node, entry, raw data,
|
|
578
593
|
* or predicate, with options for recursive or iterative traversal.
|
|
579
|
-
* @param {
|
|
594
|
+
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate
|
|
580
595
|
* - The `getNodes` function you provided takes several parameters:
|
|
581
596
|
* @param [onlyOne=false] - The `onlyOne` parameter in the `getNodes` function is a boolean flag that
|
|
582
597
|
* determines whether to return only the first node that matches the criteria specified by the
|
|
583
|
-
* `
|
|
584
|
-
* @param {
|
|
598
|
+
* `keyNodeEntryRawOrPredicate` parameter. If `onlyOne` is set to `true`, the function will
|
|
599
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
585
600
|
* `getNodes` function is used to specify the starting point for traversing the binary tree. It
|
|
586
601
|
* represents the root node of the binary tree or the node from which the traversal should begin. If
|
|
587
602
|
* not provided, the default value is set to `this._root
|
|
@@ -592,16 +607,16 @@ export class BinaryTree<
|
|
|
592
607
|
* based on the input parameters and the iteration type specified.
|
|
593
608
|
*/
|
|
594
609
|
getNodes(
|
|
595
|
-
|
|
610
|
+
keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R | NodePredicate<NODE>,
|
|
596
611
|
onlyOne = false,
|
|
597
|
-
|
|
612
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
598
613
|
iterationType: IterationType = this.iterationType
|
|
599
614
|
): NODE[] {
|
|
600
|
-
if (
|
|
601
|
-
if (
|
|
602
|
-
|
|
603
|
-
if (!
|
|
604
|
-
const callback = this._ensurePredicate(
|
|
615
|
+
if (keyNodeEntryRawOrPredicate === undefined) return [];
|
|
616
|
+
if (keyNodeEntryRawOrPredicate === null) return [];
|
|
617
|
+
startNode = this.ensureNode(startNode);
|
|
618
|
+
if (!startNode) return [];
|
|
619
|
+
const callback = this._ensurePredicate(keyNodeEntryRawOrPredicate);
|
|
605
620
|
|
|
606
621
|
const ans: NODE[] = [];
|
|
607
622
|
|
|
@@ -616,9 +631,9 @@ export class BinaryTree<
|
|
|
616
631
|
if (this.isRealNode(cur.right)) dfs(cur.right);
|
|
617
632
|
};
|
|
618
633
|
|
|
619
|
-
dfs(
|
|
634
|
+
dfs(startNode);
|
|
620
635
|
} else {
|
|
621
|
-
const stack = [
|
|
636
|
+
const stack = [startNode];
|
|
622
637
|
while (stack.length > 0) {
|
|
623
638
|
const cur = stack.pop();
|
|
624
639
|
if (this.isRealNode(cur)) {
|
|
@@ -641,10 +656,10 @@ export class BinaryTree<
|
|
|
641
656
|
*
|
|
642
657
|
* The `getNode` function retrieves a node based on the provided key, node, entry, raw data, or
|
|
643
658
|
* predicate.
|
|
644
|
-
* @param {
|
|
645
|
-
* - The `
|
|
659
|
+
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate
|
|
660
|
+
* - The `keyNodeEntryRawOrPredicate` parameter in the `getNode` function can accept a key,
|
|
646
661
|
* node, entry, raw data, or a predicate function.
|
|
647
|
-
* @param {
|
|
662
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
648
663
|
* `getNode` function is used to specify the starting point for searching for a node in a binary
|
|
649
664
|
* tree. If no specific starting point is provided, the default value is set to `this._root`, which
|
|
650
665
|
* is typically the root node of the binary tree.
|
|
@@ -656,11 +671,11 @@ export class BinaryTree<
|
|
|
656
671
|
* or `null` if no matching node is found.
|
|
657
672
|
*/
|
|
658
673
|
getNode(
|
|
659
|
-
|
|
660
|
-
|
|
674
|
+
keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R | NodePredicate<NODE>,
|
|
675
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
661
676
|
iterationType: IterationType = this.iterationType
|
|
662
|
-
):
|
|
663
|
-
return this.getNodes(
|
|
677
|
+
): OptNodeOrNull<NODE> {
|
|
678
|
+
return this.getNodes(keyNodeEntryRawOrPredicate, true, startNode, iterationType)[0] ?? null;
|
|
664
679
|
}
|
|
665
680
|
|
|
666
681
|
/**
|
|
@@ -674,9 +689,9 @@ export class BinaryTree<
|
|
|
674
689
|
* specifies how the tree nodes should be traversed when searching for a node with the given key. It
|
|
675
690
|
* is an optional parameter with a default value of `this.iterationType`.
|
|
676
691
|
* @returns The `getNodeByKey` function is returning an optional binary tree node
|
|
677
|
-
* (`
|
|
692
|
+
* (`OptNodeOrNull<NODE>`).
|
|
678
693
|
*/
|
|
679
|
-
getNodeByKey(key: K, iterationType: IterationType = this.iterationType):
|
|
694
|
+
getNodeByKey(key: K, iterationType: IterationType = this.iterationType): OptNodeOrNull<NODE> {
|
|
680
695
|
return this.getNode(key, this._root, iterationType);
|
|
681
696
|
}
|
|
682
697
|
|
|
@@ -686,10 +701,10 @@ export class BinaryTree<
|
|
|
686
701
|
*
|
|
687
702
|
* This function overrides the `get` method to retrieve the value associated with a specified key,
|
|
688
703
|
* node, entry, raw data, or predicate in a data structure.
|
|
689
|
-
* @param {
|
|
690
|
-
* - The `
|
|
704
|
+
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate
|
|
705
|
+
* - The `keyNodeEntryRawOrPredicate` parameter in the `get` method can accept one of the
|
|
691
706
|
* following types:
|
|
692
|
-
* @param {
|
|
707
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `get`
|
|
693
708
|
* method is used to specify the starting point for searching for a key or node in the binary tree.
|
|
694
709
|
* If no specific starting point is provided, the default starting point is the root of the binary
|
|
695
710
|
* tree (`this._root`).
|
|
@@ -703,11 +718,16 @@ export class BinaryTree<
|
|
|
703
718
|
* `undefined`.
|
|
704
719
|
*/
|
|
705
720
|
override get(
|
|
706
|
-
|
|
707
|
-
|
|
721
|
+
keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R,
|
|
722
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
708
723
|
iterationType: IterationType = this.iterationType
|
|
709
724
|
): V | undefined {
|
|
710
|
-
|
|
725
|
+
if (this._isMapMode) {
|
|
726
|
+
const key = this._getKey(keyNodeEntryRawOrPredicate);
|
|
727
|
+
if (key === null || key === undefined) return;
|
|
728
|
+
return this._store.get(key);
|
|
729
|
+
}
|
|
730
|
+
return this.getNode(keyNodeEntryRawOrPredicate, startNode, iterationType)?.value;
|
|
711
731
|
}
|
|
712
732
|
|
|
713
733
|
/**
|
|
@@ -716,10 +736,10 @@ export class BinaryTree<
|
|
|
716
736
|
*
|
|
717
737
|
* The `has` function in TypeScript checks if a specified key, node, entry, raw data, or predicate
|
|
718
738
|
* exists in the data structure.
|
|
719
|
-
* @param {
|
|
720
|
-
* - The `
|
|
739
|
+
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate
|
|
740
|
+
* - The `keyNodeEntryRawOrPredicate` parameter in the `override has` method can accept one of
|
|
721
741
|
* the following types:
|
|
722
|
-
* @param {
|
|
742
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
723
743
|
* `override` method is used to specify the starting point for the search operation within the data
|
|
724
744
|
* structure. It defaults to `this._root` if not provided explicitly.
|
|
725
745
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `override has` method
|
|
@@ -732,11 +752,11 @@ export class BinaryTree<
|
|
|
732
752
|
* Otherwise, it returns `false`.
|
|
733
753
|
*/
|
|
734
754
|
override has(
|
|
735
|
-
|
|
736
|
-
|
|
755
|
+
keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R | NodePredicate<NODE>,
|
|
756
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
737
757
|
iterationType: IterationType = this.iterationType
|
|
738
758
|
): boolean {
|
|
739
|
-
return this.getNodes(
|
|
759
|
+
return this.getNodes(keyNodeEntryRawOrPredicate, true, startNode, iterationType).length > 0;
|
|
740
760
|
}
|
|
741
761
|
|
|
742
762
|
/**
|
|
@@ -746,8 +766,8 @@ export class BinaryTree<
|
|
|
746
766
|
* The `clear` function resets the root node and size of a data structure to empty.
|
|
747
767
|
*/
|
|
748
768
|
clear() {
|
|
749
|
-
this.
|
|
750
|
-
this.
|
|
769
|
+
this._clearNodes();
|
|
770
|
+
if (this._isMapMode) this._clearValues();
|
|
751
771
|
}
|
|
752
772
|
|
|
753
773
|
/**
|
|
@@ -769,17 +789,17 @@ export class BinaryTree<
|
|
|
769
789
|
*
|
|
770
790
|
* The function checks if a binary tree is perfectly balanced by comparing its minimum height with
|
|
771
791
|
* its height.
|
|
772
|
-
* @param {
|
|
792
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter is the starting
|
|
773
793
|
* point for checking if the binary tree is perfectly balanced. It represents the root node of the
|
|
774
794
|
* binary tree or a specific node from which the balance check should begin.
|
|
775
795
|
* @returns The method `isPerfectlyBalanced` is returning a boolean value, which indicates whether
|
|
776
|
-
* the tree starting from the `
|
|
796
|
+
* the tree starting from the `startNode` node is perfectly balanced or not. The return value is
|
|
777
797
|
* determined by comparing the minimum height of the tree with the height of the tree. If the minimum
|
|
778
798
|
* height plus 1 is greater than or equal to the height of the tree, then it is considered perfectly
|
|
779
799
|
* balanced and
|
|
780
800
|
*/
|
|
781
|
-
isPerfectlyBalanced(
|
|
782
|
-
return this.getMinHeight(
|
|
801
|
+
isPerfectlyBalanced(startNode: BTNRep<K, V, NODE> | R = this._root): boolean {
|
|
802
|
+
return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);
|
|
783
803
|
}
|
|
784
804
|
|
|
785
805
|
/**
|
|
@@ -788,7 +808,7 @@ export class BinaryTree<
|
|
|
788
808
|
*
|
|
789
809
|
* The function `isBST` in TypeScript checks if a binary search tree is valid using either recursive
|
|
790
810
|
* or iterative methods.
|
|
791
|
-
* @param {
|
|
811
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `isBST`
|
|
792
812
|
* function represents the starting point for checking whether a binary search tree (BST) is valid.
|
|
793
813
|
* It can be a node in the BST or a reference to the root of the BST. If no specific node is
|
|
794
814
|
* provided, the function will default to
|
|
@@ -800,31 +820,28 @@ export class BinaryTree<
|
|
|
800
820
|
* the tree satisfies the BST property, where for every node, all nodes in its left subtree have keys
|
|
801
821
|
* less than the node's key, and all nodes in its right subtree have keys greater than the node's
|
|
802
822
|
*/
|
|
803
|
-
isBST(
|
|
804
|
-
beginRoot: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root,
|
|
805
|
-
iterationType: IterationType = this.iterationType
|
|
806
|
-
): boolean {
|
|
823
|
+
isBST(startNode: BTNRep<K, V, NODE> | R = this._root, iterationType: IterationType = this.iterationType): boolean {
|
|
807
824
|
// TODO there is a bug
|
|
808
|
-
|
|
809
|
-
if (!
|
|
825
|
+
startNode = this.ensureNode(startNode);
|
|
826
|
+
if (!startNode) return true;
|
|
810
827
|
|
|
811
828
|
if (iterationType === 'RECURSIVE') {
|
|
812
|
-
const dfs = (cur:
|
|
829
|
+
const dfs = (cur: OptNodeOrNull<NODE>, min: number, max: number): boolean => {
|
|
813
830
|
if (!this.isRealNode(cur)) return true;
|
|
814
831
|
const numKey = Number(cur.key);
|
|
815
832
|
if (numKey <= min || numKey >= max) return false;
|
|
816
833
|
return dfs(cur.left, min, numKey) && dfs(cur.right, numKey, max);
|
|
817
834
|
};
|
|
818
835
|
|
|
819
|
-
const isStandardBST = dfs(
|
|
820
|
-
const isInverseBST = dfs(
|
|
836
|
+
const isStandardBST = dfs(startNode, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
|
|
837
|
+
const isInverseBST = dfs(startNode, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER);
|
|
821
838
|
return isStandardBST || isInverseBST;
|
|
822
839
|
} else {
|
|
823
840
|
const checkBST = (checkMax = false) => {
|
|
824
841
|
const stack = [];
|
|
825
842
|
let prev = checkMax ? Number.MAX_SAFE_INTEGER : Number.MIN_SAFE_INTEGER;
|
|
826
843
|
// @ts-ignore
|
|
827
|
-
let curr:
|
|
844
|
+
let curr: OptNodeOrNull<NODE> = startNode;
|
|
828
845
|
while (this.isRealNode(curr) || stack.length > 0) {
|
|
829
846
|
while (this.isRealNode(curr)) {
|
|
830
847
|
stack.push(curr);
|
|
@@ -849,23 +866,20 @@ export class BinaryTree<
|
|
|
849
866
|
* Space Complexity: O(1)
|
|
850
867
|
*
|
|
851
868
|
* The `getDepth` function calculates the depth between two nodes in a binary tree.
|
|
852
|
-
* @param {
|
|
869
|
+
* @param {BTNRep<K, V, NODE> | R} dist - The `dist` parameter in the `getDepth`
|
|
853
870
|
* function represents the node or entry in a binary tree map, or a reference to a node in the tree.
|
|
854
|
-
* It is the target node for which you want to calculate the depth from the `
|
|
855
|
-
* @param {
|
|
871
|
+
* It is the target node for which you want to calculate the depth from the `startNode` node.
|
|
872
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
856
873
|
* `getDepth` function represents the starting point from which you want to calculate the depth of a
|
|
857
874
|
* given node or entry in a binary tree. If no specific starting point is provided, the default value
|
|
858
|
-
* for `
|
|
875
|
+
* for `startNode` is set to the root of the binary
|
|
859
876
|
* @returns The `getDepth` method returns the depth of a given node `dist` relative to the
|
|
860
|
-
* `
|
|
877
|
+
* `startNode` node in a binary tree. If the `dist` node is not found in the path to the `startNode`
|
|
861
878
|
* node, it returns the depth of the `dist` node from the root of the tree.
|
|
862
879
|
*/
|
|
863
|
-
getDepth(
|
|
864
|
-
dist: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
|
|
865
|
-
beginRoot: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root
|
|
866
|
-
): number {
|
|
880
|
+
getDepth(dist: BTNRep<K, V, NODE> | R, startNode: BTNRep<K, V, NODE> | R = this._root): number {
|
|
867
881
|
let distEnsured = this.ensureNode(dist);
|
|
868
|
-
const beginRootEnsured = this.ensureNode(
|
|
882
|
+
const beginRootEnsured = this.ensureNode(startNode);
|
|
869
883
|
let depth = 0;
|
|
870
884
|
while (distEnsured?.parent) {
|
|
871
885
|
if (distEnsured === beginRootEnsured) {
|
|
@@ -883,7 +897,7 @@ export class BinaryTree<
|
|
|
883
897
|
*
|
|
884
898
|
* The `getHeight` function calculates the maximum height of a binary tree using either a recursive
|
|
885
899
|
* or iterative approach in TypeScript.
|
|
886
|
-
* @param {
|
|
900
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter is the starting
|
|
887
901
|
* point from which the height of the binary tree will be calculated. It can be a node in the binary
|
|
888
902
|
* tree or a reference to the root of the tree. If not provided, it defaults to the root of the
|
|
889
903
|
* binary tree data structure.
|
|
@@ -894,24 +908,21 @@ export class BinaryTree<
|
|
|
894
908
|
* root node. The height is calculated based on the maximum depth of the tree, considering either a
|
|
895
909
|
* recursive approach or an iterative approach depending on the `iterationType` parameter.
|
|
896
910
|
*/
|
|
897
|
-
getHeight(
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
): number {
|
|
901
|
-
beginRoot = this.ensureNode(beginRoot);
|
|
902
|
-
if (!this.isRealNode(beginRoot)) return -1;
|
|
911
|
+
getHeight(startNode: BTNRep<K, V, NODE> | R = this._root, iterationType: IterationType = this.iterationType): number {
|
|
912
|
+
startNode = this.ensureNode(startNode);
|
|
913
|
+
if (!this.isRealNode(startNode)) return -1;
|
|
903
914
|
|
|
904
915
|
if (iterationType === 'RECURSIVE') {
|
|
905
|
-
const _getMaxHeight = (cur:
|
|
916
|
+
const _getMaxHeight = (cur: OptNodeOrNull<NODE>): number => {
|
|
906
917
|
if (!this.isRealNode(cur)) return -1;
|
|
907
918
|
const leftHeight = _getMaxHeight(cur.left);
|
|
908
919
|
const rightHeight = _getMaxHeight(cur.right);
|
|
909
920
|
return Math.max(leftHeight, rightHeight) + 1;
|
|
910
921
|
};
|
|
911
922
|
|
|
912
|
-
return _getMaxHeight(
|
|
923
|
+
return _getMaxHeight(startNode);
|
|
913
924
|
} else {
|
|
914
|
-
const stack: { node: NODE; depth: number }[] = [{ node:
|
|
925
|
+
const stack: { node: NODE; depth: number }[] = [{ node: startNode, depth: 0 }];
|
|
915
926
|
let maxHeight = 0;
|
|
916
927
|
|
|
917
928
|
while (stack.length > 0) {
|
|
@@ -933,7 +944,7 @@ export class BinaryTree<
|
|
|
933
944
|
*
|
|
934
945
|
* The `getMinHeight` function calculates the minimum height of a binary tree using either a
|
|
935
946
|
* recursive or iterative approach in TypeScript.
|
|
936
|
-
* @param {
|
|
947
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
937
948
|
* `getMinHeight` function represents the starting node from which the minimum height of the binary
|
|
938
949
|
* tree will be calculated. It is either a node in the binary tree or a reference to the root of the
|
|
939
950
|
* tree. If not provided, the default value is the root
|
|
@@ -946,14 +957,14 @@ export class BinaryTree<
|
|
|
946
957
|
* a stack) based on the `iterationType` parameter.
|
|
947
958
|
*/
|
|
948
959
|
getMinHeight(
|
|
949
|
-
|
|
960
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
950
961
|
iterationType: IterationType = this.iterationType
|
|
951
962
|
): number {
|
|
952
|
-
|
|
953
|
-
if (!
|
|
963
|
+
startNode = this.ensureNode(startNode);
|
|
964
|
+
if (!startNode) return -1;
|
|
954
965
|
|
|
955
966
|
if (iterationType === 'RECURSIVE') {
|
|
956
|
-
const _getMinHeight = (cur:
|
|
967
|
+
const _getMinHeight = (cur: OptNodeOrNull<NODE>): number => {
|
|
957
968
|
if (!this.isRealNode(cur)) return 0;
|
|
958
969
|
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return 0;
|
|
959
970
|
const leftMinHeight = _getMinHeight(cur.left);
|
|
@@ -961,11 +972,11 @@ export class BinaryTree<
|
|
|
961
972
|
return Math.min(leftMinHeight, rightMinHeight) + 1;
|
|
962
973
|
};
|
|
963
974
|
|
|
964
|
-
return _getMinHeight(
|
|
975
|
+
return _getMinHeight(startNode);
|
|
965
976
|
} else {
|
|
966
977
|
const stack: NODE[] = [];
|
|
967
|
-
let node:
|
|
968
|
-
last:
|
|
978
|
+
let node: OptNodeOrNull<NODE> = startNode,
|
|
979
|
+
last: OptNodeOrNull<NODE> = null;
|
|
969
980
|
const depths: Map<NODE, number> = new Map();
|
|
970
981
|
|
|
971
982
|
while (stack.length > 0 || node) {
|
|
@@ -987,7 +998,7 @@ export class BinaryTree<
|
|
|
987
998
|
}
|
|
988
999
|
}
|
|
989
1000
|
|
|
990
|
-
return depths.get(
|
|
1001
|
+
return depths.get(startNode)!;
|
|
991
1002
|
}
|
|
992
1003
|
}
|
|
993
1004
|
|
|
@@ -1001,7 +1012,7 @@ export class BinaryTree<
|
|
|
1001
1012
|
* the path to the root. It is expected to be a function that takes a node as an argument and returns
|
|
1002
1013
|
* a value based on that node. The return type of the callback function is determined by the generic
|
|
1003
1014
|
* type `C
|
|
1004
|
-
* @param {
|
|
1015
|
+
* @param {BTNRep<K, V, NODE> | R} beginNode - The `beginNode` parameter in the
|
|
1005
1016
|
* `getPathToRoot` function can be either a key, a node, an entry, or any other value of type `R`.
|
|
1006
1017
|
* @param [isReverse=true] - The `isReverse` parameter in the `getPathToRoot` function determines
|
|
1007
1018
|
* whether the resulting path from the given `beginNode` to the root should be in reverse order or
|
|
@@ -1011,9 +1022,9 @@ export class BinaryTree<
|
|
|
1011
1022
|
* array is either in reverse order or in the original order based on the value of the `isReverse`
|
|
1012
1023
|
* parameter.
|
|
1013
1024
|
*/
|
|
1014
|
-
getPathToRoot<C extends
|
|
1015
|
-
callback: C = this.
|
|
1016
|
-
beginNode:
|
|
1025
|
+
getPathToRoot<C extends NodeCallback<OptNodeOrNull<NODE>>>(
|
|
1026
|
+
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1027
|
+
beginNode: BTNRep<K, V, NODE> | R,
|
|
1017
1028
|
isReverse = true
|
|
1018
1029
|
): ReturnType<C>[] {
|
|
1019
1030
|
const result: ReturnType<C>[] = [];
|
|
@@ -1038,8 +1049,8 @@ export class BinaryTree<
|
|
|
1038
1049
|
* tail-recursive iteration.
|
|
1039
1050
|
* @param {C} callback - The `callback` parameter is a function that will be called with the leftmost
|
|
1040
1051
|
* node of a binary tree or with `undefined` if the tree is empty. It is provided with a default
|
|
1041
|
-
* value of `
|
|
1042
|
-
* @param {
|
|
1052
|
+
* value of `_DEFAULT_NODE_CALLBACK` if not specified.
|
|
1053
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
1043
1054
|
* `getLeftMost` function represents the starting point for finding the leftmost node in a binary
|
|
1044
1055
|
* tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
|
|
1045
1056
|
* starting point is provided, the function will default
|
|
@@ -1047,19 +1058,19 @@ export class BinaryTree<
|
|
|
1047
1058
|
* specifies the type of iteration to be used when traversing the binary tree nodes. It can have two
|
|
1048
1059
|
* possible values:
|
|
1049
1060
|
* @returns The `getLeftMost` function returns the result of the callback function `C` applied to the
|
|
1050
|
-
* leftmost node in the binary tree starting from the `
|
|
1051
|
-
* `NIL`, it returns the result of the callback function applied to `undefined`. If the `
|
|
1061
|
+
* leftmost node in the binary tree starting from the `startNode` node. If the `startNode` node is
|
|
1062
|
+
* `NIL`, it returns the result of the callback function applied to `undefined`. If the `startNode`
|
|
1052
1063
|
* node is not a real node, it returns the result of the callback
|
|
1053
1064
|
*/
|
|
1054
|
-
getLeftMost<C extends
|
|
1055
|
-
callback: C = this.
|
|
1056
|
-
|
|
1065
|
+
getLeftMost<C extends NodeCallback<OptNodeOrNull<NODE>>>(
|
|
1066
|
+
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1067
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
1057
1068
|
iterationType: IterationType = this.iterationType
|
|
1058
1069
|
): ReturnType<C> {
|
|
1059
|
-
if (this.isNIL(
|
|
1060
|
-
|
|
1070
|
+
if (this.isNIL(startNode)) return callback(undefined);
|
|
1071
|
+
startNode = this.ensureNode(startNode);
|
|
1061
1072
|
|
|
1062
|
-
if (!this.isRealNode(
|
|
1073
|
+
if (!this.isRealNode(startNode)) return callback(startNode);
|
|
1063
1074
|
|
|
1064
1075
|
if (iterationType === 'RECURSIVE') {
|
|
1065
1076
|
const dfs = (cur: NODE): NODE => {
|
|
@@ -1067,7 +1078,7 @@ export class BinaryTree<
|
|
|
1067
1078
|
return dfs(cur.left);
|
|
1068
1079
|
};
|
|
1069
1080
|
|
|
1070
|
-
return callback(dfs(
|
|
1081
|
+
return callback(dfs(startNode));
|
|
1071
1082
|
} else {
|
|
1072
1083
|
// Indirect implementation of iteration using tail recursion optimization
|
|
1073
1084
|
const dfs = trampoline((cur: NODE): NODE => {
|
|
@@ -1075,7 +1086,7 @@ export class BinaryTree<
|
|
|
1075
1086
|
return dfs.cont(cur.left);
|
|
1076
1087
|
});
|
|
1077
1088
|
|
|
1078
|
-
return callback(dfs(
|
|
1089
|
+
return callback(dfs(startNode));
|
|
1079
1090
|
}
|
|
1080
1091
|
}
|
|
1081
1092
|
|
|
@@ -1086,10 +1097,10 @@ export class BinaryTree<
|
|
|
1086
1097
|
* The function `getRightMost` retrieves the rightmost node in a binary tree using either recursive
|
|
1087
1098
|
* or iterative traversal methods.
|
|
1088
1099
|
* @param {C} callback - The `callback` parameter is a function that will be called with the result
|
|
1089
|
-
* of finding the rightmost node in a binary tree. It is of type `
|
|
1100
|
+
* of finding the rightmost node in a binary tree. It is of type `NodeCallback<OptNodeOrNull<NODE>>`,
|
|
1090
1101
|
* which means it is a callback function that can accept either an optional binary tree node or null
|
|
1091
1102
|
* as
|
|
1092
|
-
* @param {
|
|
1103
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
1093
1104
|
* `getRightMost` function represents the starting point for finding the rightmost node in a binary
|
|
1094
1105
|
* tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
|
|
1095
1106
|
* starting point is provided, the function will default
|
|
@@ -1101,15 +1112,15 @@ export class BinaryTree<
|
|
|
1101
1112
|
* the binary tree structure, determined based on the specified iteration type ('RECURSIVE' or
|
|
1102
1113
|
* other).
|
|
1103
1114
|
*/
|
|
1104
|
-
getRightMost<C extends
|
|
1105
|
-
callback: C = this.
|
|
1106
|
-
|
|
1115
|
+
getRightMost<C extends NodeCallback<OptNodeOrNull<NODE>>>(
|
|
1116
|
+
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1117
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
1107
1118
|
iterationType: IterationType = this.iterationType
|
|
1108
1119
|
): ReturnType<C> {
|
|
1109
|
-
if (this.isNIL(
|
|
1120
|
+
if (this.isNIL(startNode)) return callback(undefined);
|
|
1110
1121
|
// TODO support get right most by passing key in
|
|
1111
|
-
|
|
1112
|
-
if (!
|
|
1122
|
+
startNode = this.ensureNode(startNode);
|
|
1123
|
+
if (!startNode) return callback(startNode);
|
|
1113
1124
|
|
|
1114
1125
|
if (iterationType === 'RECURSIVE') {
|
|
1115
1126
|
const dfs = (cur: NODE): NODE => {
|
|
@@ -1117,7 +1128,7 @@ export class BinaryTree<
|
|
|
1117
1128
|
return dfs(cur.right);
|
|
1118
1129
|
};
|
|
1119
1130
|
|
|
1120
|
-
return callback(dfs(
|
|
1131
|
+
return callback(dfs(startNode));
|
|
1121
1132
|
} else {
|
|
1122
1133
|
// Indirect implementation of iteration using tail recursion optimization
|
|
1123
1134
|
const dfs = trampoline((cur: NODE) => {
|
|
@@ -1125,7 +1136,7 @@ export class BinaryTree<
|
|
|
1125
1136
|
return dfs.cont(cur.right);
|
|
1126
1137
|
});
|
|
1127
1138
|
|
|
1128
|
-
return callback(dfs(
|
|
1139
|
+
return callback(dfs(startNode));
|
|
1129
1140
|
}
|
|
1130
1141
|
}
|
|
1131
1142
|
|
|
@@ -1144,7 +1155,7 @@ export class BinaryTree<
|
|
|
1144
1155
|
*/
|
|
1145
1156
|
getPredecessor(node: NODE): NODE {
|
|
1146
1157
|
if (this.isRealNode(node.left)) {
|
|
1147
|
-
let predecessor:
|
|
1158
|
+
let predecessor: OptNodeOrNull<NODE> = node.left;
|
|
1148
1159
|
while (!this.isRealNode(predecessor) || (this.isRealNode(predecessor.right) && predecessor.right !== node)) {
|
|
1149
1160
|
if (this.isRealNode(predecessor)) {
|
|
1150
1161
|
predecessor = predecessor.right;
|
|
@@ -1169,7 +1180,7 @@ export class BinaryTree<
|
|
|
1169
1180
|
* have a right child, the function traverses up the parent nodes until it finds a node that is not
|
|
1170
1181
|
* the right child of its parent, and returns that node
|
|
1171
1182
|
*/
|
|
1172
|
-
getSuccessor(x?: K | NODE | null):
|
|
1183
|
+
getSuccessor(x?: K | NODE | null): OptNodeOrNull<NODE> {
|
|
1173
1184
|
x = this.ensureNode(x);
|
|
1174
1185
|
if (!this.isRealNode(x)) return undefined;
|
|
1175
1186
|
|
|
@@ -1177,7 +1188,7 @@ export class BinaryTree<
|
|
|
1177
1188
|
return this.getLeftMost(node => node, x.right);
|
|
1178
1189
|
}
|
|
1179
1190
|
|
|
1180
|
-
let y:
|
|
1191
|
+
let y: OptNodeOrNull<NODE> = x.parent;
|
|
1181
1192
|
while (this.isRealNode(y) && x === y.right) {
|
|
1182
1193
|
x = y;
|
|
1183
1194
|
y = y.parent;
|
|
@@ -1185,17 +1196,17 @@ export class BinaryTree<
|
|
|
1185
1196
|
return y;
|
|
1186
1197
|
}
|
|
1187
1198
|
|
|
1188
|
-
dfs<C extends
|
|
1199
|
+
dfs<C extends NodeCallback<NODE>>(
|
|
1189
1200
|
callback?: C,
|
|
1190
1201
|
pattern?: DFSOrderPattern,
|
|
1191
|
-
|
|
1202
|
+
startNode?: BTNRep<K, V, NODE> | R,
|
|
1192
1203
|
iterationType?: IterationType
|
|
1193
1204
|
): ReturnType<C>[];
|
|
1194
1205
|
|
|
1195
|
-
dfs<C extends
|
|
1206
|
+
dfs<C extends NodeCallback<NODE | null>>(
|
|
1196
1207
|
callback?: C,
|
|
1197
1208
|
pattern?: DFSOrderPattern,
|
|
1198
|
-
|
|
1209
|
+
startNode?: BTNRep<K, V, NODE> | R,
|
|
1199
1210
|
iterationType?: IterationType,
|
|
1200
1211
|
includeNull?: boolean
|
|
1201
1212
|
): ReturnType<C>[];
|
|
@@ -1207,14 +1218,14 @@ export class BinaryTree<
|
|
|
1207
1218
|
* The function `dfs` performs a depth-first search traversal on a binary tree structure based on the
|
|
1208
1219
|
* specified parameters.
|
|
1209
1220
|
* @param {C} callback - The `callback` parameter is a generic type `C` that extends the
|
|
1210
|
-
* `
|
|
1211
|
-
* `this.
|
|
1221
|
+
* `NodeCallback` interface with a type parameter of `OptNodeOrNull<NODE>`. It has a default value of
|
|
1222
|
+
* `this._DEFAULT_NODE_CALLBACK as C`.
|
|
1212
1223
|
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `dfs` method specifies the
|
|
1213
1224
|
* order in which the Depth-First Search (DFS) algorithm should traverse the nodes in the tree. The
|
|
1214
1225
|
* possible values for the `pattern` parameter are:
|
|
1215
|
-
* @param {
|
|
1226
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `dfs`
|
|
1216
1227
|
* method is used to specify the starting point for the Depth-First Search traversal. It can be
|
|
1217
|
-
* either a `
|
|
1228
|
+
* either a `BTNRep` object representing a key, node, or entry in the binary tree map,
|
|
1218
1229
|
* or it can be a
|
|
1219
1230
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `dfs` method specifies
|
|
1220
1231
|
* the type of iteration to be performed during the depth-first search traversal. It is used to
|
|
@@ -1226,28 +1237,28 @@ export class BinaryTree<
|
|
|
1226
1237
|
* @returns The `dfs` method is returning an array of the return type specified by the generic type
|
|
1227
1238
|
* parameter `C`. The return type is determined by the callback function provided to the method.
|
|
1228
1239
|
*/
|
|
1229
|
-
dfs<C extends
|
|
1230
|
-
callback: C = this.
|
|
1240
|
+
dfs<C extends NodeCallback<OptNodeOrNull<NODE>>>(
|
|
1241
|
+
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1231
1242
|
pattern: DFSOrderPattern = 'IN',
|
|
1232
|
-
|
|
1243
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
1233
1244
|
iterationType: IterationType = this.iterationType,
|
|
1234
1245
|
includeNull = false
|
|
1235
1246
|
): ReturnType<C>[] {
|
|
1236
|
-
|
|
1237
|
-
if (!
|
|
1238
|
-
return this._dfs(callback, pattern,
|
|
1247
|
+
startNode = this.ensureNode(startNode);
|
|
1248
|
+
if (!startNode) return [];
|
|
1249
|
+
return this._dfs(callback, pattern, startNode, iterationType, includeNull);
|
|
1239
1250
|
}
|
|
1240
1251
|
|
|
1241
|
-
bfs<C extends
|
|
1252
|
+
bfs<C extends NodeCallback<NODE>>(
|
|
1242
1253
|
callback?: C,
|
|
1243
|
-
|
|
1254
|
+
startNode?: BTNRep<K, V, NODE> | R,
|
|
1244
1255
|
iterationType?: IterationType,
|
|
1245
1256
|
includeNull?: false
|
|
1246
1257
|
): ReturnType<C>[];
|
|
1247
1258
|
|
|
1248
|
-
bfs<C extends
|
|
1259
|
+
bfs<C extends NodeCallback<NODE | null>>(
|
|
1249
1260
|
callback?: C,
|
|
1250
|
-
|
|
1261
|
+
startNode?: BTNRep<K, V, NODE> | R,
|
|
1251
1262
|
iterationType?: IterationType,
|
|
1252
1263
|
includeNull?: true
|
|
1253
1264
|
): ReturnType<C>[];
|
|
@@ -1260,8 +1271,8 @@ export class BinaryTree<
|
|
|
1260
1271
|
* tree, executing a specified callback function on each node visited.
|
|
1261
1272
|
* @param {C} callback - The `callback` parameter in the `bfs` function is a function that will be
|
|
1262
1273
|
* called on each node visited during the breadth-first search traversal. It is a generic type `C`
|
|
1263
|
-
* that extends the `
|
|
1264
|
-
* @param {
|
|
1274
|
+
* that extends the `NodeCallback` type, which takes a parameter of type `NODE` or `null`.
|
|
1275
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `bfs`
|
|
1265
1276
|
* function represents the starting point for the breadth-first search traversal in a binary tree. It
|
|
1266
1277
|
* can be specified as a key, node, or entry in the binary tree structure. If not provided, the
|
|
1267
1278
|
* default value is the root node of the binary
|
|
@@ -1275,19 +1286,19 @@ export class BinaryTree<
|
|
|
1275
1286
|
* @returns The `bfs` function returns an array of values that are the result of applying the
|
|
1276
1287
|
* provided callback function to each node in the binary tree in a breadth-first search manner.
|
|
1277
1288
|
*/
|
|
1278
|
-
bfs<C extends
|
|
1279
|
-
callback: C = this.
|
|
1280
|
-
|
|
1289
|
+
bfs<C extends NodeCallback<NODE | null>>(
|
|
1290
|
+
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1291
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
1281
1292
|
iterationType: IterationType = this.iterationType,
|
|
1282
1293
|
includeNull = false
|
|
1283
1294
|
): ReturnType<C>[] {
|
|
1284
|
-
|
|
1285
|
-
if (!
|
|
1295
|
+
startNode = this.ensureNode(startNode);
|
|
1296
|
+
if (!startNode) return [];
|
|
1286
1297
|
|
|
1287
|
-
const ans: ReturnType<
|
|
1298
|
+
const ans: ReturnType<NodeCallback<NODE>>[] = [];
|
|
1288
1299
|
|
|
1289
1300
|
if (iterationType === 'RECURSIVE') {
|
|
1290
|
-
const queue: Queue<
|
|
1301
|
+
const queue: Queue<OptNodeOrNull<NODE>> = new Queue<OptNodeOrNull<NODE>>([startNode]);
|
|
1291
1302
|
|
|
1292
1303
|
const dfs = (level: number) => {
|
|
1293
1304
|
if (queue.size === 0) return;
|
|
@@ -1308,7 +1319,7 @@ export class BinaryTree<
|
|
|
1308
1319
|
|
|
1309
1320
|
dfs(0);
|
|
1310
1321
|
} else {
|
|
1311
|
-
const queue = new Queue<
|
|
1322
|
+
const queue = new Queue<OptNodeOrNull<NODE>>([startNode]);
|
|
1312
1323
|
while (queue.size > 0) {
|
|
1313
1324
|
const levelSize = queue.size;
|
|
1314
1325
|
|
|
@@ -1337,7 +1348,7 @@ export class BinaryTree<
|
|
|
1337
1348
|
* structure based on a specified callback and iteration type.
|
|
1338
1349
|
* @param {C} callback - The `callback` parameter is a function that will be called on each leaf node
|
|
1339
1350
|
* in the binary tree. It is optional and defaults to a default callback function if not provided.
|
|
1340
|
-
* @param {
|
|
1351
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `leaves`
|
|
1341
1352
|
* method is used to specify the starting point for finding and processing the leaves of a binary
|
|
1342
1353
|
* tree. It can be provided as either a key, a node, or an entry in the binary tree structure. If not
|
|
1343
1354
|
* explicitly provided, the default value
|
|
@@ -1347,14 +1358,14 @@ export class BinaryTree<
|
|
|
1347
1358
|
* @returns The `leaves` method returns an array of values that are the result of applying the
|
|
1348
1359
|
* provided callback function to each leaf node in the binary tree.
|
|
1349
1360
|
*/
|
|
1350
|
-
leaves<C extends
|
|
1351
|
-
callback: C = this.
|
|
1352
|
-
|
|
1361
|
+
leaves<C extends NodeCallback<NODE | null>>(
|
|
1362
|
+
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1363
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
1353
1364
|
iterationType: IterationType = this.iterationType
|
|
1354
1365
|
): ReturnType<C>[] {
|
|
1355
|
-
|
|
1356
|
-
const leaves: ReturnType<
|
|
1357
|
-
if (!this.isRealNode(
|
|
1366
|
+
startNode = this.ensureNode(startNode);
|
|
1367
|
+
const leaves: ReturnType<NodeCallback<NODE>>[] = [];
|
|
1368
|
+
if (!this.isRealNode(startNode)) return [];
|
|
1358
1369
|
|
|
1359
1370
|
if (iterationType === 'RECURSIVE') {
|
|
1360
1371
|
const dfs = (cur: NODE) => {
|
|
@@ -1366,9 +1377,9 @@ export class BinaryTree<
|
|
|
1366
1377
|
if (this.isRealNode(cur.right)) dfs(cur.right);
|
|
1367
1378
|
};
|
|
1368
1379
|
|
|
1369
|
-
dfs(
|
|
1380
|
+
dfs(startNode);
|
|
1370
1381
|
} else {
|
|
1371
|
-
const queue = new Queue([
|
|
1382
|
+
const queue = new Queue([startNode]);
|
|
1372
1383
|
while (queue.size > 0) {
|
|
1373
1384
|
const cur = queue.shift();
|
|
1374
1385
|
if (this.isRealNode(cur)) {
|
|
@@ -1384,16 +1395,16 @@ export class BinaryTree<
|
|
|
1384
1395
|
return leaves;
|
|
1385
1396
|
}
|
|
1386
1397
|
|
|
1387
|
-
listLevels<C extends
|
|
1398
|
+
listLevels<C extends NodeCallback<NODE>>(
|
|
1388
1399
|
callback?: C,
|
|
1389
|
-
|
|
1400
|
+
startNode?: BTNRep<K, V, NODE> | R,
|
|
1390
1401
|
iterationType?: IterationType,
|
|
1391
1402
|
includeNull?: false
|
|
1392
1403
|
): ReturnType<C>[][];
|
|
1393
1404
|
|
|
1394
|
-
listLevels<C extends
|
|
1405
|
+
listLevels<C extends NodeCallback<NODE | null>>(
|
|
1395
1406
|
callback?: C,
|
|
1396
|
-
|
|
1407
|
+
startNode?: BTNRep<K, V, NODE> | R,
|
|
1397
1408
|
iterationType?: IterationType,
|
|
1398
1409
|
includeNull?: true
|
|
1399
1410
|
): ReturnType<C>[][];
|
|
@@ -1407,7 +1418,7 @@ export class BinaryTree<
|
|
|
1407
1418
|
* @param {C} callback - The `callback` parameter is a function that will be applied to each node in
|
|
1408
1419
|
* the binary tree during the traversal. It is used to process each node and determine what
|
|
1409
1420
|
* information to include in the output for each level of the tree.
|
|
1410
|
-
* @param {
|
|
1421
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
1411
1422
|
* `listLevels` function represents the starting point for traversing the binary tree. It can be
|
|
1412
1423
|
* either a key, a node, or an entry in the binary tree. If not provided, the default value is the
|
|
1413
1424
|
* root of the binary tree.
|
|
@@ -1422,15 +1433,15 @@ export class BinaryTree<
|
|
|
1422
1433
|
* level in a binary tree. Each inner array contains the return value of the provided callback
|
|
1423
1434
|
* function applied to the nodes at that level.
|
|
1424
1435
|
*/
|
|
1425
|
-
listLevels<C extends
|
|
1426
|
-
callback: C = this.
|
|
1427
|
-
|
|
1436
|
+
listLevels<C extends NodeCallback<NODE | null>>(
|
|
1437
|
+
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1438
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
1428
1439
|
iterationType: IterationType = this.iterationType,
|
|
1429
1440
|
includeNull = false
|
|
1430
1441
|
): ReturnType<C>[][] {
|
|
1431
|
-
|
|
1442
|
+
startNode = this.ensureNode(startNode);
|
|
1432
1443
|
const levelsNodes: ReturnType<C>[][] = [];
|
|
1433
|
-
if (!
|
|
1444
|
+
if (!startNode) return levelsNodes;
|
|
1434
1445
|
|
|
1435
1446
|
if (iterationType === 'RECURSIVE') {
|
|
1436
1447
|
const _recursive = (node: NODE | null, level: number) => {
|
|
@@ -1445,9 +1456,9 @@ export class BinaryTree<
|
|
|
1445
1456
|
}
|
|
1446
1457
|
};
|
|
1447
1458
|
|
|
1448
|
-
_recursive(
|
|
1459
|
+
_recursive(startNode, 0);
|
|
1449
1460
|
} else {
|
|
1450
|
-
const stack: [NODE | null, number][] = [[
|
|
1461
|
+
const stack: [NODE | null, number][] = [[startNode, 0]];
|
|
1451
1462
|
|
|
1452
1463
|
while (stack.length > 0) {
|
|
1453
1464
|
const head = stack.pop()!;
|
|
@@ -1477,11 +1488,11 @@ export class BinaryTree<
|
|
|
1477
1488
|
* Morris Traversal algorithm with different order patterns.
|
|
1478
1489
|
* @param {C} callback - The `callback` parameter in the `morris` function is a function that will be
|
|
1479
1490
|
* called on each node in the binary tree during the traversal. It is of type `C`, which extends the
|
|
1480
|
-
* `
|
|
1491
|
+
* `NodeCallback<NODE>` type. The default value for `callback` is `this._DEFAULT
|
|
1481
1492
|
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `morris` function specifies
|
|
1482
1493
|
* the type of Depth-First Search (DFS) order pattern to traverse the binary tree. The possible
|
|
1483
1494
|
* values for the `pattern` parameter are:
|
|
1484
|
-
* @param {
|
|
1495
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `morris`
|
|
1485
1496
|
* function is the starting point for the Morris traversal algorithm. It represents the root node of
|
|
1486
1497
|
* the binary tree or the node from which the traversal should begin. It can be provided as either a
|
|
1487
1498
|
* key, a node, an entry, or a reference
|
|
@@ -1489,19 +1500,19 @@ export class BinaryTree<
|
|
|
1489
1500
|
* provided callback function to each node in the binary tree in the specified order pattern (IN,
|
|
1490
1501
|
* PRE, or POST).
|
|
1491
1502
|
*/
|
|
1492
|
-
morris<C extends
|
|
1493
|
-
callback: C = this.
|
|
1503
|
+
morris<C extends NodeCallback<NODE>>(
|
|
1504
|
+
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1494
1505
|
pattern: DFSOrderPattern = 'IN',
|
|
1495
|
-
|
|
1506
|
+
startNode: BTNRep<K, V, NODE> | R = this._root
|
|
1496
1507
|
): ReturnType<C>[] {
|
|
1497
|
-
|
|
1498
|
-
if (!
|
|
1499
|
-
const ans: ReturnType<
|
|
1500
|
-
|
|
1501
|
-
let cur:
|
|
1502
|
-
const _reverseEdge = (node:
|
|
1503
|
-
let pre:
|
|
1504
|
-
let next:
|
|
1508
|
+
startNode = this.ensureNode(startNode);
|
|
1509
|
+
if (!startNode) return [];
|
|
1510
|
+
const ans: ReturnType<NodeCallback<NODE>>[] = [];
|
|
1511
|
+
|
|
1512
|
+
let cur: OptNodeOrNull<NODE> = startNode;
|
|
1513
|
+
const _reverseEdge = (node: OptNodeOrNull<NODE>) => {
|
|
1514
|
+
let pre: OptNodeOrNull<NODE> = null;
|
|
1515
|
+
let next: OptNodeOrNull<NODE> = null;
|
|
1505
1516
|
while (node) {
|
|
1506
1517
|
next = node.right;
|
|
1507
1518
|
node.right = pre;
|
|
@@ -1510,9 +1521,9 @@ export class BinaryTree<
|
|
|
1510
1521
|
}
|
|
1511
1522
|
return pre;
|
|
1512
1523
|
};
|
|
1513
|
-
const _printEdge = (node:
|
|
1514
|
-
const tail:
|
|
1515
|
-
let cur:
|
|
1524
|
+
const _printEdge = (node: OptNodeOrNull<NODE>) => {
|
|
1525
|
+
const tail: OptNodeOrNull<NODE> = _reverseEdge(node);
|
|
1526
|
+
let cur: OptNodeOrNull<NODE> = tail;
|
|
1516
1527
|
while (cur) {
|
|
1517
1528
|
ans.push(callback(cur));
|
|
1518
1529
|
cur = cur.right;
|
|
@@ -1569,7 +1580,7 @@ export class BinaryTree<
|
|
|
1569
1580
|
}
|
|
1570
1581
|
cur = cur.right;
|
|
1571
1582
|
}
|
|
1572
|
-
_printEdge(
|
|
1583
|
+
_printEdge(startNode);
|
|
1573
1584
|
break;
|
|
1574
1585
|
}
|
|
1575
1586
|
return ans;
|
|
@@ -1591,12 +1602,16 @@ export class BinaryTree<
|
|
|
1591
1602
|
this.bfs(
|
|
1592
1603
|
node => {
|
|
1593
1604
|
if (node === null) cloned.add(null);
|
|
1594
|
-
else
|
|
1605
|
+
else {
|
|
1606
|
+
if (this._isMapMode) cloned.add([node.key, this._store.get(node.key)]);
|
|
1607
|
+
else cloned.add([node.key, node.value]);
|
|
1608
|
+
}
|
|
1595
1609
|
},
|
|
1596
1610
|
this._root,
|
|
1597
1611
|
this.iterationType,
|
|
1598
1612
|
true
|
|
1599
1613
|
);
|
|
1614
|
+
if (this._isMapMode) cloned._store = this._store;
|
|
1600
1615
|
return cloned;
|
|
1601
1616
|
}
|
|
1602
1617
|
|
|
@@ -1667,7 +1682,7 @@ export class BinaryTree<
|
|
|
1667
1682
|
*
|
|
1668
1683
|
* The function `toVisual` in TypeScript overrides the visual representation of a binary tree with
|
|
1669
1684
|
* customizable options for displaying undefined, null, and sentinel nodes.
|
|
1670
|
-
* @param {
|
|
1685
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
1671
1686
|
* `toVisual` method is used to specify the starting point for visualizing the binary tree structure.
|
|
1672
1687
|
* It can be a node, key, entry, or the root of the tree. If no specific starting point is provided,
|
|
1673
1688
|
* the default is set to the root
|
|
@@ -1679,26 +1694,17 @@ export class BinaryTree<
|
|
|
1679
1694
|
* the lines to the output string. The final output string contains the visual representation of the
|
|
1680
1695
|
* binary tree with the specified options.
|
|
1681
1696
|
*/
|
|
1682
|
-
override toVisual(
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
): string {
|
|
1686
|
-
const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options };
|
|
1687
|
-
beginRoot = this.ensureNode(beginRoot);
|
|
1697
|
+
override toVisual(startNode: BTNRep<K, V, NODE> | R = this._root, options?: BinaryTreePrintOptions): string {
|
|
1698
|
+
const opts = { isShowUndefined: false, isShowNull: true, isShowRedBlackNIL: false, ...options };
|
|
1699
|
+
startNode = this.ensureNode(startNode);
|
|
1688
1700
|
let output = '';
|
|
1689
|
-
if (!
|
|
1690
|
-
|
|
1691
|
-
if (opts.isShowUndefined)
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
`;
|
|
1697
|
-
if (opts.isShowRedBlackNIL)
|
|
1698
|
-
output += `S for Sentinel Node(NIL)
|
|
1699
|
-
`;
|
|
1700
|
-
|
|
1701
|
-
const display = (root: OptBTNOrNull<NODE>): void => {
|
|
1701
|
+
if (!startNode) return output;
|
|
1702
|
+
|
|
1703
|
+
if (opts.isShowUndefined) output += `U for undefined\n`;
|
|
1704
|
+
if (opts.isShowNull) output += `N for null\n`;
|
|
1705
|
+
if (opts.isShowRedBlackNIL) output += `S for Sentinel Node(NIL)\n`;
|
|
1706
|
+
|
|
1707
|
+
const display = (root: OptNodeOrNull<NODE>): void => {
|
|
1702
1708
|
const [lines, , ,] = this._displayAux(root, opts);
|
|
1703
1709
|
let paragraph = '';
|
|
1704
1710
|
for (const line of lines) {
|
|
@@ -1707,24 +1713,28 @@ export class BinaryTree<
|
|
|
1707
1713
|
output += paragraph;
|
|
1708
1714
|
};
|
|
1709
1715
|
|
|
1710
|
-
display(
|
|
1716
|
+
display(startNode);
|
|
1711
1717
|
return output;
|
|
1712
1718
|
}
|
|
1713
1719
|
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1720
|
+
/**
|
|
1721
|
+
* Time Complexity: O(n)
|
|
1722
|
+
* Space Complexity: O(n)
|
|
1723
|
+
*
|
|
1724
|
+
* The function `print` in TypeScript overrides the default print behavior to log a visual
|
|
1725
|
+
* representation of the binary tree to the console.
|
|
1726
|
+
* @param {BinaryTreePrintOptions} [options] - The `options` parameter is used to specify the
|
|
1727
|
+
* printing options for the binary tree. It is an optional parameter that allows you to customize how
|
|
1728
|
+
* the binary tree is printed, such as choosing between different traversal orders or formatting
|
|
1729
|
+
* options.
|
|
1730
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
1731
|
+
* `override print` method is used to specify the starting point for printing the binary tree. It can
|
|
1732
|
+
* be either a key, a node, an entry, or the root of the tree. If no specific starting point is
|
|
1733
|
+
* provided, the default value is set to
|
|
1734
|
+
*/
|
|
1735
|
+
override print(options?: BinaryTreePrintOptions, startNode: BTNRep<K, V, NODE> | R = this._root) {
|
|
1736
|
+
console.log(this.toVisual(startNode, options));
|
|
1737
|
+
}
|
|
1728
1738
|
|
|
1729
1739
|
/**
|
|
1730
1740
|
* Time complexity: O(n)
|
|
@@ -1734,13 +1744,13 @@ export class BinaryTree<
|
|
|
1734
1744
|
* the specified order pattern and callback function.
|
|
1735
1745
|
* @param {C} callback - The `callback` parameter in the `_dfs` method is a function that will be
|
|
1736
1746
|
* called on each node visited during the depth-first search traversal. It is of type `C`, which
|
|
1737
|
-
* extends `
|
|
1747
|
+
* extends `NodeCallback<OptNodeOrNull<NODE>>`. The default value for this parameter is `this._DEFAULT
|
|
1738
1748
|
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `_dfs` method specifies the
|
|
1739
1749
|
* order in which the nodes are visited during the Depth-First Search traversal. It can have one of
|
|
1740
1750
|
* the following values:
|
|
1741
|
-
* @param {
|
|
1751
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `_dfs`
|
|
1742
1752
|
* method is used to specify the starting point for the depth-first search traversal in a binary
|
|
1743
|
-
* tree. It can be provided as either a `
|
|
1753
|
+
* tree. It can be provided as either a `BTNRep` object or a reference to the root node
|
|
1744
1754
|
* of the tree. If no specific
|
|
1745
1755
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `_dfs` method
|
|
1746
1756
|
* specifies the type of iteration to be performed during the Depth-First Search (DFS) traversal of a
|
|
@@ -1768,26 +1778,26 @@ export class BinaryTree<
|
|
|
1768
1778
|
* @returns The function `_dfs` returns an array of the return type of the callback function provided
|
|
1769
1779
|
* as input.
|
|
1770
1780
|
*/
|
|
1771
|
-
protected _dfs<C extends
|
|
1772
|
-
callback: C = this.
|
|
1781
|
+
protected _dfs<C extends NodeCallback<OptNodeOrNull<NODE>>>(
|
|
1782
|
+
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1773
1783
|
pattern: DFSOrderPattern = 'IN',
|
|
1774
|
-
|
|
1784
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
1775
1785
|
iterationType: IterationType = this.iterationType,
|
|
1776
1786
|
includeNull = false,
|
|
1777
|
-
shouldVisitLeft: (node:
|
|
1778
|
-
shouldVisitRight: (node:
|
|
1779
|
-
shouldVisitRoot: (node:
|
|
1787
|
+
shouldVisitLeft: (node: OptNodeOrNull<NODE>) => boolean = node => !!node,
|
|
1788
|
+
shouldVisitRight: (node: OptNodeOrNull<NODE>) => boolean = node => !!node,
|
|
1789
|
+
shouldVisitRoot: (node: OptNodeOrNull<NODE>) => boolean = node => {
|
|
1780
1790
|
if (includeNull) return this.isRealNodeOrNull(node);
|
|
1781
1791
|
return this.isRealNode(node);
|
|
1782
1792
|
},
|
|
1783
|
-
shouldProcessRoot: (node:
|
|
1793
|
+
shouldProcessRoot: (node: OptNodeOrNull<NODE>) => boolean = node => this.isRealNodeOrNull(node)
|
|
1784
1794
|
): ReturnType<C>[] {
|
|
1785
|
-
|
|
1786
|
-
if (!
|
|
1795
|
+
startNode = this.ensureNode(startNode);
|
|
1796
|
+
if (!startNode) return [];
|
|
1787
1797
|
const ans: ReturnType<C>[] = [];
|
|
1788
1798
|
|
|
1789
1799
|
if (iterationType === 'RECURSIVE') {
|
|
1790
|
-
const dfs = (node:
|
|
1800
|
+
const dfs = (node: OptNodeOrNull<NODE>) => {
|
|
1791
1801
|
if (!shouldVisitRoot(node)) return;
|
|
1792
1802
|
|
|
1793
1803
|
const visitLeft = () => {
|
|
@@ -1816,9 +1826,9 @@ export class BinaryTree<
|
|
|
1816
1826
|
}
|
|
1817
1827
|
};
|
|
1818
1828
|
|
|
1819
|
-
dfs(
|
|
1829
|
+
dfs(startNode);
|
|
1820
1830
|
} else {
|
|
1821
|
-
const stack: DFSStackItem<NODE>[] = [{ opt: DFSOperation.VISIT, node:
|
|
1831
|
+
const stack: DFSStackItem<NODE>[] = [{ opt: DFSOperation.VISIT, node: startNode }];
|
|
1822
1832
|
|
|
1823
1833
|
const pushLeft = (cur: DFSStackItem<NODE>) => {
|
|
1824
1834
|
if (shouldVisitLeft(cur.node)) stack.push({ opt: DFSOperation.VISIT, node: cur.node?.left });
|
|
@@ -1880,8 +1890,8 @@ export class BinaryTree<
|
|
|
1880
1890
|
if (!node) return;
|
|
1881
1891
|
|
|
1882
1892
|
if (this.iterationType === 'ITERATIVE') {
|
|
1883
|
-
const stack:
|
|
1884
|
-
let current:
|
|
1893
|
+
const stack: OptNodeOrNull<NODE>[] = [];
|
|
1894
|
+
let current: OptNodeOrNull<NODE> = node;
|
|
1885
1895
|
|
|
1886
1896
|
while (current || stack.length > 0) {
|
|
1887
1897
|
while (this.isRealNode(current)) {
|
|
@@ -1892,7 +1902,8 @@ export class BinaryTree<
|
|
|
1892
1902
|
current = stack.pop();
|
|
1893
1903
|
|
|
1894
1904
|
if (this.isRealNode(current)) {
|
|
1895
|
-
yield [current.key, current.
|
|
1905
|
+
if (this._isMapMode) yield [current.key, this._store.get(current.key)];
|
|
1906
|
+
else yield [current.key, current.value];
|
|
1896
1907
|
current = current.right;
|
|
1897
1908
|
}
|
|
1898
1909
|
}
|
|
@@ -1900,7 +1911,8 @@ export class BinaryTree<
|
|
|
1900
1911
|
if (node.left && this.isRealNode(node)) {
|
|
1901
1912
|
yield* this[Symbol.iterator](node.left);
|
|
1902
1913
|
}
|
|
1903
|
-
yield [node.key, node.
|
|
1914
|
+
if (this._isMapMode) yield [node.key, this._store.get(node.key)];
|
|
1915
|
+
else yield [node.key, node.value];
|
|
1904
1916
|
if (node.right && this.isRealNode(node)) {
|
|
1905
1917
|
yield* this[Symbol.iterator](node.right);
|
|
1906
1918
|
}
|
|
@@ -1922,7 +1934,7 @@ export class BinaryTree<
|
|
|
1922
1934
|
* information about how to display a node in a binary tree. The `NodeDisplayLayout` consists of four
|
|
1923
1935
|
* elements:
|
|
1924
1936
|
*/
|
|
1925
|
-
protected _displayAux(node:
|
|
1937
|
+
protected _displayAux(node: OptNodeOrNull<NODE>, options: BinaryTreePrintOptions): NodeDisplayLayout {
|
|
1926
1938
|
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
1927
1939
|
const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];
|
|
1928
1940
|
|
|
@@ -1990,27 +2002,24 @@ export class BinaryTree<
|
|
|
1990
2002
|
}
|
|
1991
2003
|
}
|
|
1992
2004
|
|
|
1993
|
-
protected
|
|
2005
|
+
protected _DEFAULT_NODE_CALLBACK = (node: OptNodeOrNull<NODE>) => (node ? node.key : undefined);
|
|
1994
2006
|
|
|
1995
2007
|
/**
|
|
1996
2008
|
* Time Complexity: O(1)
|
|
1997
2009
|
* Space Complexity: O(1)
|
|
1998
2010
|
*
|
|
1999
2011
|
* The _swapProperties function swaps key and value properties between two nodes in a binary tree.
|
|
2000
|
-
* @param {
|
|
2001
|
-
* `_swapProperties` method can be either a
|
|
2012
|
+
* @param {BTNRep<K, V, NODE> | R} srcNode - The `srcNode` parameter in the
|
|
2013
|
+
* `_swapProperties` method can be either a BTNRep object containing key and value
|
|
2002
2014
|
* properties, or it can be of type R.
|
|
2003
|
-
* @param {
|
|
2015
|
+
* @param {BTNRep<K, V, NODE> | R} destNode - The `destNode` parameter in the
|
|
2004
2016
|
* `_swapProperties` method represents the node or entry where the properties will be swapped with
|
|
2005
|
-
* the `srcNode`. It can be of type `
|
|
2017
|
+
* the `srcNode`. It can be of type `BTNRep<K, V, NODE>` or `R`. The method ensures that
|
|
2006
2018
|
* both `srcNode
|
|
2007
2019
|
* @returns The `_swapProperties` method returns either the `destNode` with its key and value swapped
|
|
2008
2020
|
* with the `srcNode`, or `undefined` if either `srcNode` or `destNode` is falsy.
|
|
2009
2021
|
*/
|
|
2010
|
-
protected _swapProperties(
|
|
2011
|
-
srcNode: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
|
|
2012
|
-
destNode: BTNKeyOrNodeOrEntry<K, V, NODE> | R
|
|
2013
|
-
): NODE | undefined {
|
|
2022
|
+
protected _swapProperties(srcNode: BTNRep<K, V, NODE> | R, destNode: BTNRep<K, V, NODE> | R): NODE | undefined {
|
|
2014
2023
|
srcNode = this.ensureNode(srcNode);
|
|
2015
2024
|
destNode = this.ensureNode(destNode);
|
|
2016
2025
|
|
|
@@ -2020,10 +2029,10 @@ export class BinaryTree<
|
|
|
2020
2029
|
|
|
2021
2030
|
if (tempNode) {
|
|
2022
2031
|
destNode.key = srcNode.key;
|
|
2023
|
-
destNode.value = srcNode.value;
|
|
2032
|
+
if (!this._isMapMode) destNode.value = srcNode.value;
|
|
2024
2033
|
|
|
2025
2034
|
srcNode.key = tempNode.key;
|
|
2026
|
-
srcNode.value = tempNode.value;
|
|
2035
|
+
if (!this._isMapMode) srcNode.value = tempNode.value;
|
|
2027
2036
|
}
|
|
2028
2037
|
|
|
2029
2038
|
return destNode;
|
|
@@ -2069,10 +2078,10 @@ export class BinaryTree<
|
|
|
2069
2078
|
*
|
|
2070
2079
|
* The function _setRoot sets the root node of a data structure while updating the parent reference
|
|
2071
2080
|
* of the previous root node.
|
|
2072
|
-
* @param v - The parameter `v` in the `_setRoot` method is of type `
|
|
2081
|
+
* @param v - The parameter `v` in the `_setRoot` method is of type `OptNodeOrNull<NODE>`, which means
|
|
2073
2082
|
* it can either be an optional `NODE` type or `null`.
|
|
2074
2083
|
*/
|
|
2075
|
-
protected _setRoot(v:
|
|
2084
|
+
protected _setRoot(v: OptNodeOrNull<NODE>) {
|
|
2076
2085
|
if (v) {
|
|
2077
2086
|
v.parent = undefined;
|
|
2078
2087
|
}
|
|
@@ -2085,49 +2094,116 @@ export class BinaryTree<
|
|
|
2085
2094
|
*
|
|
2086
2095
|
* The function `_ensurePredicate` in TypeScript ensures that the input is converted into a valid
|
|
2087
2096
|
* predicate function for a binary tree node.
|
|
2088
|
-
* @param {
|
|
2097
|
+
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate - The
|
|
2089
2098
|
* `_ensurePredicate` method in the provided code snippet is responsible for ensuring that the input
|
|
2090
|
-
* parameter `
|
|
2099
|
+
* parameter `keyNodeEntryRawOrPredicate` is transformed into a valid predicate function that can be
|
|
2091
2100
|
* used for filtering nodes in a binary tree.
|
|
2092
|
-
* @returns A
|
|
2101
|
+
* @returns A NodePredicate<NODE> function is being returned.
|
|
2093
2102
|
*/
|
|
2094
2103
|
protected _ensurePredicate(
|
|
2095
|
-
|
|
2096
|
-
):
|
|
2097
|
-
if (
|
|
2104
|
+
keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R | NodePredicate<NODE>
|
|
2105
|
+
): NodePredicate<NODE> {
|
|
2106
|
+
if (keyNodeEntryRawOrPredicate === null || keyNodeEntryRawOrPredicate === undefined)
|
|
2098
2107
|
return (node: NODE) => (node ? false : false);
|
|
2099
2108
|
|
|
2100
|
-
if (this.
|
|
2109
|
+
if (this._isPredicate(keyNodeEntryRawOrPredicate)) return keyNodeEntryRawOrPredicate;
|
|
2101
2110
|
|
|
2102
|
-
if (this.isRealNode(
|
|
2111
|
+
if (this.isRealNode(keyNodeEntryRawOrPredicate)) return (node: NODE) => node === keyNodeEntryRawOrPredicate;
|
|
2103
2112
|
|
|
2104
|
-
if (this.isEntry(
|
|
2105
|
-
const [key] =
|
|
2113
|
+
if (this.isEntry(keyNodeEntryRawOrPredicate)) {
|
|
2114
|
+
const [key] = keyNodeEntryRawOrPredicate;
|
|
2106
2115
|
return (node: NODE) => node.key === key;
|
|
2107
2116
|
}
|
|
2108
2117
|
|
|
2109
|
-
if (this.isKey(
|
|
2118
|
+
if (this.isKey(keyNodeEntryRawOrPredicate)) return (node: NODE) => node.key === keyNodeEntryRawOrPredicate;
|
|
2110
2119
|
|
|
2111
2120
|
if (this._toEntryFn) {
|
|
2112
|
-
const [key] = this._toEntryFn(
|
|
2121
|
+
const [key] = this._toEntryFn(keyNodeEntryRawOrPredicate);
|
|
2113
2122
|
return (node: NODE) => node.key === key;
|
|
2114
2123
|
}
|
|
2115
|
-
return (node: NODE) => node.key ===
|
|
2124
|
+
return (node: NODE) => node.key === keyNodeEntryRawOrPredicate;
|
|
2116
2125
|
}
|
|
2117
2126
|
|
|
2118
2127
|
/**
|
|
2119
2128
|
* Time Complexity: O(1)
|
|
2120
2129
|
* Space Complexity: O(1)
|
|
2121
2130
|
*
|
|
2122
|
-
* The function `
|
|
2131
|
+
* The function `_isPredicate` checks if a given parameter is a function.
|
|
2123
2132
|
* @param {any} p - The parameter `p` is a variable of type `any`, which means it can hold any type
|
|
2124
|
-
* of value. In this context, the function `
|
|
2125
|
-
* satisfies the type `
|
|
2133
|
+
* of value. In this context, the function `_isPredicate` is checking if `p` is a function that
|
|
2134
|
+
* satisfies the type `NodePredicate<NODE>`.
|
|
2126
2135
|
* @returns The function is checking if the input `p` is a function and returning a boolean value
|
|
2127
2136
|
* based on that check. If `p` is a function, it will return `true`, indicating that `p` is a
|
|
2128
2137
|
* predicate function for a binary tree node. If `p` is not a function, it will return `false`.
|
|
2129
2138
|
*/
|
|
2130
|
-
protected
|
|
2139
|
+
protected _isPredicate(p: any): p is NodePredicate<NODE> {
|
|
2131
2140
|
return typeof p === 'function';
|
|
2132
2141
|
}
|
|
2142
|
+
|
|
2143
|
+
/**
|
|
2144
|
+
* Time Complexity: O(1)
|
|
2145
|
+
* Space Complexity: O(1)
|
|
2146
|
+
*
|
|
2147
|
+
* The function `_getKey` in TypeScript returns the key from a given input, which can be a node,
|
|
2148
|
+
* entry, raw data, or null/undefined.
|
|
2149
|
+
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The `_getKey` method you provided is a
|
|
2150
|
+
* TypeScript method that takes in a parameter `keyNodeEntryOrRaw` of type `BTNRep<K, V, NODE> | R`,
|
|
2151
|
+
* where `BTNRep` is a generic type with keys `K`, `V`, and `NODE`, and `
|
|
2152
|
+
* @returns The `_getKey` method returns the key value extracted from the `keyNodeEntryOrRaw`
|
|
2153
|
+
* parameter. The return value can be a key value of type `K`, `null`, or `undefined`, depending on
|
|
2154
|
+
* the conditions checked in the method.
|
|
2155
|
+
*/
|
|
2156
|
+
protected _getKey(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): K | null | undefined {
|
|
2157
|
+
if (keyNodeEntryOrRaw === null) return null;
|
|
2158
|
+
if (keyNodeEntryOrRaw === undefined) return;
|
|
2159
|
+
if (keyNodeEntryOrRaw === this._NIL) return;
|
|
2160
|
+
if (this.isNode(keyNodeEntryOrRaw)) return keyNodeEntryOrRaw.key;
|
|
2161
|
+
|
|
2162
|
+
if (this.isEntry(keyNodeEntryOrRaw)) return keyNodeEntryOrRaw[0];
|
|
2163
|
+
|
|
2164
|
+
if (this.isRaw(keyNodeEntryOrRaw)) {
|
|
2165
|
+
if (this._toEntryFn) {
|
|
2166
|
+
const [key] = this._toEntryFn(keyNodeEntryOrRaw);
|
|
2167
|
+
return key;
|
|
2168
|
+
}
|
|
2169
|
+
return;
|
|
2170
|
+
}
|
|
2171
|
+
|
|
2172
|
+
return keyNodeEntryOrRaw;
|
|
2173
|
+
}
|
|
2174
|
+
|
|
2175
|
+
/**
|
|
2176
|
+
* Time Complexity: O(1)
|
|
2177
|
+
* Space Complexity: O(1)
|
|
2178
|
+
*
|
|
2179
|
+
* The function `_setValue` sets a value in a store based on a key, handling cases where the key or
|
|
2180
|
+
* value is null or undefined.
|
|
2181
|
+
* @param {K | null | undefined} key - The `key` parameter can be of type `K`, `null`, or
|
|
2182
|
+
* `undefined`.
|
|
2183
|
+
* @param {V | undefined} value - The `value` parameter in the `_setValue` method can be of type `V`
|
|
2184
|
+
* or `undefined`.
|
|
2185
|
+
* @returns The method `_setValue` returns `false` if either the `key` is `null` or `undefined`, or
|
|
2186
|
+
* if the `value` is `undefined`. Otherwise, it returns the result of calling the `set` method on the
|
|
2187
|
+
* `_store` object with the `key` and `value` arguments.
|
|
2188
|
+
*/
|
|
2189
|
+
protected _setValue(key: K | null | undefined, value: V | undefined) {
|
|
2190
|
+
if (key === null || key === undefined) return false;
|
|
2191
|
+
if (value === undefined) return false;
|
|
2192
|
+
return this._store.set(key, value);
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2195
|
+
/**
|
|
2196
|
+
* The _clearNodes function sets the root node to undefined and resets the size to 0.
|
|
2197
|
+
*/
|
|
2198
|
+
protected _clearNodes() {
|
|
2199
|
+
this._setRoot(undefined);
|
|
2200
|
+
this._size = 0;
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2203
|
+
/**
|
|
2204
|
+
* The _clearValues function clears all values stored in the _store object.
|
|
2205
|
+
*/
|
|
2206
|
+
protected _clearValues() {
|
|
2207
|
+
this._store.clear();
|
|
2208
|
+
}
|
|
2133
2209
|
}
|