deque-typed 1.52.9 → 1.53.1
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 +21 -21
- 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 +29 -27
- package/dist/data-structures/binary-tree/binary-tree.d.ts +186 -144
- package/dist/data-structures/binary-tree/binary-tree.js +376 -265
- package/dist/data-structures/binary-tree/bst.d.ts +56 -56
- package/dist/data-structures/binary-tree/bst.js +108 -78
- package/dist/data-structures/binary-tree/rb-tree.d.ts +13 -13
- package/dist/data-structures/binary-tree/rb-tree.js +42 -36
- package/dist/data-structures/binary-tree/tree-multi-map.d.ts +21 -21
- package/dist/data-structures/binary-tree/tree-multi-map.js +59 -49
- 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 -54
- package/src/data-structures/binary-tree/avl-tree.ts +32 -35
- package/src/data-structures/binary-tree/binary-tree.ts +440 -360
- package/src/data-structures/binary-tree/bst.ts +144 -113
- package/src/data-structures/binary-tree/rb-tree.ts +44 -43
- package/src/data-structures/binary-tree/tree-multi-map.ts +57 -61
- 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 +13 -14
- package/src/types/data-structures/binary-tree/bst.ts +3 -3
|
@@ -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 = true;
|
|
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;
|
|
@@ -170,7 +181,7 @@ export class BinaryTree<
|
|
|
170
181
|
* as NODE.
|
|
171
182
|
*/
|
|
172
183
|
createNode(key: K, value?: V): NODE {
|
|
173
|
-
return new BinaryTreeNode<K, V, NODE>(key, value) as NODE;
|
|
184
|
+
return new BinaryTreeNode<K, V, NODE>(key, this._isMapMode ? undefined : value) as NODE;
|
|
174
185
|
}
|
|
175
186
|
|
|
176
187
|
/**
|
|
@@ -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,7 +531,7 @@ 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
536
|
* node, entry or raw data. The method returns an array of
|
|
521
537
|
* `BinaryTreeDeleteResult` objects containing information about the deleted node and whether
|
|
@@ -524,11 +540,11 @@ export class BinaryTree<
|
|
|
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(
|
|
543
|
+
delete(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R): BinaryTreeDeleteResult<NODE>[] {
|
|
528
544
|
const deletedResult: BinaryTreeDeleteResult<NODE>[] = [];
|
|
529
545
|
if (!this._root) return deletedResult;
|
|
530
546
|
|
|
531
|
-
const curr = this.getNode(
|
|
547
|
+
const curr = this.getNode(keyNodeEntryOrRaw);
|
|
532
548
|
if (!curr) return deletedResult;
|
|
533
549
|
|
|
534
550
|
const parent: NODE | undefined = curr?.parent;
|
|
@@ -565,6 +581,7 @@ export class BinaryTree<
|
|
|
565
581
|
this._size = this._size - 1;
|
|
566
582
|
|
|
567
583
|
deletedResult.push({ deleted: orgCurrent, needBalanced });
|
|
584
|
+
if (this._isMapMode && orgCurrent) this._store.delete(orgCurrent.key);
|
|
568
585
|
return deletedResult;
|
|
569
586
|
}
|
|
570
587
|
|
|
@@ -574,12 +591,12 @@ export class BinaryTree<
|
|
|
574
591
|
*
|
|
575
592
|
* The function `getNodes` retrieves nodes from a binary tree based on a key, node, entry, raw data,
|
|
576
593
|
* or predicate, with options for recursive or iterative traversal.
|
|
577
|
-
* @param {
|
|
594
|
+
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate
|
|
578
595
|
* - The `getNodes` function you provided takes several parameters:
|
|
579
596
|
* @param [onlyOne=false] - The `onlyOne` parameter in the `getNodes` function is a boolean flag that
|
|
580
597
|
* determines whether to return only the first node that matches the criteria specified by the
|
|
581
|
-
* `
|
|
582
|
-
* @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
|
|
583
600
|
* `getNodes` function is used to specify the starting point for traversing the binary tree. It
|
|
584
601
|
* represents the root node of the binary tree or the node from which the traversal should begin. If
|
|
585
602
|
* not provided, the default value is set to `this._root
|
|
@@ -590,16 +607,16 @@ export class BinaryTree<
|
|
|
590
607
|
* based on the input parameters and the iteration type specified.
|
|
591
608
|
*/
|
|
592
609
|
getNodes(
|
|
593
|
-
|
|
610
|
+
keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R | NodePredicate<NODE>,
|
|
594
611
|
onlyOne = false,
|
|
595
|
-
|
|
612
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
596
613
|
iterationType: IterationType = this.iterationType
|
|
597
614
|
): NODE[] {
|
|
598
|
-
if (
|
|
599
|
-
if (
|
|
600
|
-
|
|
601
|
-
if (!
|
|
602
|
-
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);
|
|
603
620
|
|
|
604
621
|
const ans: NODE[] = [];
|
|
605
622
|
|
|
@@ -614,9 +631,9 @@ export class BinaryTree<
|
|
|
614
631
|
if (this.isRealNode(cur.right)) dfs(cur.right);
|
|
615
632
|
};
|
|
616
633
|
|
|
617
|
-
dfs(
|
|
634
|
+
dfs(startNode);
|
|
618
635
|
} else {
|
|
619
|
-
const stack = [
|
|
636
|
+
const stack = [startNode];
|
|
620
637
|
while (stack.length > 0) {
|
|
621
638
|
const cur = stack.pop();
|
|
622
639
|
if (this.isRealNode(cur)) {
|
|
@@ -639,10 +656,10 @@ export class BinaryTree<
|
|
|
639
656
|
*
|
|
640
657
|
* The `getNode` function retrieves a node based on the provided key, node, entry, raw data, or
|
|
641
658
|
* predicate.
|
|
642
|
-
* @param {
|
|
643
|
-
* - The `
|
|
659
|
+
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate
|
|
660
|
+
* - The `keyNodeEntryRawOrPredicate` parameter in the `getNode` function can accept a key,
|
|
644
661
|
* node, entry, raw data, or a predicate function.
|
|
645
|
-
* @param {
|
|
662
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
646
663
|
* `getNode` function is used to specify the starting point for searching for a node in a binary
|
|
647
664
|
* tree. If no specific starting point is provided, the default value is set to `this._root`, which
|
|
648
665
|
* is typically the root node of the binary tree.
|
|
@@ -654,11 +671,11 @@ export class BinaryTree<
|
|
|
654
671
|
* or `null` if no matching node is found.
|
|
655
672
|
*/
|
|
656
673
|
getNode(
|
|
657
|
-
|
|
658
|
-
|
|
674
|
+
keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R | NodePredicate<NODE>,
|
|
675
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
659
676
|
iterationType: IterationType = this.iterationType
|
|
660
|
-
):
|
|
661
|
-
return this.getNodes(
|
|
677
|
+
): OptNodeOrNull<NODE> {
|
|
678
|
+
return this.getNodes(keyNodeEntryRawOrPredicate, true, startNode, iterationType)[0] ?? null;
|
|
662
679
|
}
|
|
663
680
|
|
|
664
681
|
/**
|
|
@@ -672,9 +689,9 @@ export class BinaryTree<
|
|
|
672
689
|
* specifies how the tree nodes should be traversed when searching for a node with the given key. It
|
|
673
690
|
* is an optional parameter with a default value of `this.iterationType`.
|
|
674
691
|
* @returns The `getNodeByKey` function is returning an optional binary tree node
|
|
675
|
-
* (`
|
|
692
|
+
* (`OptNodeOrNull<NODE>`).
|
|
676
693
|
*/
|
|
677
|
-
getNodeByKey(key: K, iterationType: IterationType = this.iterationType):
|
|
694
|
+
getNodeByKey(key: K, iterationType: IterationType = this.iterationType): OptNodeOrNull<NODE> {
|
|
678
695
|
return this.getNode(key, this._root, iterationType);
|
|
679
696
|
}
|
|
680
697
|
|
|
@@ -684,10 +701,10 @@ export class BinaryTree<
|
|
|
684
701
|
*
|
|
685
702
|
* This function overrides the `get` method to retrieve the value associated with a specified key,
|
|
686
703
|
* node, entry, raw data, or predicate in a data structure.
|
|
687
|
-
* @param {
|
|
688
|
-
* - The `
|
|
704
|
+
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate
|
|
705
|
+
* - The `keyNodeEntryRawOrPredicate` parameter in the `get` method can accept one of the
|
|
689
706
|
* following types:
|
|
690
|
-
* @param {
|
|
707
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `get`
|
|
691
708
|
* method is used to specify the starting point for searching for a key or node in the binary tree.
|
|
692
709
|
* If no specific starting point is provided, the default starting point is the root of the binary
|
|
693
710
|
* tree (`this._root`).
|
|
@@ -701,11 +718,16 @@ export class BinaryTree<
|
|
|
701
718
|
* `undefined`.
|
|
702
719
|
*/
|
|
703
720
|
override get(
|
|
704
|
-
|
|
705
|
-
|
|
721
|
+
keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R,
|
|
722
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
706
723
|
iterationType: IterationType = this.iterationType
|
|
707
724
|
): V | undefined {
|
|
708
|
-
|
|
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;
|
|
709
731
|
}
|
|
710
732
|
|
|
711
733
|
/**
|
|
@@ -714,10 +736,10 @@ export class BinaryTree<
|
|
|
714
736
|
*
|
|
715
737
|
* The `has` function in TypeScript checks if a specified key, node, entry, raw data, or predicate
|
|
716
738
|
* exists in the data structure.
|
|
717
|
-
* @param {
|
|
718
|
-
* - The `
|
|
739
|
+
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate
|
|
740
|
+
* - The `keyNodeEntryRawOrPredicate` parameter in the `override has` method can accept one of
|
|
719
741
|
* the following types:
|
|
720
|
-
* @param {
|
|
742
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
721
743
|
* `override` method is used to specify the starting point for the search operation within the data
|
|
722
744
|
* structure. It defaults to `this._root` if not provided explicitly.
|
|
723
745
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `override has` method
|
|
@@ -730,11 +752,11 @@ export class BinaryTree<
|
|
|
730
752
|
* Otherwise, it returns `false`.
|
|
731
753
|
*/
|
|
732
754
|
override has(
|
|
733
|
-
|
|
734
|
-
|
|
755
|
+
keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R | NodePredicate<NODE>,
|
|
756
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
735
757
|
iterationType: IterationType = this.iterationType
|
|
736
758
|
): boolean {
|
|
737
|
-
return this.getNodes(
|
|
759
|
+
return this.getNodes(keyNodeEntryRawOrPredicate, true, startNode, iterationType).length > 0;
|
|
738
760
|
}
|
|
739
761
|
|
|
740
762
|
/**
|
|
@@ -744,8 +766,8 @@ export class BinaryTree<
|
|
|
744
766
|
* The `clear` function resets the root node and size of a data structure to empty.
|
|
745
767
|
*/
|
|
746
768
|
clear() {
|
|
747
|
-
this.
|
|
748
|
-
this.
|
|
769
|
+
this._clearNodes();
|
|
770
|
+
if (this._isMapMode) this._clearValues();
|
|
749
771
|
}
|
|
750
772
|
|
|
751
773
|
/**
|
|
@@ -767,17 +789,17 @@ export class BinaryTree<
|
|
|
767
789
|
*
|
|
768
790
|
* The function checks if a binary tree is perfectly balanced by comparing its minimum height with
|
|
769
791
|
* its height.
|
|
770
|
-
* @param {
|
|
792
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter is the starting
|
|
771
793
|
* point for checking if the binary tree is perfectly balanced. It represents the root node of the
|
|
772
794
|
* binary tree or a specific node from which the balance check should begin.
|
|
773
795
|
* @returns The method `isPerfectlyBalanced` is returning a boolean value, which indicates whether
|
|
774
|
-
* the tree starting from the `
|
|
796
|
+
* the tree starting from the `startNode` node is perfectly balanced or not. The return value is
|
|
775
797
|
* determined by comparing the minimum height of the tree with the height of the tree. If the minimum
|
|
776
798
|
* height plus 1 is greater than or equal to the height of the tree, then it is considered perfectly
|
|
777
799
|
* balanced and
|
|
778
800
|
*/
|
|
779
|
-
isPerfectlyBalanced(
|
|
780
|
-
return this.getMinHeight(
|
|
801
|
+
isPerfectlyBalanced(startNode: BTNRep<K, V, NODE> | R = this._root): boolean {
|
|
802
|
+
return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);
|
|
781
803
|
}
|
|
782
804
|
|
|
783
805
|
/**
|
|
@@ -786,7 +808,7 @@ export class BinaryTree<
|
|
|
786
808
|
*
|
|
787
809
|
* The function `isBST` in TypeScript checks if a binary search tree is valid using either recursive
|
|
788
810
|
* or iterative methods.
|
|
789
|
-
* @param {
|
|
811
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `isBST`
|
|
790
812
|
* function represents the starting point for checking whether a binary search tree (BST) is valid.
|
|
791
813
|
* It can be a node in the BST or a reference to the root of the BST. If no specific node is
|
|
792
814
|
* provided, the function will default to
|
|
@@ -798,31 +820,28 @@ export class BinaryTree<
|
|
|
798
820
|
* the tree satisfies the BST property, where for every node, all nodes in its left subtree have keys
|
|
799
821
|
* less than the node's key, and all nodes in its right subtree have keys greater than the node's
|
|
800
822
|
*/
|
|
801
|
-
isBST(
|
|
802
|
-
beginRoot: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root,
|
|
803
|
-
iterationType: IterationType = this.iterationType
|
|
804
|
-
): boolean {
|
|
823
|
+
isBST(startNode: BTNRep<K, V, NODE> | R = this._root, iterationType: IterationType = this.iterationType): boolean {
|
|
805
824
|
// TODO there is a bug
|
|
806
|
-
|
|
807
|
-
if (!
|
|
825
|
+
startNode = this.ensureNode(startNode);
|
|
826
|
+
if (!startNode) return true;
|
|
808
827
|
|
|
809
828
|
if (iterationType === 'RECURSIVE') {
|
|
810
|
-
const dfs = (cur:
|
|
829
|
+
const dfs = (cur: OptNodeOrNull<NODE>, min: number, max: number): boolean => {
|
|
811
830
|
if (!this.isRealNode(cur)) return true;
|
|
812
831
|
const numKey = Number(cur.key);
|
|
813
832
|
if (numKey <= min || numKey >= max) return false;
|
|
814
833
|
return dfs(cur.left, min, numKey) && dfs(cur.right, numKey, max);
|
|
815
834
|
};
|
|
816
835
|
|
|
817
|
-
const isStandardBST = dfs(
|
|
818
|
-
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);
|
|
819
838
|
return isStandardBST || isInverseBST;
|
|
820
839
|
} else {
|
|
821
840
|
const checkBST = (checkMax = false) => {
|
|
822
841
|
const stack = [];
|
|
823
842
|
let prev = checkMax ? Number.MAX_SAFE_INTEGER : Number.MIN_SAFE_INTEGER;
|
|
824
843
|
// @ts-ignore
|
|
825
|
-
let curr:
|
|
844
|
+
let curr: OptNodeOrNull<NODE> = startNode;
|
|
826
845
|
while (this.isRealNode(curr) || stack.length > 0) {
|
|
827
846
|
while (this.isRealNode(curr)) {
|
|
828
847
|
stack.push(curr);
|
|
@@ -847,23 +866,20 @@ export class BinaryTree<
|
|
|
847
866
|
* Space Complexity: O(1)
|
|
848
867
|
*
|
|
849
868
|
* The `getDepth` function calculates the depth between two nodes in a binary tree.
|
|
850
|
-
* @param {
|
|
869
|
+
* @param {BTNRep<K, V, NODE> | R} dist - The `dist` parameter in the `getDepth`
|
|
851
870
|
* function represents the node or entry in a binary tree map, or a reference to a node in the tree.
|
|
852
|
-
* It is the target node for which you want to calculate the depth from the `
|
|
853
|
-
* @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
|
|
854
873
|
* `getDepth` function represents the starting point from which you want to calculate the depth of a
|
|
855
874
|
* given node or entry in a binary tree. If no specific starting point is provided, the default value
|
|
856
|
-
* for `
|
|
875
|
+
* for `startNode` is set to the root of the binary
|
|
857
876
|
* @returns The `getDepth` method returns the depth of a given node `dist` relative to the
|
|
858
|
-
* `
|
|
877
|
+
* `startNode` node in a binary tree. If the `dist` node is not found in the path to the `startNode`
|
|
859
878
|
* node, it returns the depth of the `dist` node from the root of the tree.
|
|
860
879
|
*/
|
|
861
|
-
getDepth(
|
|
862
|
-
dist: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
|
|
863
|
-
beginRoot: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root
|
|
864
|
-
): number {
|
|
880
|
+
getDepth(dist: BTNRep<K, V, NODE> | R, startNode: BTNRep<K, V, NODE> | R = this._root): number {
|
|
865
881
|
let distEnsured = this.ensureNode(dist);
|
|
866
|
-
const beginRootEnsured = this.ensureNode(
|
|
882
|
+
const beginRootEnsured = this.ensureNode(startNode);
|
|
867
883
|
let depth = 0;
|
|
868
884
|
while (distEnsured?.parent) {
|
|
869
885
|
if (distEnsured === beginRootEnsured) {
|
|
@@ -881,7 +897,7 @@ export class BinaryTree<
|
|
|
881
897
|
*
|
|
882
898
|
* The `getHeight` function calculates the maximum height of a binary tree using either a recursive
|
|
883
899
|
* or iterative approach in TypeScript.
|
|
884
|
-
* @param {
|
|
900
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter is the starting
|
|
885
901
|
* point from which the height of the binary tree will be calculated. It can be a node in the binary
|
|
886
902
|
* tree or a reference to the root of the tree. If not provided, it defaults to the root of the
|
|
887
903
|
* binary tree data structure.
|
|
@@ -892,24 +908,21 @@ export class BinaryTree<
|
|
|
892
908
|
* root node. The height is calculated based on the maximum depth of the tree, considering either a
|
|
893
909
|
* recursive approach or an iterative approach depending on the `iterationType` parameter.
|
|
894
910
|
*/
|
|
895
|
-
getHeight(
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
): number {
|
|
899
|
-
beginRoot = this.ensureNode(beginRoot);
|
|
900
|
-
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;
|
|
901
914
|
|
|
902
915
|
if (iterationType === 'RECURSIVE') {
|
|
903
|
-
const _getMaxHeight = (cur:
|
|
916
|
+
const _getMaxHeight = (cur: OptNodeOrNull<NODE>): number => {
|
|
904
917
|
if (!this.isRealNode(cur)) return -1;
|
|
905
918
|
const leftHeight = _getMaxHeight(cur.left);
|
|
906
919
|
const rightHeight = _getMaxHeight(cur.right);
|
|
907
920
|
return Math.max(leftHeight, rightHeight) + 1;
|
|
908
921
|
};
|
|
909
922
|
|
|
910
|
-
return _getMaxHeight(
|
|
923
|
+
return _getMaxHeight(startNode);
|
|
911
924
|
} else {
|
|
912
|
-
const stack: { node: NODE; depth: number }[] = [{ node:
|
|
925
|
+
const stack: { node: NODE; depth: number }[] = [{ node: startNode, depth: 0 }];
|
|
913
926
|
let maxHeight = 0;
|
|
914
927
|
|
|
915
928
|
while (stack.length > 0) {
|
|
@@ -931,7 +944,7 @@ export class BinaryTree<
|
|
|
931
944
|
*
|
|
932
945
|
* The `getMinHeight` function calculates the minimum height of a binary tree using either a
|
|
933
946
|
* recursive or iterative approach in TypeScript.
|
|
934
|
-
* @param {
|
|
947
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
935
948
|
* `getMinHeight` function represents the starting node from which the minimum height of the binary
|
|
936
949
|
* tree will be calculated. It is either a node in the binary tree or a reference to the root of the
|
|
937
950
|
* tree. If not provided, the default value is the root
|
|
@@ -944,14 +957,14 @@ export class BinaryTree<
|
|
|
944
957
|
* a stack) based on the `iterationType` parameter.
|
|
945
958
|
*/
|
|
946
959
|
getMinHeight(
|
|
947
|
-
|
|
960
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
948
961
|
iterationType: IterationType = this.iterationType
|
|
949
962
|
): number {
|
|
950
|
-
|
|
951
|
-
if (!
|
|
963
|
+
startNode = this.ensureNode(startNode);
|
|
964
|
+
if (!startNode) return -1;
|
|
952
965
|
|
|
953
966
|
if (iterationType === 'RECURSIVE') {
|
|
954
|
-
const _getMinHeight = (cur:
|
|
967
|
+
const _getMinHeight = (cur: OptNodeOrNull<NODE>): number => {
|
|
955
968
|
if (!this.isRealNode(cur)) return 0;
|
|
956
969
|
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return 0;
|
|
957
970
|
const leftMinHeight = _getMinHeight(cur.left);
|
|
@@ -959,11 +972,11 @@ export class BinaryTree<
|
|
|
959
972
|
return Math.min(leftMinHeight, rightMinHeight) + 1;
|
|
960
973
|
};
|
|
961
974
|
|
|
962
|
-
return _getMinHeight(
|
|
975
|
+
return _getMinHeight(startNode);
|
|
963
976
|
} else {
|
|
964
977
|
const stack: NODE[] = [];
|
|
965
|
-
let node:
|
|
966
|
-
last:
|
|
978
|
+
let node: OptNodeOrNull<NODE> = startNode,
|
|
979
|
+
last: OptNodeOrNull<NODE> = null;
|
|
967
980
|
const depths: Map<NODE, number> = new Map();
|
|
968
981
|
|
|
969
982
|
while (stack.length > 0 || node) {
|
|
@@ -985,7 +998,7 @@ export class BinaryTree<
|
|
|
985
998
|
}
|
|
986
999
|
}
|
|
987
1000
|
|
|
988
|
-
return depths.get(
|
|
1001
|
+
return depths.get(startNode)!;
|
|
989
1002
|
}
|
|
990
1003
|
}
|
|
991
1004
|
|
|
@@ -999,7 +1012,7 @@ export class BinaryTree<
|
|
|
999
1012
|
* the path to the root. It is expected to be a function that takes a node as an argument and returns
|
|
1000
1013
|
* a value based on that node. The return type of the callback function is determined by the generic
|
|
1001
1014
|
* type `C
|
|
1002
|
-
* @param {
|
|
1015
|
+
* @param {BTNRep<K, V, NODE> | R} beginNode - The `beginNode` parameter in the
|
|
1003
1016
|
* `getPathToRoot` function can be either a key, a node, an entry, or any other value of type `R`.
|
|
1004
1017
|
* @param [isReverse=true] - The `isReverse` parameter in the `getPathToRoot` function determines
|
|
1005
1018
|
* whether the resulting path from the given `beginNode` to the root should be in reverse order or
|
|
@@ -1009,9 +1022,9 @@ export class BinaryTree<
|
|
|
1009
1022
|
* array is either in reverse order or in the original order based on the value of the `isReverse`
|
|
1010
1023
|
* parameter.
|
|
1011
1024
|
*/
|
|
1012
|
-
getPathToRoot<C extends
|
|
1013
|
-
callback: C = this.
|
|
1014
|
-
beginNode:
|
|
1025
|
+
getPathToRoot<C extends NodeCallback<OptNodeOrNull<NODE>>>(
|
|
1026
|
+
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1027
|
+
beginNode: BTNRep<K, V, NODE> | R,
|
|
1015
1028
|
isReverse = true
|
|
1016
1029
|
): ReturnType<C>[] {
|
|
1017
1030
|
const result: ReturnType<C>[] = [];
|
|
@@ -1036,8 +1049,8 @@ export class BinaryTree<
|
|
|
1036
1049
|
* tail-recursive iteration.
|
|
1037
1050
|
* @param {C} callback - The `callback` parameter is a function that will be called with the leftmost
|
|
1038
1051
|
* node of a binary tree or with `undefined` if the tree is empty. It is provided with a default
|
|
1039
|
-
* value of `
|
|
1040
|
-
* @param {
|
|
1052
|
+
* value of `_DEFAULT_NODE_CALLBACK` if not specified.
|
|
1053
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
1041
1054
|
* `getLeftMost` function represents the starting point for finding the leftmost node in a binary
|
|
1042
1055
|
* tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
|
|
1043
1056
|
* starting point is provided, the function will default
|
|
@@ -1045,19 +1058,19 @@ export class BinaryTree<
|
|
|
1045
1058
|
* specifies the type of iteration to be used when traversing the binary tree nodes. It can have two
|
|
1046
1059
|
* possible values:
|
|
1047
1060
|
* @returns The `getLeftMost` function returns the result of the callback function `C` applied to the
|
|
1048
|
-
* leftmost node in the binary tree starting from the `
|
|
1049
|
-
* `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`
|
|
1050
1063
|
* node is not a real node, it returns the result of the callback
|
|
1051
1064
|
*/
|
|
1052
|
-
getLeftMost<C extends
|
|
1053
|
-
callback: C = this.
|
|
1054
|
-
|
|
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,
|
|
1055
1068
|
iterationType: IterationType = this.iterationType
|
|
1056
1069
|
): ReturnType<C> {
|
|
1057
|
-
if (this.isNIL(
|
|
1058
|
-
|
|
1070
|
+
if (this.isNIL(startNode)) return callback(undefined);
|
|
1071
|
+
startNode = this.ensureNode(startNode);
|
|
1059
1072
|
|
|
1060
|
-
if (!this.isRealNode(
|
|
1073
|
+
if (!this.isRealNode(startNode)) return callback(startNode);
|
|
1061
1074
|
|
|
1062
1075
|
if (iterationType === 'RECURSIVE') {
|
|
1063
1076
|
const dfs = (cur: NODE): NODE => {
|
|
@@ -1065,7 +1078,7 @@ export class BinaryTree<
|
|
|
1065
1078
|
return dfs(cur.left);
|
|
1066
1079
|
};
|
|
1067
1080
|
|
|
1068
|
-
return callback(dfs(
|
|
1081
|
+
return callback(dfs(startNode));
|
|
1069
1082
|
} else {
|
|
1070
1083
|
// Indirect implementation of iteration using tail recursion optimization
|
|
1071
1084
|
const dfs = trampoline((cur: NODE): NODE => {
|
|
@@ -1073,7 +1086,7 @@ export class BinaryTree<
|
|
|
1073
1086
|
return dfs.cont(cur.left);
|
|
1074
1087
|
});
|
|
1075
1088
|
|
|
1076
|
-
return callback(dfs(
|
|
1089
|
+
return callback(dfs(startNode));
|
|
1077
1090
|
}
|
|
1078
1091
|
}
|
|
1079
1092
|
|
|
@@ -1084,10 +1097,10 @@ export class BinaryTree<
|
|
|
1084
1097
|
* The function `getRightMost` retrieves the rightmost node in a binary tree using either recursive
|
|
1085
1098
|
* or iterative traversal methods.
|
|
1086
1099
|
* @param {C} callback - The `callback` parameter is a function that will be called with the result
|
|
1087
|
-
* 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>>`,
|
|
1088
1101
|
* which means it is a callback function that can accept either an optional binary tree node or null
|
|
1089
1102
|
* as
|
|
1090
|
-
* @param {
|
|
1103
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
1091
1104
|
* `getRightMost` function represents the starting point for finding the rightmost node in a binary
|
|
1092
1105
|
* tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
|
|
1093
1106
|
* starting point is provided, the function will default
|
|
@@ -1099,15 +1112,15 @@ export class BinaryTree<
|
|
|
1099
1112
|
* the binary tree structure, determined based on the specified iteration type ('RECURSIVE' or
|
|
1100
1113
|
* other).
|
|
1101
1114
|
*/
|
|
1102
|
-
getRightMost<C extends
|
|
1103
|
-
callback: C = this.
|
|
1104
|
-
|
|
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,
|
|
1105
1118
|
iterationType: IterationType = this.iterationType
|
|
1106
1119
|
): ReturnType<C> {
|
|
1107
|
-
if (this.isNIL(
|
|
1120
|
+
if (this.isNIL(startNode)) return callback(undefined);
|
|
1108
1121
|
// TODO support get right most by passing key in
|
|
1109
|
-
|
|
1110
|
-
if (!
|
|
1122
|
+
startNode = this.ensureNode(startNode);
|
|
1123
|
+
if (!startNode) return callback(startNode);
|
|
1111
1124
|
|
|
1112
1125
|
if (iterationType === 'RECURSIVE') {
|
|
1113
1126
|
const dfs = (cur: NODE): NODE => {
|
|
@@ -1115,7 +1128,7 @@ export class BinaryTree<
|
|
|
1115
1128
|
return dfs(cur.right);
|
|
1116
1129
|
};
|
|
1117
1130
|
|
|
1118
|
-
return callback(dfs(
|
|
1131
|
+
return callback(dfs(startNode));
|
|
1119
1132
|
} else {
|
|
1120
1133
|
// Indirect implementation of iteration using tail recursion optimization
|
|
1121
1134
|
const dfs = trampoline((cur: NODE) => {
|
|
@@ -1123,7 +1136,7 @@ export class BinaryTree<
|
|
|
1123
1136
|
return dfs.cont(cur.right);
|
|
1124
1137
|
});
|
|
1125
1138
|
|
|
1126
|
-
return callback(dfs(
|
|
1139
|
+
return callback(dfs(startNode));
|
|
1127
1140
|
}
|
|
1128
1141
|
}
|
|
1129
1142
|
|
|
@@ -1142,7 +1155,7 @@ export class BinaryTree<
|
|
|
1142
1155
|
*/
|
|
1143
1156
|
getPredecessor(node: NODE): NODE {
|
|
1144
1157
|
if (this.isRealNode(node.left)) {
|
|
1145
|
-
let predecessor:
|
|
1158
|
+
let predecessor: OptNodeOrNull<NODE> = node.left;
|
|
1146
1159
|
while (!this.isRealNode(predecessor) || (this.isRealNode(predecessor.right) && predecessor.right !== node)) {
|
|
1147
1160
|
if (this.isRealNode(predecessor)) {
|
|
1148
1161
|
predecessor = predecessor.right;
|
|
@@ -1167,7 +1180,7 @@ export class BinaryTree<
|
|
|
1167
1180
|
* have a right child, the function traverses up the parent nodes until it finds a node that is not
|
|
1168
1181
|
* the right child of its parent, and returns that node
|
|
1169
1182
|
*/
|
|
1170
|
-
getSuccessor(x?: K | NODE | null):
|
|
1183
|
+
getSuccessor(x?: K | NODE | null): OptNodeOrNull<NODE> {
|
|
1171
1184
|
x = this.ensureNode(x);
|
|
1172
1185
|
if (!this.isRealNode(x)) return undefined;
|
|
1173
1186
|
|
|
@@ -1175,7 +1188,7 @@ export class BinaryTree<
|
|
|
1175
1188
|
return this.getLeftMost(node => node, x.right);
|
|
1176
1189
|
}
|
|
1177
1190
|
|
|
1178
|
-
let y:
|
|
1191
|
+
let y: OptNodeOrNull<NODE> = x.parent;
|
|
1179
1192
|
while (this.isRealNode(y) && x === y.right) {
|
|
1180
1193
|
x = y;
|
|
1181
1194
|
y = y.parent;
|
|
@@ -1183,17 +1196,17 @@ export class BinaryTree<
|
|
|
1183
1196
|
return y;
|
|
1184
1197
|
}
|
|
1185
1198
|
|
|
1186
|
-
dfs<C extends
|
|
1199
|
+
dfs<C extends NodeCallback<NODE>>(
|
|
1187
1200
|
callback?: C,
|
|
1188
1201
|
pattern?: DFSOrderPattern,
|
|
1189
|
-
|
|
1202
|
+
startNode?: BTNRep<K, V, NODE> | R,
|
|
1190
1203
|
iterationType?: IterationType
|
|
1191
1204
|
): ReturnType<C>[];
|
|
1192
1205
|
|
|
1193
|
-
dfs<C extends
|
|
1206
|
+
dfs<C extends NodeCallback<NODE | null>>(
|
|
1194
1207
|
callback?: C,
|
|
1195
1208
|
pattern?: DFSOrderPattern,
|
|
1196
|
-
|
|
1209
|
+
startNode?: BTNRep<K, V, NODE> | R,
|
|
1197
1210
|
iterationType?: IterationType,
|
|
1198
1211
|
includeNull?: boolean
|
|
1199
1212
|
): ReturnType<C>[];
|
|
@@ -1205,14 +1218,14 @@ export class BinaryTree<
|
|
|
1205
1218
|
* The function `dfs` performs a depth-first search traversal on a binary tree structure based on the
|
|
1206
1219
|
* specified parameters.
|
|
1207
1220
|
* @param {C} callback - The `callback` parameter is a generic type `C` that extends the
|
|
1208
|
-
* `
|
|
1209
|
-
* `this.
|
|
1221
|
+
* `NodeCallback` interface with a type parameter of `OptNodeOrNull<NODE>`. It has a default value of
|
|
1222
|
+
* `this._DEFAULT_NODE_CALLBACK as C`.
|
|
1210
1223
|
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `dfs` method specifies the
|
|
1211
1224
|
* order in which the Depth-First Search (DFS) algorithm should traverse the nodes in the tree. The
|
|
1212
1225
|
* possible values for the `pattern` parameter are:
|
|
1213
|
-
* @param {
|
|
1226
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `dfs`
|
|
1214
1227
|
* method is used to specify the starting point for the Depth-First Search traversal. It can be
|
|
1215
|
-
* either a `
|
|
1228
|
+
* either a `BTNRep` object representing a key, node, or entry in the binary tree map,
|
|
1216
1229
|
* or it can be a
|
|
1217
1230
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `dfs` method specifies
|
|
1218
1231
|
* the type of iteration to be performed during the depth-first search traversal. It is used to
|
|
@@ -1224,28 +1237,28 @@ export class BinaryTree<
|
|
|
1224
1237
|
* @returns The `dfs` method is returning an array of the return type specified by the generic type
|
|
1225
1238
|
* parameter `C`. The return type is determined by the callback function provided to the method.
|
|
1226
1239
|
*/
|
|
1227
|
-
dfs<C extends
|
|
1228
|
-
callback: C = this.
|
|
1240
|
+
dfs<C extends NodeCallback<OptNodeOrNull<NODE>>>(
|
|
1241
|
+
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1229
1242
|
pattern: DFSOrderPattern = 'IN',
|
|
1230
|
-
|
|
1243
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
1231
1244
|
iterationType: IterationType = this.iterationType,
|
|
1232
1245
|
includeNull = false
|
|
1233
1246
|
): ReturnType<C>[] {
|
|
1234
|
-
|
|
1235
|
-
if (!
|
|
1236
|
-
return this._dfs(callback, pattern,
|
|
1247
|
+
startNode = this.ensureNode(startNode);
|
|
1248
|
+
if (!startNode) return [];
|
|
1249
|
+
return this._dfs(callback, pattern, startNode, iterationType, includeNull);
|
|
1237
1250
|
}
|
|
1238
1251
|
|
|
1239
|
-
bfs<C extends
|
|
1252
|
+
bfs<C extends NodeCallback<NODE>>(
|
|
1240
1253
|
callback?: C,
|
|
1241
|
-
|
|
1254
|
+
startNode?: BTNRep<K, V, NODE> | R,
|
|
1242
1255
|
iterationType?: IterationType,
|
|
1243
1256
|
includeNull?: false
|
|
1244
1257
|
): ReturnType<C>[];
|
|
1245
1258
|
|
|
1246
|
-
bfs<C extends
|
|
1259
|
+
bfs<C extends NodeCallback<NODE | null>>(
|
|
1247
1260
|
callback?: C,
|
|
1248
|
-
|
|
1261
|
+
startNode?: BTNRep<K, V, NODE> | R,
|
|
1249
1262
|
iterationType?: IterationType,
|
|
1250
1263
|
includeNull?: true
|
|
1251
1264
|
): ReturnType<C>[];
|
|
@@ -1258,8 +1271,8 @@ export class BinaryTree<
|
|
|
1258
1271
|
* tree, executing a specified callback function on each node visited.
|
|
1259
1272
|
* @param {C} callback - The `callback` parameter in the `bfs` function is a function that will be
|
|
1260
1273
|
* called on each node visited during the breadth-first search traversal. It is a generic type `C`
|
|
1261
|
-
* that extends the `
|
|
1262
|
-
* @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`
|
|
1263
1276
|
* function represents the starting point for the breadth-first search traversal in a binary tree. It
|
|
1264
1277
|
* can be specified as a key, node, or entry in the binary tree structure. If not provided, the
|
|
1265
1278
|
* default value is the root node of the binary
|
|
@@ -1273,19 +1286,19 @@ export class BinaryTree<
|
|
|
1273
1286
|
* @returns The `bfs` function returns an array of values that are the result of applying the
|
|
1274
1287
|
* provided callback function to each node in the binary tree in a breadth-first search manner.
|
|
1275
1288
|
*/
|
|
1276
|
-
bfs<C extends
|
|
1277
|
-
callback: C = this.
|
|
1278
|
-
|
|
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,
|
|
1279
1292
|
iterationType: IterationType = this.iterationType,
|
|
1280
1293
|
includeNull = false
|
|
1281
1294
|
): ReturnType<C>[] {
|
|
1282
|
-
|
|
1283
|
-
if (!
|
|
1295
|
+
startNode = this.ensureNode(startNode);
|
|
1296
|
+
if (!startNode) return [];
|
|
1284
1297
|
|
|
1285
|
-
const ans: ReturnType<
|
|
1298
|
+
const ans: ReturnType<NodeCallback<NODE>>[] = [];
|
|
1286
1299
|
|
|
1287
1300
|
if (iterationType === 'RECURSIVE') {
|
|
1288
|
-
const queue: Queue<
|
|
1301
|
+
const queue: Queue<OptNodeOrNull<NODE>> = new Queue<OptNodeOrNull<NODE>>([startNode]);
|
|
1289
1302
|
|
|
1290
1303
|
const dfs = (level: number) => {
|
|
1291
1304
|
if (queue.size === 0) return;
|
|
@@ -1306,7 +1319,7 @@ export class BinaryTree<
|
|
|
1306
1319
|
|
|
1307
1320
|
dfs(0);
|
|
1308
1321
|
} else {
|
|
1309
|
-
const queue = new Queue<
|
|
1322
|
+
const queue = new Queue<OptNodeOrNull<NODE>>([startNode]);
|
|
1310
1323
|
while (queue.size > 0) {
|
|
1311
1324
|
const levelSize = queue.size;
|
|
1312
1325
|
|
|
@@ -1335,7 +1348,7 @@ export class BinaryTree<
|
|
|
1335
1348
|
* structure based on a specified callback and iteration type.
|
|
1336
1349
|
* @param {C} callback - The `callback` parameter is a function that will be called on each leaf node
|
|
1337
1350
|
* in the binary tree. It is optional and defaults to a default callback function if not provided.
|
|
1338
|
-
* @param {
|
|
1351
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `leaves`
|
|
1339
1352
|
* method is used to specify the starting point for finding and processing the leaves of a binary
|
|
1340
1353
|
* tree. It can be provided as either a key, a node, or an entry in the binary tree structure. If not
|
|
1341
1354
|
* explicitly provided, the default value
|
|
@@ -1345,14 +1358,14 @@ export class BinaryTree<
|
|
|
1345
1358
|
* @returns The `leaves` method returns an array of values that are the result of applying the
|
|
1346
1359
|
* provided callback function to each leaf node in the binary tree.
|
|
1347
1360
|
*/
|
|
1348
|
-
leaves<C extends
|
|
1349
|
-
callback: C = this.
|
|
1350
|
-
|
|
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,
|
|
1351
1364
|
iterationType: IterationType = this.iterationType
|
|
1352
1365
|
): ReturnType<C>[] {
|
|
1353
|
-
|
|
1354
|
-
const leaves: ReturnType<
|
|
1355
|
-
if (!this.isRealNode(
|
|
1366
|
+
startNode = this.ensureNode(startNode);
|
|
1367
|
+
const leaves: ReturnType<NodeCallback<NODE>>[] = [];
|
|
1368
|
+
if (!this.isRealNode(startNode)) return [];
|
|
1356
1369
|
|
|
1357
1370
|
if (iterationType === 'RECURSIVE') {
|
|
1358
1371
|
const dfs = (cur: NODE) => {
|
|
@@ -1364,9 +1377,9 @@ export class BinaryTree<
|
|
|
1364
1377
|
if (this.isRealNode(cur.right)) dfs(cur.right);
|
|
1365
1378
|
};
|
|
1366
1379
|
|
|
1367
|
-
dfs(
|
|
1380
|
+
dfs(startNode);
|
|
1368
1381
|
} else {
|
|
1369
|
-
const queue = new Queue([
|
|
1382
|
+
const queue = new Queue([startNode]);
|
|
1370
1383
|
while (queue.size > 0) {
|
|
1371
1384
|
const cur = queue.shift();
|
|
1372
1385
|
if (this.isRealNode(cur)) {
|
|
@@ -1382,16 +1395,16 @@ export class BinaryTree<
|
|
|
1382
1395
|
return leaves;
|
|
1383
1396
|
}
|
|
1384
1397
|
|
|
1385
|
-
listLevels<C extends
|
|
1398
|
+
listLevels<C extends NodeCallback<NODE>>(
|
|
1386
1399
|
callback?: C,
|
|
1387
|
-
|
|
1400
|
+
startNode?: BTNRep<K, V, NODE> | R,
|
|
1388
1401
|
iterationType?: IterationType,
|
|
1389
1402
|
includeNull?: false
|
|
1390
1403
|
): ReturnType<C>[][];
|
|
1391
1404
|
|
|
1392
|
-
listLevels<C extends
|
|
1405
|
+
listLevels<C extends NodeCallback<NODE | null>>(
|
|
1393
1406
|
callback?: C,
|
|
1394
|
-
|
|
1407
|
+
startNode?: BTNRep<K, V, NODE> | R,
|
|
1395
1408
|
iterationType?: IterationType,
|
|
1396
1409
|
includeNull?: true
|
|
1397
1410
|
): ReturnType<C>[][];
|
|
@@ -1405,7 +1418,7 @@ export class BinaryTree<
|
|
|
1405
1418
|
* @param {C} callback - The `callback` parameter is a function that will be applied to each node in
|
|
1406
1419
|
* the binary tree during the traversal. It is used to process each node and determine what
|
|
1407
1420
|
* information to include in the output for each level of the tree.
|
|
1408
|
-
* @param {
|
|
1421
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
1409
1422
|
* `listLevels` function represents the starting point for traversing the binary tree. It can be
|
|
1410
1423
|
* either a key, a node, or an entry in the binary tree. If not provided, the default value is the
|
|
1411
1424
|
* root of the binary tree.
|
|
@@ -1420,15 +1433,15 @@ export class BinaryTree<
|
|
|
1420
1433
|
* level in a binary tree. Each inner array contains the return value of the provided callback
|
|
1421
1434
|
* function applied to the nodes at that level.
|
|
1422
1435
|
*/
|
|
1423
|
-
listLevels<C extends
|
|
1424
|
-
callback: C = this.
|
|
1425
|
-
|
|
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,
|
|
1426
1439
|
iterationType: IterationType = this.iterationType,
|
|
1427
1440
|
includeNull = false
|
|
1428
1441
|
): ReturnType<C>[][] {
|
|
1429
|
-
|
|
1442
|
+
startNode = this.ensureNode(startNode);
|
|
1430
1443
|
const levelsNodes: ReturnType<C>[][] = [];
|
|
1431
|
-
if (!
|
|
1444
|
+
if (!startNode) return levelsNodes;
|
|
1432
1445
|
|
|
1433
1446
|
if (iterationType === 'RECURSIVE') {
|
|
1434
1447
|
const _recursive = (node: NODE | null, level: number) => {
|
|
@@ -1443,9 +1456,9 @@ export class BinaryTree<
|
|
|
1443
1456
|
}
|
|
1444
1457
|
};
|
|
1445
1458
|
|
|
1446
|
-
_recursive(
|
|
1459
|
+
_recursive(startNode, 0);
|
|
1447
1460
|
} else {
|
|
1448
|
-
const stack: [NODE | null, number][] = [[
|
|
1461
|
+
const stack: [NODE | null, number][] = [[startNode, 0]];
|
|
1449
1462
|
|
|
1450
1463
|
while (stack.length > 0) {
|
|
1451
1464
|
const head = stack.pop()!;
|
|
@@ -1475,11 +1488,11 @@ export class BinaryTree<
|
|
|
1475
1488
|
* Morris Traversal algorithm with different order patterns.
|
|
1476
1489
|
* @param {C} callback - The `callback` parameter in the `morris` function is a function that will be
|
|
1477
1490
|
* called on each node in the binary tree during the traversal. It is of type `C`, which extends the
|
|
1478
|
-
* `
|
|
1491
|
+
* `NodeCallback<NODE>` type. The default value for `callback` is `this._DEFAULT
|
|
1479
1492
|
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `morris` function specifies
|
|
1480
1493
|
* the type of Depth-First Search (DFS) order pattern to traverse the binary tree. The possible
|
|
1481
1494
|
* values for the `pattern` parameter are:
|
|
1482
|
-
* @param {
|
|
1495
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `morris`
|
|
1483
1496
|
* function is the starting point for the Morris traversal algorithm. It represents the root node of
|
|
1484
1497
|
* the binary tree or the node from which the traversal should begin. It can be provided as either a
|
|
1485
1498
|
* key, a node, an entry, or a reference
|
|
@@ -1487,19 +1500,19 @@ export class BinaryTree<
|
|
|
1487
1500
|
* provided callback function to each node in the binary tree in the specified order pattern (IN,
|
|
1488
1501
|
* PRE, or POST).
|
|
1489
1502
|
*/
|
|
1490
|
-
morris<C extends
|
|
1491
|
-
callback: C = this.
|
|
1503
|
+
morris<C extends NodeCallback<NODE>>(
|
|
1504
|
+
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1492
1505
|
pattern: DFSOrderPattern = 'IN',
|
|
1493
|
-
|
|
1506
|
+
startNode: BTNRep<K, V, NODE> | R = this._root
|
|
1494
1507
|
): ReturnType<C>[] {
|
|
1495
|
-
|
|
1496
|
-
if (!
|
|
1497
|
-
const ans: ReturnType<
|
|
1498
|
-
|
|
1499
|
-
let cur:
|
|
1500
|
-
const _reverseEdge = (node:
|
|
1501
|
-
let pre:
|
|
1502
|
-
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;
|
|
1503
1516
|
while (node) {
|
|
1504
1517
|
next = node.right;
|
|
1505
1518
|
node.right = pre;
|
|
@@ -1508,9 +1521,9 @@ export class BinaryTree<
|
|
|
1508
1521
|
}
|
|
1509
1522
|
return pre;
|
|
1510
1523
|
};
|
|
1511
|
-
const _printEdge = (node:
|
|
1512
|
-
const tail:
|
|
1513
|
-
let cur:
|
|
1524
|
+
const _printEdge = (node: OptNodeOrNull<NODE>) => {
|
|
1525
|
+
const tail: OptNodeOrNull<NODE> = _reverseEdge(node);
|
|
1526
|
+
let cur: OptNodeOrNull<NODE> = tail;
|
|
1514
1527
|
while (cur) {
|
|
1515
1528
|
ans.push(callback(cur));
|
|
1516
1529
|
cur = cur.right;
|
|
@@ -1567,7 +1580,7 @@ export class BinaryTree<
|
|
|
1567
1580
|
}
|
|
1568
1581
|
cur = cur.right;
|
|
1569
1582
|
}
|
|
1570
|
-
_printEdge(
|
|
1583
|
+
_printEdge(startNode);
|
|
1571
1584
|
break;
|
|
1572
1585
|
}
|
|
1573
1586
|
return ans;
|
|
@@ -1589,12 +1602,16 @@ export class BinaryTree<
|
|
|
1589
1602
|
this.bfs(
|
|
1590
1603
|
node => {
|
|
1591
1604
|
if (node === null) cloned.add(null);
|
|
1592
|
-
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
|
+
}
|
|
1593
1609
|
},
|
|
1594
1610
|
this._root,
|
|
1595
1611
|
this.iterationType,
|
|
1596
1612
|
true
|
|
1597
1613
|
);
|
|
1614
|
+
if (this._isMapMode) cloned._store = this._store;
|
|
1598
1615
|
return cloned;
|
|
1599
1616
|
}
|
|
1600
1617
|
|
|
@@ -1665,7 +1682,7 @@ export class BinaryTree<
|
|
|
1665
1682
|
*
|
|
1666
1683
|
* The function `toVisual` in TypeScript overrides the visual representation of a binary tree with
|
|
1667
1684
|
* customizable options for displaying undefined, null, and sentinel nodes.
|
|
1668
|
-
* @param {
|
|
1685
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
1669
1686
|
* `toVisual` method is used to specify the starting point for visualizing the binary tree structure.
|
|
1670
1687
|
* It can be a node, key, entry, or the root of the tree. If no specific starting point is provided,
|
|
1671
1688
|
* the default is set to the root
|
|
@@ -1677,20 +1694,17 @@ export class BinaryTree<
|
|
|
1677
1694
|
* the lines to the output string. The final output string contains the visual representation of the
|
|
1678
1695
|
* binary tree with the specified options.
|
|
1679
1696
|
*/
|
|
1680
|
-
override toVisual(
|
|
1681
|
-
beginRoot: BTNKeyOrNodeOrEntry<K, V, NODE> | R = this._root,
|
|
1682
|
-
options?: BinaryTreePrintOptions
|
|
1683
|
-
): string {
|
|
1697
|
+
override toVisual(startNode: BTNRep<K, V, NODE> | R = this._root, options?: BinaryTreePrintOptions): string {
|
|
1684
1698
|
const opts = { isShowUndefined: false, isShowNull: true, isShowRedBlackNIL: false, ...options };
|
|
1685
|
-
|
|
1699
|
+
startNode = this.ensureNode(startNode);
|
|
1686
1700
|
let output = '';
|
|
1687
|
-
if (!
|
|
1701
|
+
if (!startNode) return output;
|
|
1688
1702
|
|
|
1689
1703
|
if (opts.isShowUndefined) output += `U for undefined\n`;
|
|
1690
1704
|
if (opts.isShowNull) output += `N for null\n`;
|
|
1691
1705
|
if (opts.isShowRedBlackNIL) output += `S for Sentinel Node(NIL)\n`;
|
|
1692
1706
|
|
|
1693
|
-
const display = (root:
|
|
1707
|
+
const display = (root: OptNodeOrNull<NODE>): void => {
|
|
1694
1708
|
const [lines, , ,] = this._displayAux(root, opts);
|
|
1695
1709
|
let paragraph = '';
|
|
1696
1710
|
for (const line of lines) {
|
|
@@ -1699,7 +1713,7 @@ export class BinaryTree<
|
|
|
1699
1713
|
output += paragraph;
|
|
1700
1714
|
};
|
|
1701
1715
|
|
|
1702
|
-
display(
|
|
1716
|
+
display(startNode);
|
|
1703
1717
|
return output;
|
|
1704
1718
|
}
|
|
1705
1719
|
|
|
@@ -1713,13 +1727,13 @@ export class BinaryTree<
|
|
|
1713
1727
|
* printing options for the binary tree. It is an optional parameter that allows you to customize how
|
|
1714
1728
|
* the binary tree is printed, such as choosing between different traversal orders or formatting
|
|
1715
1729
|
* options.
|
|
1716
|
-
* @param {
|
|
1730
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the
|
|
1717
1731
|
* `override print` method is used to specify the starting point for printing the binary tree. It can
|
|
1718
1732
|
* be either a key, a node, an entry, or the root of the tree. If no specific starting point is
|
|
1719
1733
|
* provided, the default value is set to
|
|
1720
1734
|
*/
|
|
1721
|
-
override print(options?: BinaryTreePrintOptions,
|
|
1722
|
-
console.log(this.toVisual(
|
|
1735
|
+
override print(options?: BinaryTreePrintOptions, startNode: BTNRep<K, V, NODE> | R = this._root) {
|
|
1736
|
+
console.log(this.toVisual(startNode, options));
|
|
1723
1737
|
}
|
|
1724
1738
|
|
|
1725
1739
|
/**
|
|
@@ -1730,13 +1744,13 @@ export class BinaryTree<
|
|
|
1730
1744
|
* the specified order pattern and callback function.
|
|
1731
1745
|
* @param {C} callback - The `callback` parameter in the `_dfs` method is a function that will be
|
|
1732
1746
|
* called on each node visited during the depth-first search traversal. It is of type `C`, which
|
|
1733
|
-
* extends `
|
|
1747
|
+
* extends `NodeCallback<OptNodeOrNull<NODE>>`. The default value for this parameter is `this._DEFAULT
|
|
1734
1748
|
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `_dfs` method specifies the
|
|
1735
1749
|
* order in which the nodes are visited during the Depth-First Search traversal. It can have one of
|
|
1736
1750
|
* the following values:
|
|
1737
|
-
* @param {
|
|
1751
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `_dfs`
|
|
1738
1752
|
* method is used to specify the starting point for the depth-first search traversal in a binary
|
|
1739
|
-
* 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
|
|
1740
1754
|
* of the tree. If no specific
|
|
1741
1755
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `_dfs` method
|
|
1742
1756
|
* specifies the type of iteration to be performed during the Depth-First Search (DFS) traversal of a
|
|
@@ -1764,26 +1778,26 @@ export class BinaryTree<
|
|
|
1764
1778
|
* @returns The function `_dfs` returns an array of the return type of the callback function provided
|
|
1765
1779
|
* as input.
|
|
1766
1780
|
*/
|
|
1767
|
-
protected _dfs<C extends
|
|
1768
|
-
callback: C = this.
|
|
1781
|
+
protected _dfs<C extends NodeCallback<OptNodeOrNull<NODE>>>(
|
|
1782
|
+
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1769
1783
|
pattern: DFSOrderPattern = 'IN',
|
|
1770
|
-
|
|
1784
|
+
startNode: BTNRep<K, V, NODE> | R = this._root,
|
|
1771
1785
|
iterationType: IterationType = this.iterationType,
|
|
1772
1786
|
includeNull = false,
|
|
1773
|
-
shouldVisitLeft: (node:
|
|
1774
|
-
shouldVisitRight: (node:
|
|
1775
|
-
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 => {
|
|
1776
1790
|
if (includeNull) return this.isRealNodeOrNull(node);
|
|
1777
1791
|
return this.isRealNode(node);
|
|
1778
1792
|
},
|
|
1779
|
-
shouldProcessRoot: (node:
|
|
1793
|
+
shouldProcessRoot: (node: OptNodeOrNull<NODE>) => boolean = node => this.isRealNodeOrNull(node)
|
|
1780
1794
|
): ReturnType<C>[] {
|
|
1781
|
-
|
|
1782
|
-
if (!
|
|
1795
|
+
startNode = this.ensureNode(startNode);
|
|
1796
|
+
if (!startNode) return [];
|
|
1783
1797
|
const ans: ReturnType<C>[] = [];
|
|
1784
1798
|
|
|
1785
1799
|
if (iterationType === 'RECURSIVE') {
|
|
1786
|
-
const dfs = (node:
|
|
1800
|
+
const dfs = (node: OptNodeOrNull<NODE>) => {
|
|
1787
1801
|
if (!shouldVisitRoot(node)) return;
|
|
1788
1802
|
|
|
1789
1803
|
const visitLeft = () => {
|
|
@@ -1812,9 +1826,9 @@ export class BinaryTree<
|
|
|
1812
1826
|
}
|
|
1813
1827
|
};
|
|
1814
1828
|
|
|
1815
|
-
dfs(
|
|
1829
|
+
dfs(startNode);
|
|
1816
1830
|
} else {
|
|
1817
|
-
const stack: DFSStackItem<NODE>[] = [{ opt: DFSOperation.VISIT, node:
|
|
1831
|
+
const stack: DFSStackItem<NODE>[] = [{ opt: DFSOperation.VISIT, node: startNode }];
|
|
1818
1832
|
|
|
1819
1833
|
const pushLeft = (cur: DFSStackItem<NODE>) => {
|
|
1820
1834
|
if (shouldVisitLeft(cur.node)) stack.push({ opt: DFSOperation.VISIT, node: cur.node?.left });
|
|
@@ -1876,8 +1890,8 @@ export class BinaryTree<
|
|
|
1876
1890
|
if (!node) return;
|
|
1877
1891
|
|
|
1878
1892
|
if (this.iterationType === 'ITERATIVE') {
|
|
1879
|
-
const stack:
|
|
1880
|
-
let current:
|
|
1893
|
+
const stack: OptNodeOrNull<NODE>[] = [];
|
|
1894
|
+
let current: OptNodeOrNull<NODE> = node;
|
|
1881
1895
|
|
|
1882
1896
|
while (current || stack.length > 0) {
|
|
1883
1897
|
while (this.isRealNode(current)) {
|
|
@@ -1888,7 +1902,8 @@ export class BinaryTree<
|
|
|
1888
1902
|
current = stack.pop();
|
|
1889
1903
|
|
|
1890
1904
|
if (this.isRealNode(current)) {
|
|
1891
|
-
yield [current.key, current.
|
|
1905
|
+
if (this._isMapMode) yield [current.key, this._store.get(current.key)];
|
|
1906
|
+
else yield [current.key, current.value];
|
|
1892
1907
|
current = current.right;
|
|
1893
1908
|
}
|
|
1894
1909
|
}
|
|
@@ -1896,7 +1911,8 @@ export class BinaryTree<
|
|
|
1896
1911
|
if (node.left && this.isRealNode(node)) {
|
|
1897
1912
|
yield* this[Symbol.iterator](node.left);
|
|
1898
1913
|
}
|
|
1899
|
-
yield [node.key, node.
|
|
1914
|
+
if (this._isMapMode) yield [node.key, this._store.get(node.key)];
|
|
1915
|
+
else yield [node.key, node.value];
|
|
1900
1916
|
if (node.right && this.isRealNode(node)) {
|
|
1901
1917
|
yield* this[Symbol.iterator](node.right);
|
|
1902
1918
|
}
|
|
@@ -1918,7 +1934,7 @@ export class BinaryTree<
|
|
|
1918
1934
|
* information about how to display a node in a binary tree. The `NodeDisplayLayout` consists of four
|
|
1919
1935
|
* elements:
|
|
1920
1936
|
*/
|
|
1921
|
-
protected _displayAux(node:
|
|
1937
|
+
protected _displayAux(node: OptNodeOrNull<NODE>, options: BinaryTreePrintOptions): NodeDisplayLayout {
|
|
1922
1938
|
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
1923
1939
|
const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];
|
|
1924
1940
|
|
|
@@ -1986,27 +2002,24 @@ export class BinaryTree<
|
|
|
1986
2002
|
}
|
|
1987
2003
|
}
|
|
1988
2004
|
|
|
1989
|
-
protected
|
|
2005
|
+
protected _DEFAULT_NODE_CALLBACK = (node: OptNodeOrNull<NODE>) => (node ? node.key : undefined);
|
|
1990
2006
|
|
|
1991
2007
|
/**
|
|
1992
2008
|
* Time Complexity: O(1)
|
|
1993
2009
|
* Space Complexity: O(1)
|
|
1994
2010
|
*
|
|
1995
2011
|
* The _swapProperties function swaps key and value properties between two nodes in a binary tree.
|
|
1996
|
-
* @param {
|
|
1997
|
-
* `_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
|
|
1998
2014
|
* properties, or it can be of type R.
|
|
1999
|
-
* @param {
|
|
2015
|
+
* @param {BTNRep<K, V, NODE> | R} destNode - The `destNode` parameter in the
|
|
2000
2016
|
* `_swapProperties` method represents the node or entry where the properties will be swapped with
|
|
2001
|
-
* 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
|
|
2002
2018
|
* both `srcNode
|
|
2003
2019
|
* @returns The `_swapProperties` method returns either the `destNode` with its key and value swapped
|
|
2004
2020
|
* with the `srcNode`, or `undefined` if either `srcNode` or `destNode` is falsy.
|
|
2005
2021
|
*/
|
|
2006
|
-
protected _swapProperties(
|
|
2007
|
-
srcNode: BTNKeyOrNodeOrEntry<K, V, NODE> | R,
|
|
2008
|
-
destNode: BTNKeyOrNodeOrEntry<K, V, NODE> | R
|
|
2009
|
-
): NODE | undefined {
|
|
2022
|
+
protected _swapProperties(srcNode: BTNRep<K, V, NODE> | R, destNode: BTNRep<K, V, NODE> | R): NODE | undefined {
|
|
2010
2023
|
srcNode = this.ensureNode(srcNode);
|
|
2011
2024
|
destNode = this.ensureNode(destNode);
|
|
2012
2025
|
|
|
@@ -2016,10 +2029,10 @@ export class BinaryTree<
|
|
|
2016
2029
|
|
|
2017
2030
|
if (tempNode) {
|
|
2018
2031
|
destNode.key = srcNode.key;
|
|
2019
|
-
destNode.value = srcNode.value;
|
|
2032
|
+
if (!this._isMapMode) destNode.value = srcNode.value;
|
|
2020
2033
|
|
|
2021
2034
|
srcNode.key = tempNode.key;
|
|
2022
|
-
srcNode.value = tempNode.value;
|
|
2035
|
+
if (!this._isMapMode) srcNode.value = tempNode.value;
|
|
2023
2036
|
}
|
|
2024
2037
|
|
|
2025
2038
|
return destNode;
|
|
@@ -2065,10 +2078,10 @@ export class BinaryTree<
|
|
|
2065
2078
|
*
|
|
2066
2079
|
* The function _setRoot sets the root node of a data structure while updating the parent reference
|
|
2067
2080
|
* of the previous root node.
|
|
2068
|
-
* @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
|
|
2069
2082
|
* it can either be an optional `NODE` type or `null`.
|
|
2070
2083
|
*/
|
|
2071
|
-
protected _setRoot(v:
|
|
2084
|
+
protected _setRoot(v: OptNodeOrNull<NODE>) {
|
|
2072
2085
|
if (v) {
|
|
2073
2086
|
v.parent = undefined;
|
|
2074
2087
|
}
|
|
@@ -2081,49 +2094,116 @@ export class BinaryTree<
|
|
|
2081
2094
|
*
|
|
2082
2095
|
* The function `_ensurePredicate` in TypeScript ensures that the input is converted into a valid
|
|
2083
2096
|
* predicate function for a binary tree node.
|
|
2084
|
-
* @param {
|
|
2097
|
+
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate - The
|
|
2085
2098
|
* `_ensurePredicate` method in the provided code snippet is responsible for ensuring that the input
|
|
2086
|
-
* parameter `
|
|
2099
|
+
* parameter `keyNodeEntryRawOrPredicate` is transformed into a valid predicate function that can be
|
|
2087
2100
|
* used for filtering nodes in a binary tree.
|
|
2088
|
-
* @returns A
|
|
2101
|
+
* @returns A NodePredicate<NODE> function is being returned.
|
|
2089
2102
|
*/
|
|
2090
2103
|
protected _ensurePredicate(
|
|
2091
|
-
|
|
2092
|
-
):
|
|
2093
|
-
if (
|
|
2104
|
+
keyNodeEntryRawOrPredicate: BTNRep<K, V, NODE> | R | NodePredicate<NODE>
|
|
2105
|
+
): NodePredicate<NODE> {
|
|
2106
|
+
if (keyNodeEntryRawOrPredicate === null || keyNodeEntryRawOrPredicate === undefined)
|
|
2094
2107
|
return (node: NODE) => (node ? false : false);
|
|
2095
2108
|
|
|
2096
|
-
if (this.
|
|
2109
|
+
if (this._isPredicate(keyNodeEntryRawOrPredicate)) return keyNodeEntryRawOrPredicate;
|
|
2097
2110
|
|
|
2098
|
-
if (this.isRealNode(
|
|
2111
|
+
if (this.isRealNode(keyNodeEntryRawOrPredicate)) return (node: NODE) => node === keyNodeEntryRawOrPredicate;
|
|
2099
2112
|
|
|
2100
|
-
if (this.isEntry(
|
|
2101
|
-
const [key] =
|
|
2113
|
+
if (this.isEntry(keyNodeEntryRawOrPredicate)) {
|
|
2114
|
+
const [key] = keyNodeEntryRawOrPredicate;
|
|
2102
2115
|
return (node: NODE) => node.key === key;
|
|
2103
2116
|
}
|
|
2104
2117
|
|
|
2105
|
-
if (this.isKey(
|
|
2118
|
+
if (this.isKey(keyNodeEntryRawOrPredicate)) return (node: NODE) => node.key === keyNodeEntryRawOrPredicate;
|
|
2106
2119
|
|
|
2107
2120
|
if (this._toEntryFn) {
|
|
2108
|
-
const [key] = this._toEntryFn(
|
|
2121
|
+
const [key] = this._toEntryFn(keyNodeEntryRawOrPredicate);
|
|
2109
2122
|
return (node: NODE) => node.key === key;
|
|
2110
2123
|
}
|
|
2111
|
-
return (node: NODE) => node.key ===
|
|
2124
|
+
return (node: NODE) => node.key === keyNodeEntryRawOrPredicate;
|
|
2112
2125
|
}
|
|
2113
2126
|
|
|
2114
2127
|
/**
|
|
2115
2128
|
* Time Complexity: O(1)
|
|
2116
2129
|
* Space Complexity: O(1)
|
|
2117
2130
|
*
|
|
2118
|
-
* The function `
|
|
2131
|
+
* The function `_isPredicate` checks if a given parameter is a function.
|
|
2119
2132
|
* @param {any} p - The parameter `p` is a variable of type `any`, which means it can hold any type
|
|
2120
|
-
* of value. In this context, the function `
|
|
2121
|
-
* 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>`.
|
|
2122
2135
|
* @returns The function is checking if the input `p` is a function and returning a boolean value
|
|
2123
2136
|
* based on that check. If `p` is a function, it will return `true`, indicating that `p` is a
|
|
2124
2137
|
* predicate function for a binary tree node. If `p` is not a function, it will return `false`.
|
|
2125
2138
|
*/
|
|
2126
|
-
protected
|
|
2139
|
+
protected _isPredicate(p: any): p is NodePredicate<NODE> {
|
|
2127
2140
|
return typeof p === 'function';
|
|
2128
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
|
+
}
|
|
2129
2209
|
}
|