deque-typed 2.0.5 → 2.1.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/base/iterable-element-base.d.ts +186 -83
- package/dist/data-structures/base/iterable-element-base.js +149 -107
- package/dist/data-structures/base/iterable-entry-base.d.ts +95 -119
- package/dist/data-structures/base/iterable-entry-base.js +59 -116
- package/dist/data-structures/base/linear-base.d.ts +250 -192
- package/dist/data-structures/base/linear-base.js +137 -274
- package/dist/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
- package/dist/data-structures/binary-tree/avl-tree-counter.js +171 -205
- package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
- package/dist/data-structures/binary-tree/avl-tree-multi-map.js +135 -87
- package/dist/data-structures/binary-tree/avl-tree.d.ts +138 -149
- package/dist/data-structures/binary-tree/avl-tree.js +208 -195
- package/dist/data-structures/binary-tree/binary-tree.d.ts +476 -632
- package/dist/data-structures/binary-tree/binary-tree.js +602 -873
- package/dist/data-structures/binary-tree/bst.d.ts +258 -306
- package/dist/data-structures/binary-tree/bst.js +505 -481
- package/dist/data-structures/binary-tree/red-black-tree.d.ts +107 -179
- package/dist/data-structures/binary-tree/red-black-tree.js +114 -209
- package/dist/data-structures/binary-tree/tree-counter.d.ts +132 -154
- package/dist/data-structures/binary-tree/tree-counter.js +172 -203
- package/dist/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
- package/dist/data-structures/binary-tree/tree-multi-map.js +105 -85
- package/dist/data-structures/graph/abstract-graph.d.ts +238 -233
- package/dist/data-structures/graph/abstract-graph.js +267 -237
- package/dist/data-structures/graph/directed-graph.d.ts +108 -224
- package/dist/data-structures/graph/directed-graph.js +146 -233
- package/dist/data-structures/graph/map-graph.d.ts +49 -55
- package/dist/data-structures/graph/map-graph.js +56 -59
- package/dist/data-structures/graph/undirected-graph.d.ts +103 -146
- package/dist/data-structures/graph/undirected-graph.js +129 -149
- package/dist/data-structures/hash/hash-map.d.ts +164 -338
- package/dist/data-structures/hash/hash-map.js +270 -457
- package/dist/data-structures/heap/heap.d.ts +214 -289
- package/dist/data-structures/heap/heap.js +340 -349
- package/dist/data-structures/heap/max-heap.d.ts +11 -47
- package/dist/data-structures/heap/max-heap.js +11 -66
- package/dist/data-structures/heap/min-heap.d.ts +12 -47
- package/dist/data-structures/heap/min-heap.js +11 -66
- package/dist/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
- package/dist/data-structures/linked-list/doubly-linked-list.js +368 -494
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +261 -310
- package/dist/data-structures/linked-list/singly-linked-list.js +447 -466
- package/dist/data-structures/linked-list/skip-linked-list.d.ts +0 -107
- package/dist/data-structures/linked-list/skip-linked-list.js +0 -100
- package/dist/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
- package/dist/data-structures/priority-queue/max-priority-queue.js +11 -78
- package/dist/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
- package/dist/data-structures/priority-queue/min-priority-queue.js +10 -79
- package/dist/data-structures/priority-queue/priority-queue.d.ts +2 -61
- package/dist/data-structures/priority-queue/priority-queue.js +8 -83
- package/dist/data-structures/queue/deque.d.ts +227 -254
- package/dist/data-structures/queue/deque.js +309 -348
- package/dist/data-structures/queue/queue.d.ts +180 -201
- package/dist/data-structures/queue/queue.js +265 -248
- package/dist/data-structures/stack/stack.d.ts +124 -102
- package/dist/data-structures/stack/stack.js +181 -125
- package/dist/data-structures/trie/trie.d.ts +164 -165
- package/dist/data-structures/trie/trie.js +189 -172
- package/dist/interfaces/binary-tree.d.ts +56 -6
- package/dist/interfaces/graph.d.ts +16 -0
- package/dist/types/data-structures/base/base.d.ts +1 -1
- package/dist/types/data-structures/graph/abstract-graph.d.ts +4 -0
- package/dist/types/utils/utils.d.ts +1 -0
- package/dist/utils/utils.d.ts +1 -1
- package/dist/utils/utils.js +2 -1
- package/package.json +2 -2
- package/src/data-structures/base/iterable-element-base.ts +238 -115
- package/src/data-structures/base/iterable-entry-base.ts +96 -120
- package/src/data-structures/base/linear-base.ts +271 -277
- package/src/data-structures/binary-tree/avl-tree-counter.ts +196 -217
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +188 -102
- package/src/data-structures/binary-tree/avl-tree.ts +237 -206
- package/src/data-structures/binary-tree/binary-tree.ts +665 -896
- package/src/data-structures/binary-tree/bst.ts +565 -572
- package/src/data-structures/binary-tree/red-black-tree.ts +157 -223
- package/src/data-structures/binary-tree/tree-counter.ts +195 -219
- package/src/data-structures/binary-tree/tree-multi-map.ts +127 -98
- package/src/data-structures/graph/abstract-graph.ts +339 -264
- package/src/data-structures/graph/directed-graph.ts +146 -236
- package/src/data-structures/graph/map-graph.ts +63 -60
- package/src/data-structures/graph/undirected-graph.ts +129 -152
- package/src/data-structures/hash/hash-map.ts +274 -496
- package/src/data-structures/heap/heap.ts +389 -402
- package/src/data-structures/heap/max-heap.ts +12 -76
- package/src/data-structures/heap/min-heap.ts +13 -76
- package/src/data-structures/linked-list/doubly-linked-list.ts +426 -530
- package/src/data-structures/linked-list/singly-linked-list.ts +495 -517
- package/src/data-structures/linked-list/skip-linked-list.ts +1 -108
- package/src/data-structures/priority-queue/max-priority-queue.ts +12 -87
- package/src/data-structures/priority-queue/min-priority-queue.ts +11 -88
- package/src/data-structures/priority-queue/priority-queue.ts +3 -92
- package/src/data-structures/queue/deque.ts +381 -357
- package/src/data-structures/queue/queue.ts +310 -264
- package/src/data-structures/stack/stack.ts +217 -131
- package/src/data-structures/trie/trie.ts +240 -175
- package/src/interfaces/binary-tree.ts +240 -6
- package/src/interfaces/graph.ts +37 -0
- package/src/types/data-structures/base/base.ts +5 -5
- package/src/types/data-structures/graph/abstract-graph.ts +5 -0
- package/src/types/utils/utils.ts +2 -0
- package/src/utils/utils.ts +9 -14
|
@@ -13,18 +13,16 @@ const queue_1 = require("../queue");
|
|
|
13
13
|
const base_1 = require("../base");
|
|
14
14
|
const common_1 = require("../../common");
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
* @template V - The type of
|
|
18
|
-
* @template BinaryTreeNode<K, V> - The type of the family relationship in the binary tree.
|
|
16
|
+
* @template K - The type of the key.
|
|
17
|
+
* @template V - The type of the value.
|
|
19
18
|
*/
|
|
20
19
|
class BinaryTreeNode {
|
|
21
20
|
/**
|
|
22
|
-
*
|
|
23
|
-
* @
|
|
24
|
-
*
|
|
25
|
-
* @param
|
|
26
|
-
*
|
|
27
|
-
* default to `undefined`.
|
|
21
|
+
* Creates an instance of BinaryTreeNode.
|
|
22
|
+
* @remarks Time O(1), Space O(1)
|
|
23
|
+
*
|
|
24
|
+
* @param key - The key of the node.
|
|
25
|
+
* @param [value] - The value associated with the key.
|
|
28
26
|
*/
|
|
29
27
|
constructor(key, value) {
|
|
30
28
|
this.parent = undefined;
|
|
@@ -36,42 +34,108 @@ class BinaryTreeNode {
|
|
|
36
34
|
this.key = key;
|
|
37
35
|
this.value = value;
|
|
38
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Gets the left child of the node.
|
|
39
|
+
* @remarks Time O(1), Space O(1)
|
|
40
|
+
*
|
|
41
|
+
* @returns The left child.
|
|
42
|
+
*/
|
|
39
43
|
get left() {
|
|
40
44
|
return this._left;
|
|
41
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Sets the left child of the node and updates its parent reference.
|
|
48
|
+
* @remarks Time O(1), Space O(1)
|
|
49
|
+
*
|
|
50
|
+
* @param v - The node to set as the left child.
|
|
51
|
+
*/
|
|
42
52
|
set left(v) {
|
|
43
53
|
if (v) {
|
|
44
54
|
v.parent = this;
|
|
45
55
|
}
|
|
46
56
|
this._left = v;
|
|
47
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Gets the right child of the node.
|
|
60
|
+
* @remarks Time O(1), Space O(1)
|
|
61
|
+
*
|
|
62
|
+
* @returns The right child.
|
|
63
|
+
*/
|
|
48
64
|
get right() {
|
|
49
65
|
return this._right;
|
|
50
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Sets the right child of the node and updates its parent reference.
|
|
69
|
+
* @remarks Time O(1), Space O(1)
|
|
70
|
+
*
|
|
71
|
+
* @param v - The node to set as the right child.
|
|
72
|
+
*/
|
|
51
73
|
set right(v) {
|
|
52
74
|
if (v) {
|
|
53
75
|
v.parent = this;
|
|
54
76
|
}
|
|
55
77
|
this._right = v;
|
|
56
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Gets the height of the node (used in self-balancing trees).
|
|
81
|
+
* @remarks Time O(1), Space O(1)
|
|
82
|
+
*
|
|
83
|
+
* @returns The height.
|
|
84
|
+
*/
|
|
57
85
|
get height() {
|
|
58
86
|
return this._height;
|
|
59
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Sets the height of the node.
|
|
90
|
+
* @remarks Time O(1), Space O(1)
|
|
91
|
+
*
|
|
92
|
+
* @param value - The new height.
|
|
93
|
+
*/
|
|
60
94
|
set height(value) {
|
|
61
95
|
this._height = value;
|
|
62
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Gets the color of the node (used in Red-Black trees).
|
|
99
|
+
* @remarks Time O(1), Space O(1)
|
|
100
|
+
*
|
|
101
|
+
* @returns The node's color.
|
|
102
|
+
*/
|
|
63
103
|
get color() {
|
|
64
104
|
return this._color;
|
|
65
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Sets the color of the node.
|
|
108
|
+
* @remarks Time O(1), Space O(1)
|
|
109
|
+
*
|
|
110
|
+
* @param value - The new color.
|
|
111
|
+
*/
|
|
66
112
|
set color(value) {
|
|
67
113
|
this._color = value;
|
|
68
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Gets the count of nodes in the subtree rooted at this node (used in order-statistic trees).
|
|
117
|
+
* @remarks Time O(1), Space O(1)
|
|
118
|
+
*
|
|
119
|
+
* @returns The subtree node count.
|
|
120
|
+
*/
|
|
69
121
|
get count() {
|
|
70
122
|
return this._count;
|
|
71
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* Sets the count of nodes in the subtree.
|
|
126
|
+
* @remarks Time O(1), Space O(1)
|
|
127
|
+
*
|
|
128
|
+
* @param value - The new count.
|
|
129
|
+
*/
|
|
72
130
|
set count(value) {
|
|
73
131
|
this._count = value;
|
|
74
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Gets the position of the node relative to its parent.
|
|
135
|
+
* @remarks Time O(1), Space O(1)
|
|
136
|
+
*
|
|
137
|
+
* @returns The family position (e.g., 'ROOT', 'LEFT', 'RIGHT').
|
|
138
|
+
*/
|
|
75
139
|
get familyPosition() {
|
|
76
140
|
if (!this.parent) {
|
|
77
141
|
return this.left || this.right ? 'ROOT' : 'ISOLATED';
|
|
@@ -87,6 +151,15 @@ class BinaryTreeNode {
|
|
|
87
151
|
}
|
|
88
152
|
exports.BinaryTreeNode = BinaryTreeNode;
|
|
89
153
|
/**
|
|
154
|
+
* A general Binary Tree implementation.
|
|
155
|
+
*
|
|
156
|
+
* @remarks
|
|
157
|
+
* This class implements a basic Binary Tree, not a Binary Search Tree.
|
|
158
|
+
* The `add` operation inserts nodes level-by-level (BFS) into the first available slot.
|
|
159
|
+
*
|
|
160
|
+
* @template K - The type of the key.
|
|
161
|
+
* @template V - The type of the value.
|
|
162
|
+
* @template R - The type of the raw data object (if using `toEntryFn`).
|
|
90
163
|
* 1. Two Children Maximum: Each node has at most two children.
|
|
91
164
|
* 2. Left and Right Children: Nodes have distinct left and right children.
|
|
92
165
|
* 3. Depth and Height: Depth is the number of edges from the root to a node; height is the maximum depth in the tree.
|
|
@@ -157,13 +230,11 @@ exports.BinaryTreeNode = BinaryTreeNode;
|
|
|
157
230
|
*/
|
|
158
231
|
class BinaryTree extends base_1.IterableEntryBase {
|
|
159
232
|
/**
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
* @param [options] - The `options` parameter in the constructor is an optional object that can
|
|
166
|
-
* contain the following properties:
|
|
233
|
+
* Creates an instance of BinaryTree.
|
|
234
|
+
* @remarks Time O(N * M), where N is the number of items in `keysNodesEntriesOrRaws` and M is the tree size at insertion time (due to O(M) `add` operation). Space O(N) for storing the nodes.
|
|
235
|
+
*
|
|
236
|
+
* @param [keysNodesEntriesOrRaws=[]] - An iterable of items to add.
|
|
237
|
+
* @param [options] - Configuration options for the tree.
|
|
167
238
|
*/
|
|
168
239
|
constructor(keysNodesEntriesOrRaws = [], options) {
|
|
169
240
|
super();
|
|
@@ -173,6 +244,13 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
173
244
|
this._store = new Map();
|
|
174
245
|
this._size = 0;
|
|
175
246
|
this._NIL = new BinaryTreeNode(NaN);
|
|
247
|
+
/**
|
|
248
|
+
* (Protected) Default callback function, returns the node's key.
|
|
249
|
+
* @remarks Time O(1)
|
|
250
|
+
*
|
|
251
|
+
* @param node - The node.
|
|
252
|
+
* @returns The node's key or undefined.
|
|
253
|
+
*/
|
|
176
254
|
this._DEFAULT_NODE_CALLBACK = (node) => (node ? node.key : undefined);
|
|
177
255
|
if (options) {
|
|
178
256
|
const { iterationType, toEntryFn, isMapMode, isDuplicate } = options;
|
|
@@ -190,70 +268,97 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
190
268
|
if (keysNodesEntriesOrRaws)
|
|
191
269
|
this.addMany(keysNodesEntriesOrRaws);
|
|
192
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* Gets whether the tree is in Map mode.
|
|
273
|
+
* @remarks In Map mode (default), values are stored in an external Map, and nodes only hold keys. If false, values are stored directly on the nodes. Time O(1)
|
|
274
|
+
*
|
|
275
|
+
* @returns True if in Map mode, false otherwise.
|
|
276
|
+
*/
|
|
193
277
|
get isMapMode() {
|
|
194
278
|
return this._isMapMode;
|
|
195
279
|
}
|
|
280
|
+
/**
|
|
281
|
+
* Gets whether the tree allows duplicate keys.
|
|
282
|
+
* @remarks Time O(1)
|
|
283
|
+
*
|
|
284
|
+
* @returns True if duplicates are allowed, false otherwise.
|
|
285
|
+
*/
|
|
196
286
|
get isDuplicate() {
|
|
197
287
|
return this._isDuplicate;
|
|
198
288
|
}
|
|
289
|
+
/**
|
|
290
|
+
* Gets the external value store (used in Map mode).
|
|
291
|
+
* @remarks Time O(1)
|
|
292
|
+
*
|
|
293
|
+
* @returns The map storing key-value pairs.
|
|
294
|
+
*/
|
|
199
295
|
get store() {
|
|
200
296
|
return this._store;
|
|
201
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* Gets the root node of the tree.
|
|
300
|
+
* @remarks Time O(1)
|
|
301
|
+
*
|
|
302
|
+
* @returns The root node.
|
|
303
|
+
*/
|
|
202
304
|
get root() {
|
|
203
305
|
return this._root;
|
|
204
306
|
}
|
|
307
|
+
/**
|
|
308
|
+
* Gets the number of nodes in the tree.
|
|
309
|
+
* @remarks Time O(1)
|
|
310
|
+
*
|
|
311
|
+
* @returns The size of the tree.
|
|
312
|
+
*/
|
|
205
313
|
get size() {
|
|
206
314
|
return this._size;
|
|
207
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* Gets the sentinel NIL node (used in self-balancing trees like Red-Black Tree).
|
|
318
|
+
* @remarks Time O(1)
|
|
319
|
+
*
|
|
320
|
+
* @returns The NIL node.
|
|
321
|
+
*/
|
|
208
322
|
get NIL() {
|
|
209
323
|
return this._NIL;
|
|
210
324
|
}
|
|
325
|
+
/**
|
|
326
|
+
* Gets the function used to convert raw data objects (R) into [key, value] entries.
|
|
327
|
+
* @remarks Time O(1)
|
|
328
|
+
*
|
|
329
|
+
* @returns The conversion function.
|
|
330
|
+
*/
|
|
211
331
|
get toEntryFn() {
|
|
212
332
|
return this._toEntryFn;
|
|
213
333
|
}
|
|
214
334
|
/**
|
|
215
|
-
*
|
|
216
|
-
*
|
|
335
|
+
* (Protected) Creates a new node.
|
|
336
|
+
* @remarks Time O(1), Space O(1)
|
|
217
337
|
*
|
|
218
|
-
* The
|
|
219
|
-
* @param
|
|
220
|
-
* @
|
|
221
|
-
* not required to be provided when calling the function. If a `value` is provided, it should be of
|
|
222
|
-
* type `V`, which is the type of the value associated with the node.
|
|
223
|
-
* @returns A new BinaryTreeNode instance with the provided key and value is being returned, casted
|
|
224
|
-
* as BinaryTreeNode<K, V>.
|
|
338
|
+
* @param key - The key for the new node.
|
|
339
|
+
* @param [value] - The value for the new node (used if not in Map mode).
|
|
340
|
+
* @returns The newly created node.
|
|
225
341
|
*/
|
|
226
|
-
|
|
342
|
+
_createNode(key, value) {
|
|
227
343
|
return new BinaryTreeNode(key, this._isMapMode ? undefined : value);
|
|
228
344
|
}
|
|
229
345
|
/**
|
|
230
|
-
*
|
|
231
|
-
*
|
|
346
|
+
* Creates a new, empty tree of the same type and configuration.
|
|
347
|
+
* @remarks Time O(1) (excluding options cloning), Space O(1)
|
|
232
348
|
*
|
|
233
|
-
*
|
|
234
|
-
* @
|
|
235
|
-
* that allows you to provide partial configuration options for creating a binary tree. It is of type
|
|
236
|
-
* `Partial<BinaryTreeOptions<K, V, R>>`, which means you can pass in an object containing a subset
|
|
237
|
-
* of properties
|
|
238
|
-
* @returns A new instance of a binary tree with the specified options is being returned.
|
|
349
|
+
* @param [options] - Optional overrides for the new tree's options.
|
|
350
|
+
* @returns A new, empty tree instance.
|
|
239
351
|
*/
|
|
240
352
|
createTree(options) {
|
|
241
|
-
return
|
|
353
|
+
return this._createInstance(options);
|
|
242
354
|
}
|
|
243
355
|
/**
|
|
244
|
-
*
|
|
245
|
-
* Space
|
|
356
|
+
* Ensures the input is a node. If it's a key or entry, it searches for the node.
|
|
357
|
+
* @remarks Time O(1) if a node is passed. O(N) if a key or entry is passed (due to `getNode` performing a full search). Space O(1) if iterative search, O(H) if recursive (where H is height, O(N) worst-case).
|
|
246
358
|
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
* @
|
|
250
|
-
* parameter in the `ensureNode` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It
|
|
251
|
-
* is used to determine whether the input is a key, node, entry, or raw data. The
|
|
252
|
-
* @param {IterationType} iterationType - The `iterationType` parameter in the `ensureNode` function
|
|
253
|
-
* is used to specify the type of iteration to be performed. It has a default value of
|
|
254
|
-
* `this.iterationType` if not explicitly provided.
|
|
255
|
-
* @returns The `ensureNode` function returns either a node, `null`, or `undefined` based on the
|
|
256
|
-
* conditions specified in the code snippet.
|
|
359
|
+
* @param keyNodeOrEntry - The item to resolve to a node.
|
|
360
|
+
* @param [iterationType=this.iterationType] - The traversal method to use if searching.
|
|
361
|
+
* @returns The resolved node, or null/undefined if not found or input is null/undefined.
|
|
257
362
|
*/
|
|
258
363
|
ensureNode(keyNodeOrEntry, iterationType = this.iterationType) {
|
|
259
364
|
if (keyNodeOrEntry === null)
|
|
@@ -275,47 +380,31 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
275
380
|
return this.getNode(keyNodeOrEntry, this._root, iterationType);
|
|
276
381
|
}
|
|
277
382
|
/**
|
|
278
|
-
*
|
|
279
|
-
*
|
|
383
|
+
* Checks if the given item is a `BinaryTreeNode` instance.
|
|
384
|
+
* @remarks Time O(1), Space O(1)
|
|
280
385
|
*
|
|
281
|
-
*
|
|
282
|
-
* @
|
|
283
|
-
* `keyNodeOrEntry` can be either a key, a node, an entry, or raw data. The function is
|
|
284
|
-
* checking if the input is an instance of a `BinaryTreeNode` and returning a boolean value
|
|
285
|
-
* accordingly.
|
|
286
|
-
* @returns The function `isNode` is checking if the input `keyNodeOrEntry` is an instance of
|
|
287
|
-
* `BinaryTreeNode`. If it is, the function returns `true`, indicating that the input is a node. If
|
|
288
|
-
* it is not an instance of `BinaryTreeNode`, the function returns `false`, indicating that the input
|
|
289
|
-
* is not a node.
|
|
386
|
+
* @param keyNodeOrEntry - The item to check.
|
|
387
|
+
* @returns True if it's a node, false otherwise.
|
|
290
388
|
*/
|
|
291
389
|
isNode(keyNodeOrEntry) {
|
|
292
390
|
return keyNodeOrEntry instanceof BinaryTreeNode;
|
|
293
391
|
}
|
|
294
392
|
/**
|
|
295
|
-
*
|
|
296
|
-
*
|
|
393
|
+
* Checks if the given item is a raw data object (R) that needs conversion via `toEntryFn`.
|
|
394
|
+
* @remarks Time O(1), Space O(1)
|
|
297
395
|
*
|
|
298
|
-
*
|
|
299
|
-
* @
|
|
300
|
-
* @returns The function `isRaw` is checking if the `keyNodeEntryOrRaw` parameter is of type `R` by
|
|
301
|
-
* checking if it is an object. If the parameter is an object, the function will return `true`,
|
|
302
|
-
* indicating that it is of type `R`.
|
|
396
|
+
* @param keyNodeEntryOrRaw - The item to check.
|
|
397
|
+
* @returns True if it's a raw object, false otherwise.
|
|
303
398
|
*/
|
|
304
399
|
isRaw(keyNodeEntryOrRaw) {
|
|
305
400
|
return this._toEntryFn !== undefined && typeof keyNodeEntryOrRaw === 'object';
|
|
306
401
|
}
|
|
307
402
|
/**
|
|
308
|
-
*
|
|
309
|
-
*
|
|
403
|
+
* Checks if the given item is a "real" node (i.e., not null, undefined, or NIL).
|
|
404
|
+
* @remarks Time O(1), Space O(1)
|
|
310
405
|
*
|
|
311
|
-
*
|
|
312
|
-
* @
|
|
313
|
-
* parameter in the `isRealNode` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`.
|
|
314
|
-
* The function checks if the input parameter is a `BinaryTreeNode<K, V>` type by verifying if it is not equal
|
|
315
|
-
* @returns The function `isRealNode` is checking if the input `keyNodeOrEntry` is a valid
|
|
316
|
-
* node by comparing it to `this._NIL`, `null`, and `undefined`. If the input is not one of these
|
|
317
|
-
* values, it then calls the `isNode` method to further determine if the input is a node. The
|
|
318
|
-
* function will return a boolean value indicating whether the
|
|
406
|
+
* @param keyNodeOrEntry - The item to check.
|
|
407
|
+
* @returns True if it's a real node, false otherwise.
|
|
319
408
|
*/
|
|
320
409
|
isRealNode(keyNodeOrEntry) {
|
|
321
410
|
if (keyNodeOrEntry === this._NIL || keyNodeOrEntry === null || keyNodeOrEntry === undefined)
|
|
@@ -323,97 +412,66 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
323
412
|
return this.isNode(keyNodeOrEntry);
|
|
324
413
|
}
|
|
325
414
|
/**
|
|
326
|
-
*
|
|
327
|
-
*
|
|
415
|
+
* Checks if the given item is either a "real" node or null.
|
|
416
|
+
* @remarks Time O(1), Space O(1)
|
|
328
417
|
*
|
|
329
|
-
*
|
|
330
|
-
* @
|
|
331
|
-
* `keyNodeOrEntry` in the `isRealNodeOrNull` function can be of type `BTNRep<K,
|
|
332
|
-
* V, BinaryTreeNode<K, V>>` or `R`. It is a union type that can either be a key, a node, an entry, or
|
|
333
|
-
* @returns The function `isRealNodeOrNull` is returning a boolean value. It checks if the input
|
|
334
|
-
* `keyNodeOrEntry` is either `null` or a real node, and returns `true` if it is a node or
|
|
335
|
-
* `null`, and `false` otherwise.
|
|
418
|
+
* @param keyNodeOrEntry - The item to check.
|
|
419
|
+
* @returns True if it's a real node or null, false otherwise.
|
|
336
420
|
*/
|
|
337
421
|
isRealNodeOrNull(keyNodeOrEntry) {
|
|
338
422
|
return keyNodeOrEntry === null || this.isRealNode(keyNodeOrEntry);
|
|
339
423
|
}
|
|
340
424
|
/**
|
|
341
|
-
*
|
|
342
|
-
*
|
|
425
|
+
* Checks if the given item is the sentinel NIL node.
|
|
426
|
+
* @remarks Time O(1), Space O(1)
|
|
343
427
|
*
|
|
344
|
-
*
|
|
345
|
-
* @
|
|
346
|
-
* BinaryTreeNode<K, V>>
|
|
347
|
-
* @returns The function is checking if the `keyNodeOrEntry` parameter is equal to the `_NIL`
|
|
348
|
-
* property of the current object and returning a boolean value based on that comparison.
|
|
428
|
+
* @param keyNodeOrEntry - The item to check.
|
|
429
|
+
* @returns True if it's the NIL node, false otherwise.
|
|
349
430
|
*/
|
|
350
431
|
isNIL(keyNodeOrEntry) {
|
|
351
432
|
return keyNodeOrEntry === this._NIL;
|
|
352
433
|
}
|
|
353
434
|
/**
|
|
354
|
-
*
|
|
355
|
-
*
|
|
435
|
+
* Checks if the given item is a `Range` object.
|
|
436
|
+
* @remarks Time O(1), Space O(1)
|
|
356
437
|
*
|
|
357
|
-
*
|
|
358
|
-
* @
|
|
359
|
-
* - The `keyNodeEntryOrPredicate` parameter in the `isRange` function can be
|
|
360
|
-
* of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `, `NodePredicate<BinaryTreeNode<K, V>>`, or
|
|
361
|
-
* `Range<K>`. The function checks if the `keyNodeEntry
|
|
362
|
-
* @returns The `isRange` function is checking if the `keyNodeEntryOrPredicate` parameter is an
|
|
363
|
-
* instance of the `Range` class. If it is an instance of `Range`, the function will return `true`,
|
|
364
|
-
* indicating that the parameter is a `Range<K>`. If it is not an instance of `Range`, the function
|
|
365
|
-
* will return `false`.
|
|
438
|
+
* @param keyNodeEntryOrPredicate - The item to check.
|
|
439
|
+
* @returns True if it's a Range, false otherwise.
|
|
366
440
|
*/
|
|
367
441
|
isRange(keyNodeEntryOrPredicate) {
|
|
368
442
|
return keyNodeEntryOrPredicate instanceof common_1.Range;
|
|
369
443
|
}
|
|
370
444
|
/**
|
|
371
|
-
*
|
|
372
|
-
*
|
|
445
|
+
* Checks if a node is a leaf (has no real children).
|
|
446
|
+
* @remarks Time O(N) if a key/entry is passed (due to `ensureNode`). O(1) if a node is passed. Space O(1) or O(H) (from `ensureNode`).
|
|
373
447
|
*
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
|
|
377
|
-
* `keyNodeOrEntry` can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It represents a
|
|
378
|
-
* key, node, entry, or raw data in a binary tree structure. The function `isLeaf` checks whether the
|
|
379
|
-
* provided
|
|
380
|
-
* @returns The function `isLeaf` returns a boolean value indicating whether the input
|
|
381
|
-
* `keyNodeOrEntry` is a leaf node in a binary tree.
|
|
448
|
+
* @param keyNodeOrEntry - The node to check.
|
|
449
|
+
* @returns True if the node is a leaf, false otherwise.
|
|
382
450
|
*/
|
|
383
451
|
isLeaf(keyNodeOrEntry) {
|
|
384
452
|
keyNodeOrEntry = this.ensureNode(keyNodeOrEntry);
|
|
385
453
|
if (keyNodeOrEntry === undefined)
|
|
386
454
|
return false;
|
|
387
455
|
if (keyNodeOrEntry === null)
|
|
388
|
-
return true;
|
|
456
|
+
return true; // A null spot is considered a leaf
|
|
389
457
|
return !this.isRealNode(keyNodeOrEntry.left) && !this.isRealNode(keyNodeOrEntry.right);
|
|
390
458
|
}
|
|
391
459
|
/**
|
|
392
|
-
*
|
|
393
|
-
*
|
|
460
|
+
* Checks if the given item is a [key, value] entry pair.
|
|
461
|
+
* @remarks Time O(1), Space O(1)
|
|
394
462
|
*
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`
|
|
398
|
-
* parameter in the `isEntry` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or type `R`.
|
|
399
|
-
* The function checks if the provided `keyNodeOrEntry` is of type `BTN
|
|
400
|
-
* @returns The `isEntry` function is checking if the `keyNodeOrEntry` parameter is an array
|
|
401
|
-
* with a length of 2. If it is, then it returns `true`, indicating that the parameter is of type
|
|
402
|
-
* `BTNEntry<K, V>`. If the condition is not met, it returns `false`.
|
|
463
|
+
* @param keyNodeOrEntry - The item to check.
|
|
464
|
+
* @returns True if it's an entry, false otherwise.
|
|
403
465
|
*/
|
|
404
466
|
isEntry(keyNodeOrEntry) {
|
|
405
467
|
return Array.isArray(keyNodeOrEntry) && keyNodeOrEntry.length === 2;
|
|
406
468
|
}
|
|
407
469
|
/**
|
|
408
|
-
*
|
|
409
|
-
*
|
|
470
|
+
* Checks if the given key is valid (comparable or null).
|
|
471
|
+
* @remarks Time O(1), Space O(1)
|
|
410
472
|
*
|
|
411
|
-
*
|
|
412
|
-
* @
|
|
413
|
-
* TypeScript.
|
|
414
|
-
* @returns The function `isValidKey` is checking if the `key` parameter is `null` or if it is comparable.
|
|
415
|
-
* If the `key` is `null`, the function returns `true`. Otherwise, it returns the result of the
|
|
416
|
-
* `isComparable` function, which is not provided in the code snippet.
|
|
473
|
+
* @param key - The key to validate.
|
|
474
|
+
* @returns True if the key is valid, false otherwise.
|
|
417
475
|
*/
|
|
418
476
|
isValidKey(key) {
|
|
419
477
|
if (key === null)
|
|
@@ -421,27 +479,17 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
421
479
|
return (0, utils_1.isComparable)(key);
|
|
422
480
|
}
|
|
423
481
|
/**
|
|
424
|
-
*
|
|
425
|
-
*
|
|
482
|
+
* Adds a new node to the tree.
|
|
483
|
+
* @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). This implementation adds the node at the first available position in a level-order (BFS) traversal. This is NOT a Binary Search Tree insertion. Time O(N), where N is the number of nodes. It must traverse level-by-level to find an empty slot. Space O(N) in the worst case for the BFS queue (e.g., a full last level).
|
|
426
484
|
*
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
* @
|
|
430
|
-
* seems to be for adding a new node to a binary tree structure. The `keyNodeOrEntry`
|
|
431
|
-
* parameter in the method can accept different types of values:
|
|
432
|
-
* @param {V} [value] - The `value` parameter in the `add` method represents the value associated
|
|
433
|
-
* with the key that you want to add to the binary tree. When adding a key-value pair to the binary
|
|
434
|
-
* tree, you provide the key and its corresponding value. The `add` method then creates a new node
|
|
435
|
-
* with this
|
|
436
|
-
* @returns The `add` method returns a boolean value. It returns `true` if the insertion of the new
|
|
437
|
-
* node was successful, and `false` if the insertion position could not be found or if a duplicate
|
|
438
|
-
* key was found and the node was replaced instead of inserted.
|
|
485
|
+
* @param keyNodeOrEntry - The key, node, or entry to add.
|
|
486
|
+
* @param [value] - The value, if providing just a key.
|
|
487
|
+
* @returns True if the addition was successful, false otherwise.
|
|
439
488
|
*/
|
|
440
489
|
add(keyNodeOrEntry, value) {
|
|
441
490
|
const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
442
491
|
if (newNode === undefined)
|
|
443
492
|
return false;
|
|
444
|
-
// If the tree is empty, directly set the new node as the root node
|
|
445
493
|
if (!this._root) {
|
|
446
494
|
this._setRoot(newNode);
|
|
447
495
|
if (this._isMapMode)
|
|
@@ -450,25 +498,22 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
450
498
|
return true;
|
|
451
499
|
}
|
|
452
500
|
const queue = new queue_1.Queue([this._root]);
|
|
453
|
-
let potentialParent;
|
|
501
|
+
let potentialParent;
|
|
454
502
|
while (queue.length > 0) {
|
|
455
503
|
const cur = queue.shift();
|
|
456
504
|
if (!cur)
|
|
457
505
|
continue;
|
|
458
506
|
if (!this._isDuplicate) {
|
|
459
|
-
// Check for duplicate keys when newNode is not null
|
|
460
507
|
if (newNode !== null && cur.key === newNode.key) {
|
|
461
508
|
this._replaceNode(cur, newNode);
|
|
462
509
|
if (this._isMapMode)
|
|
463
510
|
this._setValue(cur.key, newValue);
|
|
464
|
-
return true; //
|
|
511
|
+
return true; // Replaced existing node
|
|
465
512
|
}
|
|
466
513
|
}
|
|
467
|
-
// Record the first possible insertion location found
|
|
468
514
|
if (potentialParent === undefined && (cur.left === undefined || cur.right === undefined)) {
|
|
469
515
|
potentialParent = cur;
|
|
470
516
|
}
|
|
471
|
-
// Continue traversing the left and right subtrees
|
|
472
517
|
if (cur.left !== null) {
|
|
473
518
|
if (cur.left)
|
|
474
519
|
queue.push(cur.left);
|
|
@@ -478,7 +523,6 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
478
523
|
queue.push(cur.right);
|
|
479
524
|
}
|
|
480
525
|
}
|
|
481
|
-
// At the end of the traversal, if the insertion position is found, insert
|
|
482
526
|
if (potentialParent) {
|
|
483
527
|
if (potentialParent.left === undefined) {
|
|
484
528
|
potentialParent.left = newNode;
|
|
@@ -491,28 +535,17 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
491
535
|
this._size++;
|
|
492
536
|
return true;
|
|
493
537
|
}
|
|
494
|
-
return false; //
|
|
495
|
-
}
|
|
496
|
-
/**
|
|
497
|
-
*
|
|
498
|
-
* Space
|
|
499
|
-
*
|
|
500
|
-
*
|
|
501
|
-
*
|
|
502
|
-
* each
|
|
503
|
-
* @param keysNodesEntriesOrRaws - `keysNodesEntriesOrRaws` is an iterable that can contain a
|
|
504
|
-
* mix of keys, nodes, entries, or raw values. Each element in this iterable can be of type
|
|
505
|
-
* `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`.
|
|
506
|
-
* @param [values] - The `values` parameter in the `addMany` function is an optional parameter that
|
|
507
|
-
* accepts an iterable of values. These values correspond to the keys or nodes being added in the
|
|
508
|
-
* `keysNodesEntriesOrRaws` parameter. If provided, the function will iterate over the values and
|
|
509
|
-
* assign them
|
|
510
|
-
* @returns The `addMany` method returns an array of boolean values indicating whether each key,
|
|
511
|
-
* node, entry, or raw value was successfully added to the data structure. Each boolean value
|
|
512
|
-
* corresponds to the success of adding the corresponding key or value in the input iterable.
|
|
538
|
+
return false; // Should not happen if tree is not full?
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Adds multiple items to the tree.
|
|
542
|
+
* @remarks Time O(N * M), where N is the number of items to add and M is the size of the tree at insertion (due to O(M) `add` operation). Space O(M) (from `add`) + O(N) (for the `inserted` array).
|
|
543
|
+
*
|
|
544
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to add.
|
|
545
|
+
* @param [values] - An optional parallel iterable of values.
|
|
546
|
+
* @returns An array of booleans indicating the success of each individual `add` operation.
|
|
513
547
|
*/
|
|
514
548
|
addMany(keysNodesEntriesOrRaws, values) {
|
|
515
|
-
// TODO not sure addMany not be run multi times
|
|
516
549
|
const inserted = [];
|
|
517
550
|
let valuesIterator;
|
|
518
551
|
if (values) {
|
|
@@ -533,46 +566,31 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
533
566
|
return inserted;
|
|
534
567
|
}
|
|
535
568
|
/**
|
|
536
|
-
*
|
|
537
|
-
*
|
|
569
|
+
* Merges another tree into this one by adding all its nodes.
|
|
570
|
+
* @remarks Time O(N * M), same as `addMany`, where N is the size of `anotherTree` and M is the size of this tree. Space O(M) (from `add`).
|
|
538
571
|
*
|
|
539
|
-
*
|
|
540
|
-
* elements from the other tree.
|
|
541
|
-
* @param anotherTree - BinaryTree<K, V, R, MK, MV, MR>
|
|
572
|
+
* @param anotherTree - The tree to merge.
|
|
542
573
|
*/
|
|
543
574
|
merge(anotherTree) {
|
|
544
575
|
this.addMany(anotherTree, []);
|
|
545
576
|
}
|
|
546
577
|
/**
|
|
547
|
-
*
|
|
548
|
-
*
|
|
578
|
+
* Clears the tree and refills it with new items.
|
|
579
|
+
* @remarks Time O(N) (for `clear`) + O(N * M) (for `addMany`) = O(N * M). Space O(M) (from `addMany`).
|
|
549
580
|
*
|
|
550
|
-
*
|
|
551
|
-
*
|
|
552
|
-
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the `refill`
|
|
553
|
-
* method can accept an iterable containing a mix of `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` objects or `R`
|
|
554
|
-
* objects.
|
|
555
|
-
* @param [values] - The `values` parameter in the `refill` method is an optional parameter that
|
|
556
|
-
* accepts an iterable of values of type `V` or `undefined`.
|
|
581
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to add.
|
|
582
|
+
* @param [values] - An optional parallel iterable of values.
|
|
557
583
|
*/
|
|
558
584
|
refill(keysNodesEntriesOrRaws, values) {
|
|
559
585
|
this.clear();
|
|
560
586
|
this.addMany(keysNodesEntriesOrRaws, values);
|
|
561
587
|
}
|
|
562
588
|
/**
|
|
563
|
-
*
|
|
564
|
-
*
|
|
589
|
+
* Deletes a node from the tree.
|
|
590
|
+
* @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). This implementation finds the node, and if it has two children, swaps it with the rightmost node of its left subtree (in-order predecessor) before deleting. Time O(N) in the worst case. O(N) to find the node (`getNode`) and O(H) (which is O(N) worst-case) to find the rightmost node. Space O(1) (if `getNode` is iterative, which it is).
|
|
565
591
|
*
|
|
566
|
-
*
|
|
567
|
-
*
|
|
568
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry
|
|
569
|
-
* - The `delete` method you provided is used to delete a node from a binary tree based on the key,
|
|
570
|
-
* node, entry or raw data. The method returns an array of
|
|
571
|
-
* `BinaryTreeDeleteResult` objects containing information about the deleted node and whether
|
|
572
|
-
* balancing is needed.
|
|
573
|
-
* @returns The `delete` method returns an array of `BinaryTreeDeleteResult` objects. Each object in
|
|
574
|
-
* the array contains information about the node that was deleted (`deleted`) and the node that may
|
|
575
|
-
* need to be balanced (`needBalanced`).
|
|
592
|
+
* @param keyNodeOrEntry - The node to delete.
|
|
593
|
+
* @returns An array containing deletion results (for compatibility with self-balancing trees).
|
|
576
594
|
*/
|
|
577
595
|
delete(keyNodeOrEntry) {
|
|
578
596
|
const deletedResult = [];
|
|
@@ -585,14 +603,20 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
585
603
|
let needBalanced;
|
|
586
604
|
let orgCurrent = curr;
|
|
587
605
|
if (!curr.left && !curr.right && !parent) {
|
|
606
|
+
// Deleting the root with no children
|
|
588
607
|
this._setRoot(undefined);
|
|
589
608
|
}
|
|
590
609
|
else if (curr.left) {
|
|
610
|
+
// Node has a left child (or two children)
|
|
611
|
+
// Find the rightmost node in the left subtree
|
|
591
612
|
const leftSubTreeRightMost = this.getRightMost(node => node, curr.left);
|
|
592
613
|
if (leftSubTreeRightMost) {
|
|
593
614
|
const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
|
|
615
|
+
// Swap properties
|
|
594
616
|
orgCurrent = this._swapProperties(curr, leftSubTreeRightMost);
|
|
617
|
+
// `orgCurrent` is now the node to be physically deleted (which was the rightmost)
|
|
595
618
|
if (parentOfLeftSubTreeMax) {
|
|
619
|
+
// Unlink the rightmost node
|
|
596
620
|
if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost)
|
|
597
621
|
parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
|
|
598
622
|
else
|
|
@@ -602,6 +626,8 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
602
626
|
}
|
|
603
627
|
}
|
|
604
628
|
else if (parent) {
|
|
629
|
+
// Node has no left child, but has a parent
|
|
630
|
+
// Promote the right child (which could be null)
|
|
605
631
|
const { familyPosition: fp } = curr;
|
|
606
632
|
if (fp === 'LEFT' || fp === 'ROOT_LEFT') {
|
|
607
633
|
parent.left = curr.right;
|
|
@@ -612,6 +638,8 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
612
638
|
needBalanced = parent;
|
|
613
639
|
}
|
|
614
640
|
else {
|
|
641
|
+
// Deleting the root, which has no left child
|
|
642
|
+
// Promote the right child as the new root
|
|
615
643
|
this._setRoot(curr.right);
|
|
616
644
|
curr.right = undefined;
|
|
617
645
|
}
|
|
@@ -622,28 +650,16 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
622
650
|
return deletedResult;
|
|
623
651
|
}
|
|
624
652
|
/**
|
|
625
|
-
*
|
|
626
|
-
*
|
|
627
|
-
*
|
|
628
|
-
*
|
|
629
|
-
*
|
|
630
|
-
* @param
|
|
631
|
-
*
|
|
632
|
-
* @param [
|
|
633
|
-
*
|
|
634
|
-
*
|
|
635
|
-
* @param {C} callback - The `callback` parameter in the `search` function is a callback function
|
|
636
|
-
* that will be called on each node that matches the search criteria. It is of type `C`, which
|
|
637
|
-
* extends `NodeCallback<BinaryTreeNode<K, V> | null>`. The default value for `callback` is `this._DEFAULT_NODE_CALLBACK` if
|
|
638
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `search` function is
|
|
639
|
-
* used to specify the node from which the search operation should begin. It represents the starting
|
|
640
|
-
* point in the binary tree where the search will be performed. If no specific `startNode` is
|
|
641
|
-
* provided, the search operation will start from the root
|
|
642
|
-
* @param {IterationType} iterationType - The `iterationType` parameter in the `search` function
|
|
643
|
-
* specifies the type of iteration to be used when searching for nodes in a binary tree. It can have
|
|
644
|
-
* two possible values:
|
|
645
|
-
* @returns The `search` function returns an array of values that match the provided criteria based
|
|
646
|
-
* on the search algorithm implemented within the function.
|
|
653
|
+
* Searches the tree for nodes matching a predicate.
|
|
654
|
+
* @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). Performs a full DFS (pre-order) scan of the tree. Time O(N), as it may visit every node. Space O(H) for the call stack (recursive) or explicit stack (iterative), where H is the tree height (O(N) worst-case).
|
|
655
|
+
*
|
|
656
|
+
* @template C - The type of the callback function.
|
|
657
|
+
* @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
|
|
658
|
+
* @param [onlyOne=false] - If true, stops after finding the first match.
|
|
659
|
+
* @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on matching nodes.
|
|
660
|
+
* @param [startNode=this._root] - The node to start the search from.
|
|
661
|
+
* @param [iterationType=this.iterationType] - Whether to use 'RECURSIVE' or 'ITERATIVE' search.
|
|
662
|
+
* @returns An array of results from the callback function for each matching node.
|
|
647
663
|
*/
|
|
648
664
|
search(keyNodeEntryOrPredicate, onlyOne = false, callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
|
|
649
665
|
if (keyNodeEntryOrPredicate === undefined)
|
|
@@ -690,74 +706,29 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
690
706
|
}
|
|
691
707
|
return ans;
|
|
692
708
|
}
|
|
693
|
-
/**
|
|
694
|
-
* Time Complexity: O(n)
|
|
695
|
-
* Space Complexity: O(k + log n)
|
|
696
|
-
*
|
|
697
|
-
* The function `getNodes` retrieves nodes from a binary tree based on a key, node, entry, raw data,
|
|
698
|
-
* or predicate, with options for recursive or iterative traversal.
|
|
699
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
|
|
700
|
-
* - The `getNodes` function you provided takes several parameters:
|
|
701
|
-
* @param [onlyOne=false] - The `onlyOne` parameter in the `getNodes` function is a boolean flag that
|
|
702
|
-
* determines whether to return only the first node that matches the criteria specified by the
|
|
703
|
-
* `keyNodeEntryOrPredicate` parameter. If `onlyOne` is set to `true`, the function will
|
|
704
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
705
|
-
* `getNodes` function is used to specify the starting point for traversing the binary tree. It
|
|
706
|
-
* represents the root node of the binary tree or the node from which the traversal should begin. If
|
|
707
|
-
* not provided, the default value is set to `this._root
|
|
708
|
-
* @param {IterationType} iterationType - The `iterationType` parameter in the `getNodes` function
|
|
709
|
-
* determines the type of iteration to be performed when traversing the nodes of a binary tree. It
|
|
710
|
-
* can have two possible values:
|
|
711
|
-
* @returns The `getNodes` function returns an array of nodes that satisfy the provided condition
|
|
712
|
-
* based on the input parameters and the iteration type specified.
|
|
713
|
-
*/
|
|
714
709
|
getNodes(keyNodeEntryOrPredicate, onlyOne = false, startNode = this._root, iterationType = this.iterationType) {
|
|
715
710
|
return this.search(keyNodeEntryOrPredicate, onlyOne, node => node, startNode, iterationType);
|
|
716
711
|
}
|
|
717
712
|
/**
|
|
718
|
-
*
|
|
719
|
-
*
|
|
720
|
-
*
|
|
721
|
-
*
|
|
722
|
-
*
|
|
723
|
-
* @param
|
|
724
|
-
*
|
|
725
|
-
* node, entry, raw data, or a predicate function.
|
|
726
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
727
|
-
* `getNode` function is used to specify the starting point for searching for a node in a binary
|
|
728
|
-
* tree. If no specific starting point is provided, the default value is set to `this._root`, which
|
|
729
|
-
* is typically the root node of the binary tree.
|
|
730
|
-
* @param {IterationType} iterationType - The `iterationType` parameter in the `getNode` method is
|
|
731
|
-
* used to specify the type of iteration to be performed when searching for a node. It has a default
|
|
732
|
-
* value of `this.iterationType`, which means it will use the iteration type defined in the current
|
|
733
|
-
* context if no specific value is provided
|
|
734
|
-
* @returns The `getNode` function is returning the first node that matches the specified criteria,
|
|
735
|
-
* or `null` if no matching node is found.
|
|
713
|
+
* Gets the first node matching a predicate.
|
|
714
|
+
* @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). Time O(N) in the worst case (via `search`). Space O(H) or O(N) (via `search`).
|
|
715
|
+
*
|
|
716
|
+
* @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
|
|
717
|
+
* @param [startNode=this._root] - The node to start the search from.
|
|
718
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
719
|
+
* @returns The first matching node, or undefined if not found.
|
|
736
720
|
*/
|
|
737
721
|
getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
738
722
|
return this.search(keyNodeEntryOrPredicate, true, node => node, startNode, iterationType)[0];
|
|
739
723
|
}
|
|
740
724
|
/**
|
|
741
|
-
*
|
|
742
|
-
*
|
|
743
|
-
*
|
|
744
|
-
*
|
|
745
|
-
* node
|
|
746
|
-
* @param
|
|
747
|
-
*
|
|
748
|
-
* following types:
|
|
749
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `get`
|
|
750
|
-
* method is used to specify the starting point for searching for a key or node in the binary tree.
|
|
751
|
-
* If no specific starting point is provided, the default starting point is the root of the binary
|
|
752
|
-
* tree (`this._root`).
|
|
753
|
-
* @param {IterationType} iterationType - The `iterationType` parameter in the `get` method is used
|
|
754
|
-
* to specify the type of iteration to be performed when searching for a key in the binary tree. It
|
|
755
|
-
* is an optional parameter with a default value of `this.iterationType`, which means it will use the
|
|
756
|
-
* iteration type defined in the
|
|
757
|
-
* @returns The `get` method is returning the value associated with the specified key, node, entry,
|
|
758
|
-
* raw data, or predicate in the binary tree map. If the specified key or node is found in the tree,
|
|
759
|
-
* the method returns the corresponding value. If the key or node is not found, it returns
|
|
760
|
-
* `undefined`.
|
|
725
|
+
* Gets the value associated with a key.
|
|
726
|
+
* @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). Time O(1) if in Map mode. O(N) if not in Map mode (uses `getNode`). Space O(1) if in Map mode. O(H) or O(N) otherwise.
|
|
727
|
+
*
|
|
728
|
+
* @param keyNodeEntryOrPredicate - The key, node, or entry to get the value for.
|
|
729
|
+
* @param [startNode=this._root] - The node to start searching from (if not in Map mode).
|
|
730
|
+
* @param [iterationType=this.iterationType] - The traversal method (if not in Map mode).
|
|
731
|
+
* @returns The associated value, or undefined.
|
|
761
732
|
*/
|
|
762
733
|
get(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
763
734
|
var _a;
|
|
@@ -769,35 +740,12 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
769
740
|
}
|
|
770
741
|
return (_a = this.getNode(keyNodeEntryOrPredicate, startNode, iterationType)) === null || _a === void 0 ? void 0 : _a.value;
|
|
771
742
|
}
|
|
772
|
-
/**
|
|
773
|
-
* Time Complexity: O(n)
|
|
774
|
-
* Space Complexity: O(log n)
|
|
775
|
-
*
|
|
776
|
-
* The `has` function in TypeScript checks if a specified key, node, entry, raw data, or predicate
|
|
777
|
-
* exists in the data structure.
|
|
778
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
|
|
779
|
-
* - The `keyNodeEntryOrPredicate` parameter in the `override has` method can accept one of
|
|
780
|
-
* the following types:
|
|
781
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
782
|
-
* `override` method is used to specify the starting point for the search operation within the data
|
|
783
|
-
* structure. It defaults to `this._root` if not provided explicitly.
|
|
784
|
-
* @param {IterationType} iterationType - The `iterationType` parameter in the `override has` method
|
|
785
|
-
* is used to specify the type of iteration to be performed. It has a default value of
|
|
786
|
-
* `this.iterationType`, which means it will use the iteration type defined in the current context if
|
|
787
|
-
* no value is provided when calling the method.
|
|
788
|
-
* @returns The `override has` method is returning a boolean value. It checks if there are any nodes
|
|
789
|
-
* that match the provided key, node, entry, raw data, or predicate in the tree structure. If there
|
|
790
|
-
* are matching nodes, it returns `true`, indicating that the tree contains the specified element.
|
|
791
|
-
* Otherwise, it returns `false`.
|
|
792
|
-
*/
|
|
793
743
|
has(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
794
744
|
return this.search(keyNodeEntryOrPredicate, true, node => node, startNode, iterationType).length > 0;
|
|
795
745
|
}
|
|
796
746
|
/**
|
|
797
|
-
*
|
|
798
|
-
*
|
|
799
|
-
*
|
|
800
|
-
* The clear function removes nodes and values in map mode.
|
|
747
|
+
* Clears the tree of all nodes and values.
|
|
748
|
+
* @remarks Time O(N) if in Map mode (due to `_store.clear()`), O(1) otherwise. Space O(1)
|
|
801
749
|
*/
|
|
802
750
|
clear() {
|
|
803
751
|
this._clearNodes();
|
|
@@ -805,57 +753,35 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
805
753
|
this._clearValues();
|
|
806
754
|
}
|
|
807
755
|
/**
|
|
808
|
-
*
|
|
809
|
-
*
|
|
756
|
+
* Checks if the tree is empty.
|
|
757
|
+
* @remarks Time O(1), Space O(1)
|
|
810
758
|
*
|
|
811
|
-
*
|
|
812
|
-
* boolean value.
|
|
813
|
-
* @returns The `isEmpty()` method is returning a boolean value, specifically `true` if the `_size`
|
|
814
|
-
* property is equal to 0, indicating that the data structure is empty, and `false` otherwise.
|
|
759
|
+
* @returns True if the tree has no nodes, false otherwise.
|
|
815
760
|
*/
|
|
816
761
|
isEmpty() {
|
|
817
762
|
return this._size === 0;
|
|
818
763
|
}
|
|
819
764
|
/**
|
|
820
|
-
*
|
|
821
|
-
* Space
|
|
765
|
+
* Checks if the tree is perfectly balanced.
|
|
766
|
+
* @remarks A tree is perfectly balanced if the difference between min and max height is at most 1. Time O(N), as it requires two full traversals (`getMinHeight` and `getHeight`). Space O(H) or O(N) (from height calculation).
|
|
822
767
|
*
|
|
823
|
-
*
|
|
824
|
-
*
|
|
825
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting
|
|
826
|
-
* point for checking if the binary tree is perfectly balanced. It represents the root node of the
|
|
827
|
-
* binary tree or a specific node from which the balance check should begin.
|
|
828
|
-
* @returns The method `isPerfectlyBalanced` is returning a boolean value, which indicates whether
|
|
829
|
-
* the tree starting from the `startNode` node is perfectly balanced or not. The return value is
|
|
830
|
-
* determined by comparing the minimum height of the tree with the height of the tree. If the minimum
|
|
831
|
-
* height plus 1 is greater than or equal to the height of the tree, then it is considered perfectly
|
|
832
|
-
* balanced and
|
|
768
|
+
* @param [startNode=this._root] - The node to start checking from.
|
|
769
|
+
* @returns True if perfectly balanced, false otherwise.
|
|
833
770
|
*/
|
|
834
771
|
isPerfectlyBalanced(startNode = this._root) {
|
|
835
772
|
return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);
|
|
836
773
|
}
|
|
837
774
|
/**
|
|
838
|
-
*
|
|
839
|
-
* Space
|
|
775
|
+
* Checks if the tree is a valid Binary Search Tree (BST).
|
|
776
|
+
* @remarks Time O(N), as it must visit every node. Space O(H) for the call stack (recursive) or explicit stack (iterative), where H is the tree height (O(N) worst-case).
|
|
840
777
|
*
|
|
841
|
-
*
|
|
842
|
-
*
|
|
843
|
-
* @
|
|
844
|
-
* function represents the starting point for checking whether a binary search tree (BST) is valid.
|
|
845
|
-
* It can be a node in the BST or a reference to the root of the BST. If no specific node is
|
|
846
|
-
* provided, the function will default to
|
|
847
|
-
* @param {IterationType} iterationType - The `iterationType` parameter in the `isBST` function
|
|
848
|
-
* determines whether the function should use a recursive approach or an iterative approach to check
|
|
849
|
-
* if the binary search tree (BST) is valid.
|
|
850
|
-
* @returns The `isBST` method is returning a boolean value, which indicates whether the binary
|
|
851
|
-
* search tree (BST) represented by the given root node is a valid BST or not. The method checks if
|
|
852
|
-
* the tree satisfies the BST property, where for every node, all nodes in its left subtree have keys
|
|
853
|
-
* less than the node's key, and all nodes in its right subtree have keys greater than the node's
|
|
778
|
+
* @param [startNode=this._root] - The node to start checking from.
|
|
779
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
780
|
+
* @returns True if it's a valid BST, false otherwise.
|
|
854
781
|
*/
|
|
855
782
|
isBST(startNode = this._root, iterationType = this.iterationType) {
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
if (!startNode)
|
|
783
|
+
const startNodeSired = this.ensureNode(startNode);
|
|
784
|
+
if (!startNodeSired)
|
|
859
785
|
return true;
|
|
860
786
|
if (iterationType === 'RECURSIVE') {
|
|
861
787
|
const dfs = (cur, min, max) => {
|
|
@@ -866,16 +792,16 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
866
792
|
return false;
|
|
867
793
|
return dfs(cur.left, min, numKey) && dfs(cur.right, numKey, max);
|
|
868
794
|
};
|
|
869
|
-
const isStandardBST = dfs(
|
|
870
|
-
const isInverseBST = dfs(
|
|
795
|
+
const isStandardBST = dfs(startNodeSired, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
|
|
796
|
+
const isInverseBST = dfs(startNodeSired, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER); // Check for reverse BST
|
|
871
797
|
return isStandardBST || isInverseBST;
|
|
872
798
|
}
|
|
873
799
|
else {
|
|
800
|
+
// Iterative in-order traversal check
|
|
874
801
|
const checkBST = (checkMax = false) => {
|
|
875
802
|
const stack = [];
|
|
876
803
|
let prev = checkMax ? Number.MAX_SAFE_INTEGER : Number.MIN_SAFE_INTEGER;
|
|
877
|
-
|
|
878
|
-
let curr = startNode;
|
|
804
|
+
let curr = startNodeSired;
|
|
879
805
|
while (this.isRealNode(curr) || stack.length > 0) {
|
|
880
806
|
while (this.isRealNode(curr)) {
|
|
881
807
|
stack.push(curr);
|
|
@@ -890,25 +816,18 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
890
816
|
}
|
|
891
817
|
return true;
|
|
892
818
|
};
|
|
893
|
-
const isStandardBST = checkBST(false)
|
|
819
|
+
const isStandardBST = checkBST(false);
|
|
820
|
+
const isInverseBST = checkBST(true);
|
|
894
821
|
return isStandardBST || isInverseBST;
|
|
895
822
|
}
|
|
896
823
|
}
|
|
897
824
|
/**
|
|
898
|
-
*
|
|
899
|
-
*
|
|
825
|
+
* Gets the depth of a node (distance from `startNode`).
|
|
826
|
+
* @remarks Time O(H), where H is the depth of the `dist` node relative to `startNode`. O(N) worst-case. Space O(1).
|
|
900
827
|
*
|
|
901
|
-
* The
|
|
902
|
-
* @param
|
|
903
|
-
*
|
|
904
|
-
* It is the target node for which you want to calculate the depth from the `startNode` node.
|
|
905
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
906
|
-
* `getDepth` function represents the starting point from which you want to calculate the depth of a
|
|
907
|
-
* given node or entry in a binary tree. If no specific starting point is provided, the default value
|
|
908
|
-
* for `startNode` is set to the root of the binary
|
|
909
|
-
* @returns The `getDepth` method returns the depth of a given node `dist` relative to the
|
|
910
|
-
* `startNode` node in a binary tree. If the `dist` node is not found in the path to the `startNode`
|
|
911
|
-
* node, it returns the depth of the `dist` node from the root of the tree.
|
|
828
|
+
* @param dist - The node to find the depth of.
|
|
829
|
+
* @param [startNode=this._root] - The node to measure depth from (defaults to root).
|
|
830
|
+
* @returns The depth (0 if `dist` is `startNode`).
|
|
912
831
|
*/
|
|
913
832
|
getDepth(dist, startNode = this._root) {
|
|
914
833
|
let distEnsured = this.ensureNode(dist);
|
|
@@ -924,21 +843,12 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
924
843
|
return depth;
|
|
925
844
|
}
|
|
926
845
|
/**
|
|
927
|
-
*
|
|
928
|
-
* Space
|
|
846
|
+
* Gets the maximum height of the tree (longest path from startNode to a leaf).
|
|
847
|
+
* @remarks Time O(N), as it must visit every node. Space O(H) for recursive stack (O(N) worst-case) or O(N) for iterative stack (storing node + depth).
|
|
929
848
|
*
|
|
930
|
-
*
|
|
931
|
-
*
|
|
932
|
-
* @
|
|
933
|
-
* point from which the height of the binary tree will be calculated. It can be a node in the binary
|
|
934
|
-
* tree or a reference to the root of the tree. If not provided, it defaults to the root of the
|
|
935
|
-
* binary tree data structure.
|
|
936
|
-
* @param {IterationType} iterationType - The `iterationType` parameter is used to determine the type
|
|
937
|
-
* of iteration to be performed while calculating the height of the binary tree. It can have two
|
|
938
|
-
* possible values:
|
|
939
|
-
* @returns The `getHeight` method returns the height of the binary tree starting from the specified
|
|
940
|
-
* root node. The height is calculated based on the maximum depth of the tree, considering either a
|
|
941
|
-
* recursive approach or an iterative approach depending on the `iterationType` parameter.
|
|
849
|
+
* @param [startNode=this._root] - The node to start measuring from.
|
|
850
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
851
|
+
* @returns The height ( -1 for an empty tree, 0 for a single-node tree).
|
|
942
852
|
*/
|
|
943
853
|
getHeight(startNode = this._root, iterationType = this.iterationType) {
|
|
944
854
|
startNode = this.ensureNode(startNode);
|
|
@@ -955,6 +865,7 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
955
865
|
return _getMaxHeight(startNode);
|
|
956
866
|
}
|
|
957
867
|
else {
|
|
868
|
+
// Iterative (using DFS)
|
|
958
869
|
const stack = [{ node: startNode, depth: 0 }];
|
|
959
870
|
let maxHeight = 0;
|
|
960
871
|
while (stack.length > 0) {
|
|
@@ -969,22 +880,12 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
969
880
|
}
|
|
970
881
|
}
|
|
971
882
|
/**
|
|
972
|
-
*
|
|
973
|
-
* Space
|
|
883
|
+
* Gets the minimum height of the tree (shortest path from startNode to a leaf).
|
|
884
|
+
* @remarks Time O(N), as it must visit every node. Space O(H) for recursive stack (O(N) worst-case) or O(N) for iterative (due to `depths` Map).
|
|
974
885
|
*
|
|
975
|
-
*
|
|
976
|
-
*
|
|
977
|
-
* @
|
|
978
|
-
* `getMinHeight` function represents the starting node from which the minimum height of the binary
|
|
979
|
-
* tree will be calculated. It is either a node in the binary tree or a reference to the root of the
|
|
980
|
-
* tree. If not provided, the default value is the root
|
|
981
|
-
* @param {IterationType} iterationType - The `iterationType` parameter in the `getMinHeight` method
|
|
982
|
-
* specifies the type of iteration to use when calculating the minimum height of a binary tree. It
|
|
983
|
-
* can have two possible values:
|
|
984
|
-
* @returns The `getMinHeight` method returns the minimum height of the binary tree starting from the
|
|
985
|
-
* specified root node. The height is calculated based on the shortest path from the root node to a
|
|
986
|
-
* leaf node in the tree. The method uses either a recursive approach or an iterative approach (using
|
|
987
|
-
* a stack) based on the `iterationType` parameter.
|
|
886
|
+
* @param [startNode=this._root] - The node to start measuring from.
|
|
887
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
888
|
+
* @returns The minimum height (-1 for empty, 0 for single node).
|
|
988
889
|
*/
|
|
989
890
|
getMinHeight(startNode = this._root, iterationType = this.iterationType) {
|
|
990
891
|
startNode = this.ensureNode(startNode);
|
|
@@ -995,7 +896,7 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
995
896
|
if (!this.isRealNode(cur))
|
|
996
897
|
return 0;
|
|
997
898
|
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right))
|
|
998
|
-
return 0;
|
|
899
|
+
return 0; // Leaf node
|
|
999
900
|
const leftMinHeight = _getMinHeight(cur.left);
|
|
1000
901
|
const rightMinHeight = _getMinHeight(cur.right);
|
|
1001
902
|
return Math.min(leftMinHeight, rightMinHeight) + 1;
|
|
@@ -1003,6 +904,7 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1003
904
|
return _getMinHeight(startNode);
|
|
1004
905
|
}
|
|
1005
906
|
else {
|
|
907
|
+
// Iterative (using post-order DFS)
|
|
1006
908
|
const stack = [];
|
|
1007
909
|
let node = startNode, last = null;
|
|
1008
910
|
const depths = new Map();
|
|
@@ -1031,24 +933,14 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1031
933
|
}
|
|
1032
934
|
}
|
|
1033
935
|
/**
|
|
1034
|
-
*
|
|
1035
|
-
*
|
|
1036
|
-
*
|
|
1037
|
-
*
|
|
1038
|
-
*
|
|
1039
|
-
* @param
|
|
1040
|
-
*
|
|
1041
|
-
*
|
|
1042
|
-
* type `C
|
|
1043
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } beginNode - The `beginNode` parameter in the
|
|
1044
|
-
* `getPathToRoot` function can be either a key, a node, an entry, or any other value of type `R`.
|
|
1045
|
-
* @param [isReverse=true] - The `isReverse` parameter in the `getPathToRoot` function determines
|
|
1046
|
-
* whether the resulting path from the given `beginNode` to the root should be in reverse order or
|
|
1047
|
-
* not. If `isReverse` is set to `true`, the path will be reversed before being returned. If `is
|
|
1048
|
-
* @returns The function `getPathToRoot` returns an array of the return values of the callback
|
|
1049
|
-
* function `callback` applied to each node in the path from the `beginNode` to the root node. The
|
|
1050
|
-
* array is either in reverse order or in the original order based on the value of the `isReverse`
|
|
1051
|
-
* parameter.
|
|
936
|
+
* Gets the path from a given node up to the root.
|
|
937
|
+
* @remarks Time O(H), where H is the depth of the `beginNode`. O(N) worst-case. Space O(H) for the result array.
|
|
938
|
+
*
|
|
939
|
+
* @template C - The type of the callback function.
|
|
940
|
+
* @param beginNode - The node to start the path from.
|
|
941
|
+
* @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on each node in the path.
|
|
942
|
+
* @param [isReverse=false] - If true, returns the path from root-to-node.
|
|
943
|
+
* @returns An array of callback results.
|
|
1052
944
|
*/
|
|
1053
945
|
getPathToRoot(beginNode, callback = this._DEFAULT_NODE_CALLBACK, isReverse = false) {
|
|
1054
946
|
const result = [];
|
|
@@ -1056,40 +948,28 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1056
948
|
if (!beginNodeEnsured)
|
|
1057
949
|
return result;
|
|
1058
950
|
while (beginNodeEnsured.parent) {
|
|
1059
|
-
// Array.push + Array.reverse is more efficient than Array.unshift
|
|
1060
951
|
result.push(callback(beginNodeEnsured));
|
|
1061
952
|
beginNodeEnsured = beginNodeEnsured.parent;
|
|
1062
953
|
}
|
|
1063
|
-
result.push(callback(beginNodeEnsured));
|
|
954
|
+
result.push(callback(beginNodeEnsured)); // Add the root
|
|
1064
955
|
return isReverse ? result.reverse() : result;
|
|
1065
956
|
}
|
|
1066
957
|
/**
|
|
1067
|
-
*
|
|
1068
|
-
*
|
|
1069
|
-
*
|
|
1070
|
-
*
|
|
1071
|
-
*
|
|
1072
|
-
* @param
|
|
1073
|
-
*
|
|
1074
|
-
*
|
|
1075
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
1076
|
-
* `getLeftMost` function represents the starting point for finding the leftmost node in a binary
|
|
1077
|
-
* tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
|
|
1078
|
-
* starting point is provided, the function will default
|
|
1079
|
-
* @param {IterationType} iterationType - The `iterationType` parameter in the `getLeftMost` function
|
|
1080
|
-
* specifies the type of iteration to be used when traversing the binary tree nodes. It can have two
|
|
1081
|
-
* possible values:
|
|
1082
|
-
* @returns The `getLeftMost` function returns the result of the callback function `C` applied to the
|
|
1083
|
-
* leftmost node in the binary tree starting from the `startNode` node. If the `startNode` node is
|
|
1084
|
-
* `NIL`, it returns the result of the callback function applied to `undefined`. If the `startNode`
|
|
1085
|
-
* node is not a real node, it returns the result of the callback
|
|
958
|
+
* Finds the leftmost node in a subtree (the node with the smallest key in a BST).
|
|
959
|
+
* @remarks Time O(H), where H is the height of the left spine. O(N) worst-case. Space O(H) for recursive/trampoline stack.
|
|
960
|
+
*
|
|
961
|
+
* @template C - The type of the callback function.
|
|
962
|
+
* @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on the leftmost node.
|
|
963
|
+
* @param [startNode=this._root] - The subtree root to search from.
|
|
964
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
965
|
+
* @returns The callback result for the leftmost node.
|
|
1086
966
|
*/
|
|
1087
967
|
getLeftMost(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
|
|
1088
968
|
if (this.isNIL(startNode))
|
|
1089
969
|
return callback(undefined);
|
|
1090
|
-
|
|
1091
|
-
if (!this.isRealNode(
|
|
1092
|
-
return callback(
|
|
970
|
+
const ensuredStartNode = this.ensureNode(startNode);
|
|
971
|
+
if (!this.isRealNode(ensuredStartNode))
|
|
972
|
+
return callback(undefined);
|
|
1093
973
|
if (iterationType === 'RECURSIVE') {
|
|
1094
974
|
const dfs = (cur) => {
|
|
1095
975
|
const { left } = cur;
|
|
@@ -1097,47 +977,35 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1097
977
|
return cur;
|
|
1098
978
|
return dfs(left);
|
|
1099
979
|
};
|
|
1100
|
-
return callback(dfs(
|
|
980
|
+
return callback(dfs(ensuredStartNode));
|
|
1101
981
|
}
|
|
1102
982
|
else {
|
|
1103
|
-
//
|
|
983
|
+
// Iterative (trampolined to prevent stack overflow, though 'ITERATIVE' usually means a loop)
|
|
1104
984
|
const dfs = (0, utils_1.makeTrampoline)((cur) => {
|
|
1105
985
|
const { left } = cur;
|
|
1106
986
|
if (!this.isRealNode(left))
|
|
1107
987
|
return cur;
|
|
1108
988
|
return (0, utils_1.makeTrampolineThunk)(() => dfs(left));
|
|
1109
989
|
});
|
|
1110
|
-
return callback(dfs(
|
|
990
|
+
return callback(dfs(ensuredStartNode));
|
|
1111
991
|
}
|
|
1112
992
|
}
|
|
1113
993
|
/**
|
|
1114
|
-
*
|
|
1115
|
-
*
|
|
1116
|
-
*
|
|
1117
|
-
*
|
|
1118
|
-
*
|
|
1119
|
-
* @param
|
|
1120
|
-
*
|
|
1121
|
-
*
|
|
1122
|
-
* as
|
|
1123
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
1124
|
-
* `getRightMost` function represents the starting point for finding the rightmost node in a binary
|
|
1125
|
-
* tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
|
|
1126
|
-
* starting point is provided, the function will default
|
|
1127
|
-
* @param {IterationType} iterationType - The `iterationType` parameter in the `getRightMost`
|
|
1128
|
-
* function specifies the type of iteration to be used when traversing the binary tree nodes. It can
|
|
1129
|
-
* have two possible values:
|
|
1130
|
-
* @returns The `getRightMost` function returns the result of the callback function `C`, which is
|
|
1131
|
-
* passed as a parameter to the function. The callback function is called with the rightmost node in
|
|
1132
|
-
* the binary tree structure, determined based on the specified iteration type ('RECURSIVE' or
|
|
1133
|
-
* other).
|
|
994
|
+
* Finds the rightmost node in a subtree (the node with the largest key in a BST).
|
|
995
|
+
* @remarks Time O(H), where H is the height of the right spine. O(N) worst-case. Space O(H) for recursive/trampoline stack.
|
|
996
|
+
*
|
|
997
|
+
* @template C - The type of the callback function.
|
|
998
|
+
* @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on the rightmost node.
|
|
999
|
+
* @param [startNode=this._root] - The subtree root to search from.
|
|
1000
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
1001
|
+
* @returns The callback result for the rightmost node.
|
|
1134
1002
|
*/
|
|
1135
1003
|
getRightMost(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
|
|
1136
1004
|
if (this.isNIL(startNode))
|
|
1137
1005
|
return callback(undefined);
|
|
1138
1006
|
startNode = this.ensureNode(startNode);
|
|
1139
1007
|
if (!startNode)
|
|
1140
|
-
return callback(
|
|
1008
|
+
return callback(undefined);
|
|
1141
1009
|
if (iterationType === 'RECURSIVE') {
|
|
1142
1010
|
const dfs = (cur) => {
|
|
1143
1011
|
const { right } = cur;
|
|
@@ -1148,7 +1016,6 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1148
1016
|
return callback(dfs(startNode));
|
|
1149
1017
|
}
|
|
1150
1018
|
else {
|
|
1151
|
-
// Indirect implementation of iteration using tail recursion optimization
|
|
1152
1019
|
const dfs = (0, utils_1.makeTrampoline)((cur) => {
|
|
1153
1020
|
const { right } = cur;
|
|
1154
1021
|
if (!this.isRealNode(right))
|
|
@@ -1159,17 +1026,11 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1159
1026
|
}
|
|
1160
1027
|
}
|
|
1161
1028
|
/**
|
|
1162
|
-
*
|
|
1163
|
-
*
|
|
1029
|
+
* Gets the Morris traversal predecessor (rightmost node in the left subtree, or node itself).
|
|
1030
|
+
* @remarks This is primarily a helper for Morris traversal. Time O(H), where H is the height of the left subtree. O(N) worst-case. Space O(1).
|
|
1164
1031
|
*
|
|
1165
|
-
*
|
|
1166
|
-
*
|
|
1167
|
-
* @param {BinaryTreeNode<K, V>} node - The `getPredecessor` function you provided seems to be attempting to find the
|
|
1168
|
-
* predecessor of a given node in a binary tree. However, there seems to be a logical issue in the
|
|
1169
|
-
* while loop condition that might cause an infinite loop.
|
|
1170
|
-
* @returns The `getPredecessor` function returns the predecessor node of the input `BinaryTreeNode<K, V>` parameter.
|
|
1171
|
-
* If the left child of the input node exists, it traverses to the rightmost node of the left subtree
|
|
1172
|
-
* to find the predecessor. If the left child does not exist, it returns the input node itself.
|
|
1032
|
+
* @param node - The node to find the predecessor for.
|
|
1033
|
+
* @returns The Morris predecessor.
|
|
1173
1034
|
*/
|
|
1174
1035
|
getPredecessor(node) {
|
|
1175
1036
|
if (this.isRealNode(node.left)) {
|
|
@@ -1186,17 +1047,11 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1186
1047
|
}
|
|
1187
1048
|
}
|
|
1188
1049
|
/**
|
|
1189
|
-
*
|
|
1190
|
-
*
|
|
1050
|
+
* Gets the in-order successor of a node in a BST.
|
|
1051
|
+
* @remarks Time O(H), where H is the tree height. O(N) worst-case. Space O(H) (due to `getLeftMost` stack).
|
|
1191
1052
|
*
|
|
1192
|
-
*
|
|
1193
|
-
*
|
|
1194
|
-
* @param {K | BinaryTreeNode<K, V> | null} [x] - The `getSuccessor` function takes a parameter `x`, which can be of
|
|
1195
|
-
* type `K`, `BinaryTreeNode<K, V>`, or `null`.
|
|
1196
|
-
* @returns The `getSuccessor` function returns the successor node of the input node `x`. If `x` has
|
|
1197
|
-
* a right child, the function returns the leftmost node in the right subtree of `x`. If `x` does not
|
|
1198
|
-
* have a right child, the function traverses up the parent nodes until it finds a node that is not
|
|
1199
|
-
* the right child of its parent, and returns that node
|
|
1053
|
+
* @param [x] - The node to find the successor of.
|
|
1054
|
+
* @returns The successor node, or null/undefined if none exists.
|
|
1200
1055
|
*/
|
|
1201
1056
|
getSuccessor(x) {
|
|
1202
1057
|
x = this.ensureNode(x);
|
|
@@ -1213,32 +1068,17 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1213
1068
|
return y;
|
|
1214
1069
|
}
|
|
1215
1070
|
/**
|
|
1216
|
-
*
|
|
1217
|
-
* Space
|
|
1218
|
-
*
|
|
1219
|
-
*
|
|
1220
|
-
*
|
|
1221
|
-
* @param
|
|
1222
|
-
*
|
|
1223
|
-
*
|
|
1224
|
-
* @param
|
|
1225
|
-
*
|
|
1226
|
-
*
|
|
1227
|
-
* @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `dfs` function is a boolean flag
|
|
1228
|
-
* that determines whether the depth-first search should stop after finding the first matching node
|
|
1229
|
-
* or continue searching for all matching nodes. If `onlyOne` is set to `true`, the search will stop
|
|
1230
|
-
* after finding the first matching node
|
|
1231
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined}
|
|
1232
|
-
* startNode - The `startNode` parameter in the `dfs` function can be one of the following types:
|
|
1233
|
-
* @param {IterationType} iterationType - The `iterationType` parameter in the `dfs` function
|
|
1234
|
-
* specifies the type of iteration to be performed during the Depth-First Search traversal. It is
|
|
1235
|
-
* used to determine the order in which nodes are visited during the traversal. The possible values
|
|
1236
|
-
* for `iterationType` are typically defined as an enum or a
|
|
1237
|
-
* @param [includeNull=false] - The `includeNull` parameter in the `dfs` function determines whether
|
|
1238
|
-
* null nodes should be included in the depth-first search traversal. If `includeNull` is set to
|
|
1239
|
-
* `true`, null nodes will be included in the traversal process. If it is set to `false`, null nodes
|
|
1240
|
-
* will be skipped
|
|
1241
|
-
* @returns The `dfs` method is returning an array of the return type of the callback function `C`.
|
|
1071
|
+
* Performs a Depth-First Search (DFS) traversal.
|
|
1072
|
+
* @remarks Time O(N), visits every node. Space O(H) for the call/explicit stack. O(N) worst-case.
|
|
1073
|
+
*
|
|
1074
|
+
* @template C - The type of the callback function.
|
|
1075
|
+
* @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
|
|
1076
|
+
* @param [pattern='IN'] - The traversal order ('IN', 'PRE', 'POST').
|
|
1077
|
+
* @param [onlyOne=false] - If true, stops after the first callback.
|
|
1078
|
+
* @param [startNode=this._root] - The node to start from.
|
|
1079
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
1080
|
+
* @param [includeNull=false] - If true, includes null nodes in the traversal.
|
|
1081
|
+
* @returns An array of callback results.
|
|
1242
1082
|
*/
|
|
1243
1083
|
dfs(callback = this._DEFAULT_NODE_CALLBACK, pattern = 'IN', onlyOne = false, startNode = this._root, iterationType = this.iterationType, includeNull = false) {
|
|
1244
1084
|
startNode = this.ensureNode(startNode);
|
|
@@ -1247,27 +1087,15 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1247
1087
|
return this._dfs(callback, pattern, onlyOne, startNode, iterationType, includeNull);
|
|
1248
1088
|
}
|
|
1249
1089
|
/**
|
|
1250
|
-
*
|
|
1251
|
-
*
|
|
1252
|
-
*
|
|
1253
|
-
*
|
|
1254
|
-
*
|
|
1255
|
-
* @param
|
|
1256
|
-
*
|
|
1257
|
-
*
|
|
1258
|
-
* @
|
|
1259
|
-
* function represents the starting point for the breadth-first search traversal in a binary tree. It
|
|
1260
|
-
* can be specified as a key, node, or entry in the binary tree structure. If not provided, the
|
|
1261
|
-
* default value is the root node of the binary
|
|
1262
|
-
* @param {IterationType} iterationType - The `iterationType` parameter in the `bfs` function
|
|
1263
|
-
* determines the type of iteration to be performed on the binary tree nodes. It can have two
|
|
1264
|
-
* possible values:
|
|
1265
|
-
* @param [includeNull=false] - The `includeNull` parameter in the `bfs` function determines whether
|
|
1266
|
-
* to include `null` values in the breadth-first search traversal of a binary tree. If `includeNull`
|
|
1267
|
-
* is set to `true`, the traversal will include `null` values for nodes that do not have children
|
|
1268
|
-
* (left
|
|
1269
|
-
* @returns The `bfs` function returns an array of values that are the result of applying the
|
|
1270
|
-
* provided callback function to each node in the binary tree in a breadth-first search manner.
|
|
1090
|
+
* Performs a Breadth-First Search (BFS) or Level-Order traversal.
|
|
1091
|
+
* @remarks Time O(N), visits every node. Space O(N) in the worst case for the queue (e.g., a full last level).
|
|
1092
|
+
*
|
|
1093
|
+
* @template C - The type of the callback function.
|
|
1094
|
+
* @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
|
|
1095
|
+
* @param [startNode=this._root] - The node to start from.
|
|
1096
|
+
* @param [iterationType=this.iterationType] - The traversal method ('RECURSIVE' BFS is less common but supported here).
|
|
1097
|
+
* @param [includeNull=false] - If true, includes null nodes in the traversal.
|
|
1098
|
+
* @returns An array of callback results.
|
|
1271
1099
|
*/
|
|
1272
1100
|
bfs(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType, includeNull = false) {
|
|
1273
1101
|
startNode = this.ensureNode(startNode);
|
|
@@ -1275,6 +1103,7 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1275
1103
|
return [];
|
|
1276
1104
|
const ans = [];
|
|
1277
1105
|
if (iterationType === 'RECURSIVE') {
|
|
1106
|
+
// This is a "recursive" BFS, which is atypical. It uses a queue but calls itself.
|
|
1278
1107
|
const queue = new queue_1.Queue([
|
|
1279
1108
|
startNode
|
|
1280
1109
|
]);
|
|
@@ -1300,9 +1129,10 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1300
1129
|
dfs(0);
|
|
1301
1130
|
}
|
|
1302
1131
|
else {
|
|
1132
|
+
// Standard iterative BFS
|
|
1303
1133
|
const queue = new queue_1.Queue([startNode]);
|
|
1304
1134
|
while (queue.length > 0) {
|
|
1305
|
-
const levelSize = queue.length;
|
|
1135
|
+
const levelSize = queue.length; // Not strictly needed here, but good for level-by-level
|
|
1306
1136
|
for (let i = 0; i < levelSize; i++) {
|
|
1307
1137
|
const current = queue.shift();
|
|
1308
1138
|
ans.push(callback(current));
|
|
@@ -1324,22 +1154,14 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1324
1154
|
return ans;
|
|
1325
1155
|
}
|
|
1326
1156
|
/**
|
|
1327
|
-
*
|
|
1328
|
-
* Space
|
|
1157
|
+
* Finds all leaf nodes in the tree.
|
|
1158
|
+
* @remarks Time O(N), visits every node. Space O(H) for recursive stack or O(N) for iterative queue.
|
|
1329
1159
|
*
|
|
1330
|
-
*
|
|
1331
|
-
*
|
|
1332
|
-
* @param
|
|
1333
|
-
*
|
|
1334
|
-
* @
|
|
1335
|
-
* method is used to specify the starting point for finding and processing the leaves of a binary
|
|
1336
|
-
* tree. It can be provided as either a key, a node, or an entry in the binary tree structure. If not
|
|
1337
|
-
* explicitly provided, the default value
|
|
1338
|
-
* @param {IterationType} iterationType - The `iterationType` parameter in the `leaves` method
|
|
1339
|
-
* specifies the type of iteration to be performed when collecting the leaves of a binary tree. It
|
|
1340
|
-
* can have two possible values:
|
|
1341
|
-
* @returns The `leaves` method returns an array of values that are the result of applying the
|
|
1342
|
-
* provided callback function to each leaf node in the binary tree.
|
|
1160
|
+
* @template C - The type of the callback function.
|
|
1161
|
+
* @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each leaf node.
|
|
1162
|
+
* @param [startNode=this._root] - The node to start from.
|
|
1163
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
1164
|
+
* @returns An array of callback results.
|
|
1343
1165
|
*/
|
|
1344
1166
|
leaves(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
|
|
1345
1167
|
startNode = this.ensureNode(startNode);
|
|
@@ -1347,6 +1169,7 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1347
1169
|
if (!this.isRealNode(startNode))
|
|
1348
1170
|
return [];
|
|
1349
1171
|
if (iterationType === 'RECURSIVE') {
|
|
1172
|
+
// DFS-based
|
|
1350
1173
|
const dfs = (cur) => {
|
|
1351
1174
|
if (this.isLeaf(cur)) {
|
|
1352
1175
|
leaves.push(callback(cur));
|
|
@@ -1361,6 +1184,7 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1361
1184
|
dfs(startNode);
|
|
1362
1185
|
}
|
|
1363
1186
|
else {
|
|
1187
|
+
// BFS-based
|
|
1364
1188
|
const queue = new queue_1.Queue([startNode]);
|
|
1365
1189
|
while (queue.length > 0) {
|
|
1366
1190
|
const cur = queue.shift();
|
|
@@ -1378,28 +1202,15 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1378
1202
|
return leaves;
|
|
1379
1203
|
}
|
|
1380
1204
|
/**
|
|
1381
|
-
*
|
|
1382
|
-
*
|
|
1383
|
-
*
|
|
1384
|
-
*
|
|
1385
|
-
*
|
|
1386
|
-
* @param
|
|
1387
|
-
*
|
|
1388
|
-
*
|
|
1389
|
-
* @
|
|
1390
|
-
* `listLevels` function represents the starting point for traversing the binary tree. It can be
|
|
1391
|
-
* either a key, a node, or an entry in the binary tree. If not provided, the default value is the
|
|
1392
|
-
* root of the binary tree.
|
|
1393
|
-
* @param {IterationType} iterationType - The `iterationType` parameter in the `listLevels` function
|
|
1394
|
-
* determines the type of iteration to be performed on the binary tree nodes. It can have two
|
|
1395
|
-
* possible values:
|
|
1396
|
-
* @param [includeNull=false] - The `includeNull` parameter in the `listLevels` method determines
|
|
1397
|
-
* whether or not to include null nodes in the traversal of the binary tree. If `includeNull` is set
|
|
1398
|
-
* to `true`, the traversal will include null nodes in the levels of the tree. If set to `false`,
|
|
1399
|
-
* null
|
|
1400
|
-
* @returns The `listLevels` method returns an array of arrays, where each inner array represents a
|
|
1401
|
-
* level in a binary tree. Each inner array contains the return value of the provided callback
|
|
1402
|
-
* function applied to the nodes at that level.
|
|
1205
|
+
* Returns a 2D array of nodes, grouped by level.
|
|
1206
|
+
* @remarks Time O(N), visits every node. Space O(N) for the result array and the queue/stack.
|
|
1207
|
+
*
|
|
1208
|
+
* @template C - The type of the callback function.
|
|
1209
|
+
* @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
|
|
1210
|
+
* @param [startNode=this._root] - The node to start from.
|
|
1211
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
1212
|
+
* @param [includeNull=false] - If true, includes null nodes.
|
|
1213
|
+
* @returns A 2D array of callback results.
|
|
1403
1214
|
*/
|
|
1404
1215
|
listLevels(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType, includeNull = false) {
|
|
1405
1216
|
startNode = this.ensureNode(startNode);
|
|
@@ -1407,6 +1218,7 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1407
1218
|
if (!startNode)
|
|
1408
1219
|
return levelsNodes;
|
|
1409
1220
|
if (iterationType === 'RECURSIVE') {
|
|
1221
|
+
// Pre-order DFS based level listing
|
|
1410
1222
|
const _recursive = (node, level) => {
|
|
1411
1223
|
if (!levelsNodes[level])
|
|
1412
1224
|
levelsNodes[level] = [];
|
|
@@ -1427,6 +1239,7 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1427
1239
|
_recursive(startNode, 0);
|
|
1428
1240
|
}
|
|
1429
1241
|
else {
|
|
1242
|
+
// Iterative DFS based level listing
|
|
1430
1243
|
const stack = [[startNode, 0]];
|
|
1431
1244
|
while (stack.length > 0) {
|
|
1432
1245
|
const head = stack.pop();
|
|
@@ -1451,24 +1264,14 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1451
1264
|
return levelsNodes;
|
|
1452
1265
|
}
|
|
1453
1266
|
/**
|
|
1454
|
-
*
|
|
1455
|
-
*
|
|
1456
|
-
*
|
|
1457
|
-
*
|
|
1458
|
-
*
|
|
1459
|
-
* @param
|
|
1460
|
-
*
|
|
1461
|
-
*
|
|
1462
|
-
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `morris` function specifies
|
|
1463
|
-
* the type of Depth-First Search (DFS) order pattern to traverse the binary tree. The possible
|
|
1464
|
-
* values for the `pattern` parameter are:
|
|
1465
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `morris`
|
|
1466
|
-
* function is the starting point for the Morris traversal algorithm. It represents the root node of
|
|
1467
|
-
* the binary tree or the node from which the traversal should begin. It can be provided as either a
|
|
1468
|
-
* key, a node, an entry, or a reference
|
|
1469
|
-
* @returns The `morris` function is returning an array of values that are the result of applying the
|
|
1470
|
-
* provided callback function to each node in the binary tree in the specified order pattern (IN,
|
|
1471
|
-
* PRE, or POST).
|
|
1267
|
+
* Performs a Morris (threaded) traversal.
|
|
1268
|
+
* @remarks This traversal uses O(1) extra space (excluding the result array) by temporarily modifying the tree's right child pointers. Time O(N), as each node is visited a constant number of times. Space O(1) (excluding the `ans` array).
|
|
1269
|
+
*
|
|
1270
|
+
* @template C - The type of the callback function.
|
|
1271
|
+
* @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
|
|
1272
|
+
* @param [pattern='IN'] - The traversal order ('IN', 'PRE', 'POST').
|
|
1273
|
+
* @param [startNode=this._root] - The node to start from.
|
|
1274
|
+
* @returns An array of callback results.
|
|
1472
1275
|
*/
|
|
1473
1276
|
morris(callback = this._DEFAULT_NODE_CALLBACK, pattern = 'IN', startNode = this._root) {
|
|
1474
1277
|
startNode = this.ensureNode(startNode);
|
|
@@ -1476,6 +1279,7 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1476
1279
|
return [];
|
|
1477
1280
|
const ans = [];
|
|
1478
1281
|
let cur = startNode;
|
|
1282
|
+
// Helper to reverse a linked list (formed by right pointers)
|
|
1479
1283
|
const _reverseEdge = (node) => {
|
|
1480
1284
|
let pre = null;
|
|
1481
1285
|
let next = null;
|
|
@@ -1487,6 +1291,7 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1487
1291
|
}
|
|
1488
1292
|
return pre;
|
|
1489
1293
|
};
|
|
1294
|
+
// Helper to print the reversed edge (for post-order)
|
|
1490
1295
|
const _printEdge = (node) => {
|
|
1491
1296
|
const tail = _reverseEdge(node);
|
|
1492
1297
|
let cur = tail;
|
|
@@ -1494,7 +1299,7 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1494
1299
|
ans.push(callback(cur));
|
|
1495
1300
|
cur = cur.right;
|
|
1496
1301
|
}
|
|
1497
|
-
_reverseEdge(tail);
|
|
1302
|
+
_reverseEdge(tail); // Restore the edge
|
|
1498
1303
|
};
|
|
1499
1304
|
switch (pattern) {
|
|
1500
1305
|
case 'IN':
|
|
@@ -1502,11 +1307,13 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1502
1307
|
if (cur.left) {
|
|
1503
1308
|
const predecessor = this.getPredecessor(cur);
|
|
1504
1309
|
if (!predecessor.right) {
|
|
1310
|
+
// Create thread
|
|
1505
1311
|
predecessor.right = cur;
|
|
1506
1312
|
cur = cur.left;
|
|
1507
1313
|
continue;
|
|
1508
1314
|
}
|
|
1509
1315
|
else {
|
|
1316
|
+
// Remove thread
|
|
1510
1317
|
predecessor.right = null;
|
|
1511
1318
|
}
|
|
1512
1319
|
}
|
|
@@ -1519,12 +1326,14 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1519
1326
|
if (cur.left) {
|
|
1520
1327
|
const predecessor = this.getPredecessor(cur);
|
|
1521
1328
|
if (!predecessor.right) {
|
|
1329
|
+
// Create thread and visit
|
|
1522
1330
|
predecessor.right = cur;
|
|
1523
1331
|
ans.push(callback(cur));
|
|
1524
1332
|
cur = cur.left;
|
|
1525
1333
|
continue;
|
|
1526
1334
|
}
|
|
1527
1335
|
else {
|
|
1336
|
+
// Remove thread
|
|
1528
1337
|
predecessor.right = null;
|
|
1529
1338
|
}
|
|
1530
1339
|
}
|
|
@@ -1539,108 +1348,77 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1539
1348
|
if (cur.left) {
|
|
1540
1349
|
const predecessor = this.getPredecessor(cur);
|
|
1541
1350
|
if (predecessor.right === null) {
|
|
1351
|
+
// Create thread
|
|
1542
1352
|
predecessor.right = cur;
|
|
1543
1353
|
cur = cur.left;
|
|
1544
1354
|
continue;
|
|
1545
1355
|
}
|
|
1546
1356
|
else {
|
|
1357
|
+
// Remove thread and print right spine of left child
|
|
1547
1358
|
predecessor.right = null;
|
|
1548
1359
|
_printEdge(cur.left);
|
|
1549
1360
|
}
|
|
1550
1361
|
}
|
|
1551
1362
|
cur = cur.right;
|
|
1552
1363
|
}
|
|
1553
|
-
_printEdge(startNode);
|
|
1364
|
+
_printEdge(startNode); // Print the right spine of the root
|
|
1554
1365
|
break;
|
|
1555
1366
|
}
|
|
1556
1367
|
return ans;
|
|
1557
1368
|
}
|
|
1558
1369
|
/**
|
|
1559
|
-
*
|
|
1560
|
-
*
|
|
1370
|
+
* Clones the tree.
|
|
1371
|
+
* @remarks Time O(N * M), where N is the number of nodes and M is the tree size during insertion (due to `bfs` + `add`, and `add` is O(M)). Space O(N) for the new tree and the BFS queue.
|
|
1561
1372
|
*
|
|
1562
|
-
*
|
|
1563
|
-
* search.
|
|
1564
|
-
* @returns The `clone()` method is returning a cloned copy of the tree with the same structure and
|
|
1565
|
-
* values as the original tree. The method creates a new tree, iterates over the nodes of the
|
|
1566
|
-
* original tree using breadth-first search (bfs), and adds the nodes to the new tree. If a node in
|
|
1567
|
-
* the original tree is null, a null node is added to the cloned tree. If a node
|
|
1373
|
+
* @returns A new, cloned instance of the tree.
|
|
1568
1374
|
*/
|
|
1569
1375
|
clone() {
|
|
1570
|
-
const
|
|
1571
|
-
this._clone(
|
|
1572
|
-
return
|
|
1573
|
-
}
|
|
1574
|
-
/**
|
|
1575
|
-
*
|
|
1576
|
-
*
|
|
1577
|
-
*
|
|
1578
|
-
*
|
|
1579
|
-
*
|
|
1580
|
-
* @
|
|
1581
|
-
* called with four arguments: the `value` of the current entry, the `key` of the current entry, the
|
|
1582
|
-
* `index` of the current entry in the iteration, and the reference to the tree itself (`
|
|
1583
|
-
* @param {any} [thisArg] - The `thisArg` parameter in the `filter` method allows you to specify the
|
|
1584
|
-
* value of `this` that should be used when executing the `predicate` function. This is useful when
|
|
1585
|
-
* the `predicate` function relies on the context of a specific object or value. By providing a
|
|
1586
|
-
* `thisArg
|
|
1587
|
-
* @returns The `filter` method is returning a new tree that contains entries that pass the provided
|
|
1588
|
-
* predicate function.
|
|
1376
|
+
const out = this._createInstance();
|
|
1377
|
+
this._clone(out);
|
|
1378
|
+
return out;
|
|
1379
|
+
}
|
|
1380
|
+
/**
|
|
1381
|
+
* Creates a new tree containing only the entries that satisfy the predicate.
|
|
1382
|
+
* @remarks Time O(N * M), where N is nodes in this tree, and M is size of the new tree during insertion (O(N) iteration + O(M) `add` for each item). Space O(N) for the new tree.
|
|
1383
|
+
*
|
|
1384
|
+
* @param predicate - A function to test each [key, value] pair.
|
|
1385
|
+
* @param [thisArg] - `this` context for the predicate.
|
|
1386
|
+
* @returns A new, filtered tree.
|
|
1589
1387
|
*/
|
|
1590
1388
|
filter(predicate, thisArg) {
|
|
1591
|
-
const
|
|
1592
|
-
let
|
|
1593
|
-
for (const [
|
|
1594
|
-
if (predicate.call(thisArg,
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
*
|
|
1602
|
-
*
|
|
1603
|
-
*
|
|
1604
|
-
*
|
|
1605
|
-
*
|
|
1606
|
-
* @param
|
|
1607
|
-
*
|
|
1608
|
-
*
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
}
|
|
1625
|
-
return newTree;
|
|
1626
|
-
}
|
|
1627
|
-
/**
|
|
1628
|
-
* Time Complexity: O(n)
|
|
1629
|
-
* Space Complexity: O(n)
|
|
1630
|
-
*
|
|
1631
|
-
* The function `toVisual` in TypeScript overrides the visual representation of a binary tree with
|
|
1632
|
-
* customizable options for displaying undefined, null, and sentinel nodes.
|
|
1633
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
1634
|
-
* `toVisual` method is used to specify the starting point for visualizing the binary tree structure.
|
|
1635
|
-
* It can be a node, key, entry, or the root of the tree. If no specific starting point is provided,
|
|
1636
|
-
* the default is set to the root
|
|
1637
|
-
* @param {BinaryTreePrintOptions} [options] - The `options` parameter in the `toVisual` method is an
|
|
1638
|
-
* object that contains the following properties:
|
|
1639
|
-
* @returns The `override toVisual` method returns a string that represents the visual display of the
|
|
1640
|
-
* binary tree based on the provided options for showing undefined, null, and Red-Black NIL nodes.
|
|
1641
|
-
* The method constructs the visual representation by calling the `_displayAux` method and appending
|
|
1642
|
-
* the lines to the output string. The final output string contains the visual representation of the
|
|
1643
|
-
* binary tree with the specified options.
|
|
1389
|
+
const out = this._createInstance();
|
|
1390
|
+
let i = 0;
|
|
1391
|
+
for (const [k, v] of this)
|
|
1392
|
+
if (predicate.call(thisArg, k, v, i++, this))
|
|
1393
|
+
out.add([k, v]);
|
|
1394
|
+
return out;
|
|
1395
|
+
}
|
|
1396
|
+
/**
|
|
1397
|
+
* Creates a new tree by mapping each [key, value] pair to a new entry.
|
|
1398
|
+
* @remarks Time O(N * M), where N is nodes in this tree, and M is size of the new tree during insertion. Space O(N) for the new tree.
|
|
1399
|
+
*
|
|
1400
|
+
* @template MK - New key type.
|
|
1401
|
+
* @template MV - New value type.
|
|
1402
|
+
* @template MR - New raw type.
|
|
1403
|
+
* @param cb - A function to map each [key, value] pair.
|
|
1404
|
+
* @param [options] - Options for the new tree.
|
|
1405
|
+
* @param [thisArg] - `this` context for the callback.
|
|
1406
|
+
* @returns A new, mapped tree.
|
|
1407
|
+
*/
|
|
1408
|
+
map(cb, options, thisArg) {
|
|
1409
|
+
const out = this._createLike([], options);
|
|
1410
|
+
let i = 0;
|
|
1411
|
+
for (const [k, v] of this)
|
|
1412
|
+
out.add(cb.call(thisArg, k, v, i++, this));
|
|
1413
|
+
return out;
|
|
1414
|
+
}
|
|
1415
|
+
/**
|
|
1416
|
+
* Generates a string representation of the tree for visualization.
|
|
1417
|
+
* @remarks Time O(N), visits every node. Space O(N*H) or O(N^2) in the worst case, as the string width can grow significantly.
|
|
1418
|
+
*
|
|
1419
|
+
* @param [startNode=this._root] - The node to start printing from.
|
|
1420
|
+
* @param [options] - Options to control the output (e.g., show nulls).
|
|
1421
|
+
* @returns The string representation of the tree.
|
|
1644
1422
|
*/
|
|
1645
1423
|
toVisual(startNode = this._root, options) {
|
|
1646
1424
|
const opts = Object.assign({ isShowUndefined: false, isShowNull: true, isShowRedBlackNIL: false }, options);
|
|
@@ -1666,117 +1444,31 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1666
1444
|
return output;
|
|
1667
1445
|
}
|
|
1668
1446
|
/**
|
|
1669
|
-
*
|
|
1670
|
-
* Space
|
|
1447
|
+
* Prints a visual representation of the tree to the console.
|
|
1448
|
+
* @remarks Time O(N) (via `toVisual`). Space O(N*H) or O(N^2) (via `toVisual`).
|
|
1671
1449
|
*
|
|
1672
|
-
*
|
|
1673
|
-
*
|
|
1674
|
-
* @param {BinaryTreePrintOptions} [options] - The `options` parameter is used to specify the
|
|
1675
|
-
* printing options for the binary tree. It is an optional parameter that allows you to customize how
|
|
1676
|
-
* the binary tree is printed, such as choosing between different traversal orders or formatting
|
|
1677
|
-
* options.
|
|
1678
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
|
|
1679
|
-
* `override print` method is used to specify the starting point for printing the binary tree. It can
|
|
1680
|
-
* be either a key, a node, an entry, or the root of the tree. If no specific starting point is
|
|
1681
|
-
* provided, the default value is set to
|
|
1450
|
+
* @param [options] - Options to control the output.
|
|
1451
|
+
* @param [startNode=this._root] - The node to start printing from.
|
|
1682
1452
|
*/
|
|
1683
1453
|
print(options, startNode = this._root) {
|
|
1684
1454
|
console.log(this.toVisual(startNode, options));
|
|
1685
1455
|
}
|
|
1686
|
-
_clone(cloned) {
|
|
1687
|
-
this.bfs(node => {
|
|
1688
|
-
if (node === null)
|
|
1689
|
-
cloned.add(null);
|
|
1690
|
-
else {
|
|
1691
|
-
if (this._isMapMode)
|
|
1692
|
-
cloned.add([node.key, this._store.get(node.key)]);
|
|
1693
|
-
else
|
|
1694
|
-
cloned.add([node.key, node.value]);
|
|
1695
|
-
}
|
|
1696
|
-
}, this._root, this.iterationType, true);
|
|
1697
|
-
if (this._isMapMode)
|
|
1698
|
-
cloned._store = this._store;
|
|
1699
|
-
}
|
|
1700
1456
|
/**
|
|
1701
|
-
*
|
|
1702
|
-
* Space
|
|
1457
|
+
* (Protected) Core DFS implementation.
|
|
1458
|
+
* @remarks Time O(N), visits every node satisfying predicates. Space O(H) for call/explicit stack. O(N) worst-case.
|
|
1703
1459
|
*
|
|
1704
|
-
*
|
|
1705
|
-
*
|
|
1706
|
-
* @param
|
|
1707
|
-
*
|
|
1708
|
-
*
|
|
1709
|
-
*
|
|
1710
|
-
* @param
|
|
1711
|
-
*
|
|
1712
|
-
*
|
|
1713
|
-
* @
|
|
1714
|
-
*
|
|
1715
|
-
*
|
|
1716
|
-
* value.
|
|
1717
|
-
*/
|
|
1718
|
-
_keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value) {
|
|
1719
|
-
if (keyNodeOrEntry === undefined)
|
|
1720
|
-
return [undefined, undefined];
|
|
1721
|
-
if (keyNodeOrEntry === null)
|
|
1722
|
-
return [null, undefined];
|
|
1723
|
-
if (this.isNode(keyNodeOrEntry))
|
|
1724
|
-
return [keyNodeOrEntry, value];
|
|
1725
|
-
if (this.isEntry(keyNodeOrEntry)) {
|
|
1726
|
-
const [key, entryValue] = keyNodeOrEntry;
|
|
1727
|
-
if (key === undefined)
|
|
1728
|
-
return [undefined, undefined];
|
|
1729
|
-
else if (key === null)
|
|
1730
|
-
return [null, undefined];
|
|
1731
|
-
const finalValue = value !== null && value !== void 0 ? value : entryValue;
|
|
1732
|
-
return [this.createNode(key, finalValue), finalValue];
|
|
1733
|
-
}
|
|
1734
|
-
return [this.createNode(keyNodeOrEntry, value), value];
|
|
1735
|
-
}
|
|
1736
|
-
/**
|
|
1737
|
-
* Time complexity: O(n)
|
|
1738
|
-
* Space complexity: O(n)
|
|
1739
|
-
*
|
|
1740
|
-
* The `_dfs` function performs a depth-first search traversal on a binary tree, with customizable
|
|
1741
|
-
* options for traversal order and node processing.
|
|
1742
|
-
* @param {C} callback - The `callback` parameter in the `_dfs` method is a function that will be
|
|
1743
|
-
* called on each node visited during the depth-first search traversal. It is a generic type `C` that
|
|
1744
|
-
* extends `NodeCallback<BinaryTreeNode<K, V> | null>`. The default value for `callback`
|
|
1745
|
-
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `_dfs` method specifies the
|
|
1746
|
-
* order in which the nodes are visited during a depth-first search traversal. It can have one of the
|
|
1747
|
-
* following values:
|
|
1748
|
-
* @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `_dfs` method is a boolean flag
|
|
1749
|
-
* that determines whether the traversal should stop after processing a single node. If `onlyOne` is
|
|
1750
|
-
* set to `true`, the traversal will return as soon as a single node is processed. If it is set to
|
|
1751
|
-
* `false
|
|
1752
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined}
|
|
1753
|
-
* startNode - The `startNode` parameter in the `_dfs` method is used to specify the starting node
|
|
1754
|
-
* for the depth-first search traversal. It can be provided in different forms:
|
|
1755
|
-
* @param {IterationType} iterationType - The `iterationType` parameter in the `_dfs` method
|
|
1756
|
-
* specifies whether the traversal should be done recursively or iteratively. It can have two
|
|
1757
|
-
* possible values:
|
|
1758
|
-
* @param [includeNull=false] - The `includeNull` parameter in the `_dfs` method determines whether
|
|
1759
|
-
* null nodes should be included in the traversal process. If `includeNull` is set to `true`, the
|
|
1760
|
-
* method will consider null nodes as valid nodes to visit or process. If `includeNull` is set to
|
|
1761
|
-
* `false`,
|
|
1762
|
-
* @param shouldVisitLeft - The `shouldVisitLeft` parameter in the `_dfs` method is a function that
|
|
1763
|
-
* determines whether the left child of a node should be visited during the Depth-First Search
|
|
1764
|
-
* traversal. By default, it checks if the node is not null or undefined before visiting the left
|
|
1765
|
-
* child. You can customize this behavior
|
|
1766
|
-
* @param shouldVisitRight - The `shouldVisitRight` parameter in the `_dfs` method is a function that
|
|
1767
|
-
* determines whether to visit the right child node of the current node during a depth-first search
|
|
1768
|
-
* traversal. The default implementation of this function checks if the node is not null or undefined
|
|
1769
|
-
* before deciding to visit it.
|
|
1770
|
-
* @param shouldVisitRoot - The `shouldVisitRoot` parameter in the `_dfs` method is a function that
|
|
1771
|
-
* determines whether a given node should be visited during the depth-first search traversal. The
|
|
1772
|
-
* function takes a node as an argument and returns a boolean value indicating whether the node
|
|
1773
|
-
* should be visited.
|
|
1774
|
-
* @param shouldProcessRoot - The `shouldProcessRoot` parameter in the `_dfs` method is a function
|
|
1775
|
-
* that determines whether the root node should be processed during the Depth-First Search traversal.
|
|
1776
|
-
* It takes a node (BinaryTreeNode<K, V> | null | undefined) as input and returns a boolean value. If
|
|
1777
|
-
* the function
|
|
1778
|
-
* @returns The `_dfs` method returns an array of the return type of the provided callback function
|
|
1779
|
-
* `C`.
|
|
1460
|
+
* @template C - Callback type.
|
|
1461
|
+
* @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on nodes.
|
|
1462
|
+
* @param [pattern='IN'] - Traversal order.
|
|
1463
|
+
* @param [onlyOne=false] - Stop after first match.
|
|
1464
|
+
* @param [startNode=this._root] - Starting node.
|
|
1465
|
+
* @param [iterationType=this.iterationType] - Traversal method.
|
|
1466
|
+
* @param [includeNull=false] - Include nulls.
|
|
1467
|
+
* @param [shouldVisitLeft] - Predicate to traverse left.
|
|
1468
|
+
* @param [shouldVisitRight] - Predicate to traverse right.
|
|
1469
|
+
* @param [shouldVisitRoot] - Predicate to visit root.
|
|
1470
|
+
* @param [shouldProcessRoot] - Predicate to process root.
|
|
1471
|
+
* @returns Array of callback results.
|
|
1780
1472
|
*/
|
|
1781
1473
|
_dfs(callback = this._DEFAULT_NODE_CALLBACK, pattern = 'IN', onlyOne = false, startNode = this._root, iterationType = this.iterationType, includeNull = false, shouldVisitLeft = node => !!node, shouldVisitRight = node => !!node, shouldVisitRoot = node => {
|
|
1782
1474
|
if (includeNull)
|
|
@@ -1832,6 +1524,7 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1832
1524
|
dfs(startNode);
|
|
1833
1525
|
}
|
|
1834
1526
|
else {
|
|
1527
|
+
// Iterative
|
|
1835
1528
|
const stack = [{ opt: common_1.DFSOperation.VISIT, node: startNode }];
|
|
1836
1529
|
const pushLeft = (cur) => {
|
|
1837
1530
|
var _a;
|
|
@@ -1861,6 +1554,7 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1861
1554
|
}
|
|
1862
1555
|
}
|
|
1863
1556
|
else {
|
|
1557
|
+
// VISIT
|
|
1864
1558
|
switch (pattern) {
|
|
1865
1559
|
case 'IN':
|
|
1866
1560
|
pushRight(cur);
|
|
@@ -1884,19 +1578,11 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1884
1578
|
return ans;
|
|
1885
1579
|
}
|
|
1886
1580
|
/**
|
|
1887
|
-
*
|
|
1888
|
-
* Space
|
|
1581
|
+
* (Protected) Gets the iterator for the tree (default in-order).
|
|
1582
|
+
* @remarks Time O(N) for full iteration. O(H) to get the first element. Space O(H) for the iterative stack. O(H) for recursive stack.
|
|
1889
1583
|
*
|
|
1890
|
-
*
|
|
1891
|
-
*
|
|
1892
|
-
* @param node - The `node` parameter in the `_getIterator` method represents the current node being
|
|
1893
|
-
* processed during iteration. It is initially set to the root node of the data structure (or the
|
|
1894
|
-
* node passed as an argument), and then it is traversed through the data structure based on the
|
|
1895
|
-
* iteration type specified (`ITER
|
|
1896
|
-
* @returns The `_getIterator` method returns an IterableIterator containing key-value pairs of nodes
|
|
1897
|
-
* in a binary tree structure. The method uses an iterative approach to traverse the tree based on
|
|
1898
|
-
* the `iterationType` property. If the `iterationType` is set to 'ITERATIVE', the method uses a
|
|
1899
|
-
* stack to perform an in-order traversal of the tree. If the `iterationType` is not 'ITERATIVE
|
|
1584
|
+
* @param [node=this._root] - The node to start iteration from.
|
|
1585
|
+
* @returns An iterator for [key, value] pairs.
|
|
1900
1586
|
*/
|
|
1901
1587
|
*_getIterator(node = this._root) {
|
|
1902
1588
|
if (!node)
|
|
@@ -1905,21 +1591,25 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1905
1591
|
const stack = [];
|
|
1906
1592
|
let current = node;
|
|
1907
1593
|
while (current || stack.length > 0) {
|
|
1594
|
+
// Go to the leftmost node
|
|
1908
1595
|
while (this.isRealNode(current)) {
|
|
1909
1596
|
stack.push(current);
|
|
1910
1597
|
current = current.left;
|
|
1911
1598
|
}
|
|
1599
|
+
// Visit the node
|
|
1912
1600
|
current = stack.pop();
|
|
1913
1601
|
if (this.isRealNode(current)) {
|
|
1914
1602
|
if (this._isMapMode)
|
|
1915
1603
|
yield [current.key, this._store.get(current.key)];
|
|
1916
1604
|
else
|
|
1917
1605
|
yield [current.key, current.value];
|
|
1606
|
+
// Move to the right subtree
|
|
1918
1607
|
current = current.right;
|
|
1919
1608
|
}
|
|
1920
1609
|
}
|
|
1921
1610
|
}
|
|
1922
1611
|
else {
|
|
1612
|
+
// Recursive in-order traversal
|
|
1923
1613
|
if (node.left && this.isRealNode(node)) {
|
|
1924
1614
|
yield* this[Symbol.iterator](node.left);
|
|
1925
1615
|
}
|
|
@@ -1933,24 +1623,104 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1933
1623
|
}
|
|
1934
1624
|
}
|
|
1935
1625
|
/**
|
|
1936
|
-
*
|
|
1937
|
-
*
|
|
1626
|
+
* (Protected) Snapshots the current tree's configuration options.
|
|
1627
|
+
* @remarks Time O(1)
|
|
1628
|
+
*
|
|
1629
|
+
* @template TK, TV, TR - Generic types for the options.
|
|
1630
|
+
* @returns The options object.
|
|
1631
|
+
*/
|
|
1632
|
+
_snapshotOptions() {
|
|
1633
|
+
return {
|
|
1634
|
+
iterationType: this.iterationType,
|
|
1635
|
+
toEntryFn: this.toEntryFn,
|
|
1636
|
+
isMapMode: this.isMapMode,
|
|
1637
|
+
isDuplicate: this.isDuplicate
|
|
1638
|
+
};
|
|
1639
|
+
}
|
|
1640
|
+
/**
|
|
1641
|
+
* (Protected) Creates a new, empty instance of the same tree constructor.
|
|
1642
|
+
* @remarks Time O(1)
|
|
1643
|
+
*
|
|
1644
|
+
* @template TK, TV, TR - Generic types for the new instance.
|
|
1645
|
+
* @param [options] - Options for the new tree.
|
|
1646
|
+
* @returns A new, empty tree.
|
|
1647
|
+
*/
|
|
1648
|
+
_createInstance(options) {
|
|
1649
|
+
const Ctor = this.constructor;
|
|
1650
|
+
return new Ctor([], Object.assign(Object.assign({}, this._snapshotOptions()), (options !== null && options !== void 0 ? options : {})));
|
|
1651
|
+
}
|
|
1652
|
+
/**
|
|
1653
|
+
* (Protected) Creates a new instance of the same tree constructor, potentially with different generic types.
|
|
1654
|
+
* @remarks Time O(N) (or as per constructor) due to processing the iterable.
|
|
1938
1655
|
*
|
|
1939
|
-
*
|
|
1940
|
-
*
|
|
1941
|
-
* @param
|
|
1942
|
-
*
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1656
|
+
* @template TK, TV, TR - Generic types for the new instance.
|
|
1657
|
+
* @param [iter=[]] - An iterable to populate the new tree.
|
|
1658
|
+
* @param [options] - Options for the new tree.
|
|
1659
|
+
* @returns A new tree.
|
|
1660
|
+
*/
|
|
1661
|
+
_createLike(iter = [], options) {
|
|
1662
|
+
const Ctor = this.constructor;
|
|
1663
|
+
return new Ctor(iter, Object.assign(Object.assign({}, this._snapshotOptions()), (options !== null && options !== void 0 ? options : {})));
|
|
1664
|
+
}
|
|
1665
|
+
/**
|
|
1666
|
+
* (Protected) Converts a key, node, or entry into a standardized [node, value] tuple.
|
|
1667
|
+
* @remarks Time O(1)
|
|
1668
|
+
*
|
|
1669
|
+
* @param keyNodeOrEntry - The input item.
|
|
1670
|
+
* @param [value] - An optional value (used if input is just a key).
|
|
1671
|
+
* @returns A tuple of [node, value].
|
|
1672
|
+
*/
|
|
1673
|
+
_keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value) {
|
|
1674
|
+
if (keyNodeOrEntry === undefined)
|
|
1675
|
+
return [undefined, undefined];
|
|
1676
|
+
if (keyNodeOrEntry === null)
|
|
1677
|
+
return [null, undefined];
|
|
1678
|
+
if (this.isNode(keyNodeOrEntry))
|
|
1679
|
+
return [keyNodeOrEntry, value];
|
|
1680
|
+
if (this.isEntry(keyNodeOrEntry)) {
|
|
1681
|
+
const [key, entryValue] = keyNodeOrEntry;
|
|
1682
|
+
if (key === undefined)
|
|
1683
|
+
return [undefined, undefined];
|
|
1684
|
+
else if (key === null)
|
|
1685
|
+
return [null, undefined];
|
|
1686
|
+
const finalValue = value !== null && value !== void 0 ? value : entryValue;
|
|
1687
|
+
return [this._createNode(key, finalValue), finalValue];
|
|
1688
|
+
}
|
|
1689
|
+
return [this._createNode(keyNodeOrEntry, value), value];
|
|
1690
|
+
}
|
|
1691
|
+
/**
|
|
1692
|
+
* (Protected) Helper for cloning. Performs a BFS and adds all nodes to the new tree.
|
|
1693
|
+
* @remarks Time O(N * M) (O(N) BFS + O(M) `add` for each node).
|
|
1694
|
+
*
|
|
1695
|
+
* @param cloned - The new, empty tree instance to populate.
|
|
1696
|
+
*/
|
|
1697
|
+
_clone(cloned) {
|
|
1698
|
+
// Use BFS with nulls to preserve the tree structure
|
|
1699
|
+
this.bfs(node => {
|
|
1700
|
+
if (node === null)
|
|
1701
|
+
cloned.add(null);
|
|
1702
|
+
else {
|
|
1703
|
+
if (this._isMapMode)
|
|
1704
|
+
cloned.add([node.key, this._store.get(node.key)]);
|
|
1705
|
+
else
|
|
1706
|
+
cloned.add([node.key, node.value]);
|
|
1707
|
+
}
|
|
1708
|
+
}, this._root, this.iterationType, true // Include nulls
|
|
1709
|
+
);
|
|
1710
|
+
if (this._isMapMode)
|
|
1711
|
+
cloned._store = this._store;
|
|
1712
|
+
}
|
|
1713
|
+
/**
|
|
1714
|
+
* (Protected) Recursive helper for `toVisual`.
|
|
1715
|
+
* @remarks Time O(N), Space O(N*H) or O(N^2)
|
|
1716
|
+
*
|
|
1717
|
+
* @param node - The current node.
|
|
1718
|
+
* @param options - Print options.
|
|
1719
|
+
* @returns Layout information for this subtree.
|
|
1949
1720
|
*/
|
|
1950
1721
|
_displayAux(node, options) {
|
|
1951
1722
|
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
1952
|
-
const emptyDisplayLayout = [['─'], 1, 0, 0];
|
|
1953
|
-
// Check if node is null or undefined or key is NaN
|
|
1723
|
+
const emptyDisplayLayout = [['─'], 1, 0, 0]; // Represents an empty spot
|
|
1954
1724
|
if (node === null && !isShowNull) {
|
|
1955
1725
|
return emptyDisplayLayout;
|
|
1956
1726
|
}
|
|
@@ -1961,15 +1731,20 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
1961
1731
|
return emptyDisplayLayout;
|
|
1962
1732
|
}
|
|
1963
1733
|
else if (node !== null && node !== undefined) {
|
|
1964
|
-
//
|
|
1734
|
+
// Real node
|
|
1965
1735
|
const key = node.key, line = this.isNIL(node) ? 'S' : String(key), width = line.length;
|
|
1966
1736
|
return _buildNodeDisplay(line, width, this._displayAux(node.left, options), this._displayAux(node.right, options));
|
|
1967
1737
|
}
|
|
1968
1738
|
else {
|
|
1969
|
-
//
|
|
1739
|
+
// Null or Undefined
|
|
1970
1740
|
const line = node === undefined ? 'U' : 'N', width = line.length;
|
|
1741
|
+
// Treat as a leaf
|
|
1971
1742
|
return _buildNodeDisplay(line, width, [[''], 1, 0, 0], [[''], 1, 0, 0]);
|
|
1972
1743
|
}
|
|
1744
|
+
/**
|
|
1745
|
+
* (Inner) Builds the display lines for a node.
|
|
1746
|
+
* @remarks Time/Space: Proportional to the width and height of the subtrees.
|
|
1747
|
+
*/
|
|
1973
1748
|
function _buildNodeDisplay(line, width, left, right) {
|
|
1974
1749
|
const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
|
|
1975
1750
|
const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
|
|
@@ -2000,30 +1775,25 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
2000
1775
|
}
|
|
2001
1776
|
}
|
|
2002
1777
|
/**
|
|
2003
|
-
*
|
|
2004
|
-
*
|
|
1778
|
+
* (Protected) Swaps the key/value properties of two nodes.
|
|
1779
|
+
* @remarks Time O(1)
|
|
2005
1780
|
*
|
|
2006
|
-
*
|
|
2007
|
-
* @param
|
|
2008
|
-
* `
|
|
2009
|
-
* properties, or it can be of type R.
|
|
2010
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } destNode - The `destNode` parameter in the
|
|
2011
|
-
* `_swapProperties` method represents the node or entry where the properties will be swapped with
|
|
2012
|
-
* the `srcNode`. It can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. The method ensures that
|
|
2013
|
-
* both `srcNode
|
|
2014
|
-
* @returns The `_swapProperties` method returns either the `destNode` with its key and value swapped
|
|
2015
|
-
* with the `srcNode`, or `undefined` if either `srcNode` or `destNode` is falsy.
|
|
1781
|
+
* @param srcNode - The source node.
|
|
1782
|
+
* @param destNode - The destination node.
|
|
1783
|
+
* @returns The `destNode` (now holding `srcNode`'s properties).
|
|
2016
1784
|
*/
|
|
2017
1785
|
_swapProperties(srcNode, destNode) {
|
|
2018
1786
|
srcNode = this.ensureNode(srcNode);
|
|
2019
1787
|
destNode = this.ensureNode(destNode);
|
|
2020
1788
|
if (srcNode && destNode) {
|
|
2021
1789
|
const { key, value } = destNode;
|
|
2022
|
-
const tempNode = this.
|
|
1790
|
+
const tempNode = this._createNode(key, value); // Use a temp node to hold dest properties
|
|
2023
1791
|
if (tempNode) {
|
|
1792
|
+
// Copy src to dest
|
|
2024
1793
|
destNode.key = srcNode.key;
|
|
2025
1794
|
if (!this._isMapMode)
|
|
2026
1795
|
destNode.value = srcNode.value;
|
|
1796
|
+
// Copy temp (original dest) to src
|
|
2027
1797
|
srcNode.key = tempNode.key;
|
|
2028
1798
|
if (!this._isMapMode)
|
|
2029
1799
|
srcNode.value = tempNode.value;
|
|
@@ -2033,18 +1803,12 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
2033
1803
|
return undefined;
|
|
2034
1804
|
}
|
|
2035
1805
|
/**
|
|
2036
|
-
*
|
|
2037
|
-
*
|
|
1806
|
+
* (Protected) Replaces a node in the tree with a new node, maintaining children and parent links.
|
|
1807
|
+
* @remarks Time O(1)
|
|
2038
1808
|
*
|
|
2039
|
-
*
|
|
2040
|
-
* @param
|
|
2041
|
-
*
|
|
2042
|
-
* @param {BinaryTreeNode<K, V>} newNode - The `newNode` parameter in the `_replaceNode` function represents the node
|
|
2043
|
-
* that will replace the `oldNode` in a tree data structure. This function is responsible for
|
|
2044
|
-
* updating the parent, left child, right child, and root (if necessary) references when replacing a
|
|
2045
|
-
* node in the tree.
|
|
2046
|
-
* @returns The method `_replaceNode` is returning the `newNode` that was passed as a parameter after
|
|
2047
|
-
* replacing the `oldNode` with it in the binary tree structure.
|
|
1809
|
+
* @param oldNode - The node to be replaced.
|
|
1810
|
+
* @param newNode - The node to insert.
|
|
1811
|
+
* @returns The `newNode`.
|
|
2048
1812
|
*/
|
|
2049
1813
|
_replaceNode(oldNode, newNode) {
|
|
2050
1814
|
if (oldNode.parent) {
|
|
@@ -2064,13 +1828,10 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
2064
1828
|
return newNode;
|
|
2065
1829
|
}
|
|
2066
1830
|
/**
|
|
2067
|
-
*
|
|
2068
|
-
*
|
|
1831
|
+
* (Protected) Sets the root node and clears its parent reference.
|
|
1832
|
+
* @remarks Time O(1)
|
|
2069
1833
|
*
|
|
2070
|
-
*
|
|
2071
|
-
* of the previous root node.
|
|
2072
|
-
* @param v - The parameter `v` in the `_setRoot` method is of type `BinaryTreeNode<K, V> | null | undefined`, which means
|
|
2073
|
-
* it can either be an optional `BinaryTreeNode<K, V>` type or `null`.
|
|
1834
|
+
* @param v - The node to set as root.
|
|
2074
1835
|
*/
|
|
2075
1836
|
_setRoot(v) {
|
|
2076
1837
|
if (v) {
|
|
@@ -2078,18 +1839,6 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
2078
1839
|
}
|
|
2079
1840
|
this._root = v;
|
|
2080
1841
|
}
|
|
2081
|
-
/**
|
|
2082
|
-
* Time Complexity: O(1)
|
|
2083
|
-
* Space Complexity: O(1)
|
|
2084
|
-
*
|
|
2085
|
-
* The function `_ensurePredicate` in TypeScript ensures that the input is converted into a valid
|
|
2086
|
-
* predicate function for a binary tree node.
|
|
2087
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The
|
|
2088
|
-
* `_ensurePredicate` method in the provided code snippet is responsible for ensuring that the input
|
|
2089
|
-
* parameter `keyNodeEntryOrPredicate` is transformed into a valid predicate function that can be
|
|
2090
|
-
* used for filtering nodes in a binary tree.
|
|
2091
|
-
* @returns A NodePredicate<BinaryTreeNode<K, V>> function is being returned.
|
|
2092
|
-
*/
|
|
2093
1842
|
_ensurePredicate(keyNodeEntryOrPredicate) {
|
|
2094
1843
|
if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined)
|
|
2095
1844
|
return (node) => (node ? false : false);
|
|
@@ -2105,6 +1854,7 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
2105
1854
|
return node.key === key;
|
|
2106
1855
|
};
|
|
2107
1856
|
}
|
|
1857
|
+
// Assume it's a key
|
|
2108
1858
|
return (node) => {
|
|
2109
1859
|
if (!node)
|
|
2110
1860
|
return false;
|
|
@@ -2112,32 +1862,21 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
2112
1862
|
};
|
|
2113
1863
|
}
|
|
2114
1864
|
/**
|
|
2115
|
-
*
|
|
2116
|
-
*
|
|
1865
|
+
* (Protected) Checks if an item is a predicate function.
|
|
1866
|
+
* @remarks Time O(1)
|
|
2117
1867
|
*
|
|
2118
|
-
*
|
|
2119
|
-
* @
|
|
2120
|
-
* of value. In this context, the function `_isPredicate` is checking if `p` is a function that
|
|
2121
|
-
* satisfies the type `NodePredicate<BinaryTreeNode<K, V>>`.
|
|
2122
|
-
* @returns The function is checking if the input `p` is a function and returning a boolean value
|
|
2123
|
-
* based on that check. If `p` is a function, it will return `true`, indicating that `p` is a
|
|
2124
|
-
* predicate function for a binary tree node. If `p` is not a function, it will return `false`.
|
|
1868
|
+
* @param p - The item to check.
|
|
1869
|
+
* @returns True if it's a function.
|
|
2125
1870
|
*/
|
|
2126
1871
|
_isPredicate(p) {
|
|
2127
1872
|
return typeof p === 'function';
|
|
2128
1873
|
}
|
|
2129
1874
|
/**
|
|
2130
|
-
*
|
|
2131
|
-
*
|
|
1875
|
+
* (Protected) Extracts the key from a key, node, or entry.
|
|
1876
|
+
* @remarks Time O(1)
|
|
2132
1877
|
*
|
|
2133
|
-
*
|
|
2134
|
-
*
|
|
2135
|
-
* @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `_extractKey` method you provided is a
|
|
2136
|
-
* TypeScript method that takes in a parameter `keyNodeOrEntry` of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `,
|
|
2137
|
-
* where `BTNRep` is a generic type with keys `K`, `V`, and `BinaryTreeNode<K, V>`, and `
|
|
2138
|
-
* @returns The `_extractKey` method returns the key value extracted from the `keyNodeOrEntry`
|
|
2139
|
-
* parameter. The return value can be a key value of type `K`, `null`, or `undefined`, depending on
|
|
2140
|
-
* the conditions checked in the method.
|
|
1878
|
+
* @param keyNodeOrEntry - The item.
|
|
1879
|
+
* @returns The extracted key.
|
|
2141
1880
|
*/
|
|
2142
1881
|
_extractKey(keyNodeOrEntry) {
|
|
2143
1882
|
if (keyNodeOrEntry === null)
|
|
@@ -2153,41 +1892,31 @@ class BinaryTree extends base_1.IterableEntryBase {
|
|
|
2153
1892
|
return keyNodeOrEntry;
|
|
2154
1893
|
}
|
|
2155
1894
|
/**
|
|
2156
|
-
*
|
|
2157
|
-
*
|
|
1895
|
+
* (Protected) Sets a value in the external store (Map mode).
|
|
1896
|
+
* @remarks Time O(1) (average for Map.set).
|
|
2158
1897
|
*
|
|
2159
|
-
*
|
|
2160
|
-
* value
|
|
2161
|
-
* @
|
|
2162
|
-
* `undefined`.
|
|
2163
|
-
* @param {V | undefined} value - The `value` parameter in the `_setValue` method can be of type `V`
|
|
2164
|
-
* or `undefined`.
|
|
2165
|
-
* @returns The method `_setValue` returns `false` if either the `key` is `null` or `undefined`, or
|
|
2166
|
-
* if the `value` is `undefined`. Otherwise, it returns the result of calling the `set` method on the
|
|
2167
|
-
* `_store` object with the `key` and `value` arguments.
|
|
1898
|
+
* @param key - The key.
|
|
1899
|
+
* @param value - The value.
|
|
1900
|
+
* @returns True if successful.
|
|
2168
1901
|
*/
|
|
2169
1902
|
_setValue(key, value) {
|
|
2170
1903
|
if (key === null || key === undefined)
|
|
2171
1904
|
return false;
|
|
2172
1905
|
if (value === undefined)
|
|
2173
|
-
return false;
|
|
1906
|
+
return false; // Or allow setting undefined?
|
|
2174
1907
|
return this._store.set(key, value);
|
|
2175
1908
|
}
|
|
2176
1909
|
/**
|
|
2177
|
-
*
|
|
2178
|
-
*
|
|
2179
|
-
*
|
|
2180
|
-
* The _clearNodes function sets the root node to undefined and resets the size to 0.
|
|
1910
|
+
* (Protected) Clears all nodes from the tree.
|
|
1911
|
+
* @remarks Time O(1)
|
|
2181
1912
|
*/
|
|
2182
1913
|
_clearNodes() {
|
|
2183
1914
|
this._setRoot(undefined);
|
|
2184
1915
|
this._size = 0;
|
|
2185
1916
|
}
|
|
2186
1917
|
/**
|
|
2187
|
-
*
|
|
2188
|
-
*
|
|
2189
|
-
*
|
|
2190
|
-
* The _clearValues function clears all values stored in the _store object.
|
|
1918
|
+
* (Protected) Clears all values from the external store.
|
|
1919
|
+
* @remarks Time O(N)
|
|
2191
1920
|
*/
|
|
2192
1921
|
_clearValues() {
|
|
2193
1922
|
this._store.clear();
|