directed-graph-typed 1.48.0 → 1.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data-structures/base/index.d.ts +1 -0
- package/dist/data-structures/base/index.js +17 -0
- package/dist/data-structures/base/iterable-base.d.ts +232 -0
- package/dist/data-structures/base/iterable-base.js +312 -0
- package/dist/data-structures/binary-tree/avl-tree.d.ts +28 -19
- package/dist/data-structures/binary-tree/avl-tree.js +22 -11
- package/dist/data-structures/binary-tree/binary-tree.d.ts +158 -152
- package/dist/data-structures/binary-tree/binary-tree.js +241 -215
- package/dist/data-structures/binary-tree/bst.d.ts +64 -48
- package/dist/data-structures/binary-tree/bst.js +94 -65
- package/dist/data-structures/binary-tree/rb-tree.d.ts +39 -39
- package/dist/data-structures/binary-tree/rb-tree.js +42 -49
- package/dist/data-structures/binary-tree/tree-multimap.d.ts +60 -34
- package/dist/data-structures/binary-tree/tree-multimap.js +59 -27
- package/dist/data-structures/graph/abstract-graph.d.ts +92 -53
- package/dist/data-structures/graph/abstract-graph.js +130 -103
- package/dist/data-structures/graph/directed-graph.d.ts +70 -52
- package/dist/data-structures/graph/directed-graph.js +111 -65
- package/dist/data-structures/graph/map-graph.d.ts +5 -5
- package/dist/data-structures/graph/map-graph.js +8 -8
- package/dist/data-structures/graph/undirected-graph.d.ts +51 -32
- package/dist/data-structures/graph/undirected-graph.js +117 -54
- package/dist/data-structures/hash/hash-map.d.ts +160 -44
- package/dist/data-structures/hash/hash-map.js +314 -82
- package/dist/data-structures/heap/heap.d.ts +50 -7
- package/dist/data-structures/heap/heap.js +60 -30
- package/dist/data-structures/index.d.ts +1 -0
- package/dist/data-structures/index.js +1 -0
- package/dist/data-structures/linked-list/doubly-linked-list.d.ts +42 -55
- package/dist/data-structures/linked-list/doubly-linked-list.js +50 -77
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +36 -55
- package/dist/data-structures/linked-list/singly-linked-list.js +44 -77
- package/dist/data-structures/queue/deque.d.ts +35 -167
- package/dist/data-structures/queue/deque.js +43 -249
- package/dist/data-structures/queue/queue.d.ts +49 -48
- package/dist/data-structures/queue/queue.js +69 -82
- package/dist/data-structures/stack/stack.d.ts +43 -10
- package/dist/data-structures/stack/stack.js +50 -31
- package/dist/data-structures/trie/trie.d.ts +41 -6
- package/dist/data-structures/trie/trie.js +53 -32
- package/dist/interfaces/binary-tree.d.ts +6 -6
- package/dist/types/common.d.ts +11 -8
- package/dist/types/common.js +6 -1
- package/dist/types/data-structures/base/base.d.ts +5 -0
- package/dist/types/data-structures/base/base.js +2 -0
- package/dist/types/data-structures/base/index.d.ts +1 -0
- package/dist/types/data-structures/base/index.js +17 -0
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +3 -3
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +4 -4
- package/dist/types/data-structures/binary-tree/bst.d.ts +6 -6
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +3 -3
- package/dist/types/data-structures/binary-tree/tree-multimap.d.ts +3 -3
- package/dist/types/data-structures/hash/hash-map.d.ts +4 -0
- package/dist/types/data-structures/index.d.ts +1 -0
- package/dist/types/data-structures/index.js +1 -0
- package/package.json +2 -2
- package/src/data-structures/base/index.ts +1 -0
- package/src/data-structures/base/iterable-base.ts +329 -0
- package/src/data-structures/binary-tree/avl-tree.ts +37 -25
- package/src/data-structures/binary-tree/binary-tree.ts +336 -296
- package/src/data-structures/binary-tree/bst.ts +135 -89
- package/src/data-structures/binary-tree/rb-tree.ts +60 -69
- package/src/data-structures/binary-tree/tree-multimap.ts +86 -49
- package/src/data-structures/graph/abstract-graph.ts +136 -104
- package/src/data-structures/graph/directed-graph.ts +114 -65
- package/src/data-structures/graph/map-graph.ts +8 -8
- package/src/data-structures/graph/undirected-graph.ts +124 -56
- package/src/data-structures/hash/hash-map.ts +335 -84
- package/src/data-structures/heap/heap.ts +63 -36
- package/src/data-structures/index.ts +1 -0
- package/src/data-structures/linked-list/doubly-linked-list.ts +54 -83
- package/src/data-structures/linked-list/singly-linked-list.ts +49 -84
- package/src/data-structures/queue/deque.ts +43 -275
- package/src/data-structures/queue/queue.ts +71 -86
- package/src/data-structures/stack/stack.ts +53 -34
- package/src/data-structures/trie/trie.ts +58 -35
- package/src/interfaces/binary-tree.ts +5 -6
- package/src/types/common.ts +11 -8
- package/src/types/data-structures/base/base.ts +6 -0
- package/src/types/data-structures/base/index.ts +1 -0
- package/src/types/data-structures/binary-tree/avl-tree.ts +3 -3
- package/src/types/data-structures/binary-tree/binary-tree.ts +6 -5
- package/src/types/data-structures/binary-tree/bst.ts +6 -6
- package/src/types/data-structures/binary-tree/rb-tree.ts +3 -3
- package/src/types/data-structures/binary-tree/tree-multimap.ts +3 -3
- package/src/types/data-structures/hash/hash-map.ts +2 -0
- package/src/types/data-structures/heap/heap.ts +1 -1
- package/src/types/data-structures/index.ts +1 -0
- package/src/types/data-structures/priority-queue/priority-queue.ts +1 -1
|
@@ -10,16 +10,16 @@ import type {
|
|
|
10
10
|
BinaryTreeNodeNested,
|
|
11
11
|
BinaryTreeOptions,
|
|
12
12
|
BTNCallback,
|
|
13
|
-
BTNKey,
|
|
14
13
|
BTNodeEntry,
|
|
15
14
|
BTNodeExemplar,
|
|
16
|
-
BTNodeKeyOrNode
|
|
15
|
+
BTNodeKeyOrNode,
|
|
17
16
|
} from '../../types';
|
|
18
17
|
import {
|
|
19
18
|
BinaryTreeNested,
|
|
20
19
|
BinaryTreePrintOptions,
|
|
21
20
|
BiTreeDeleteResult,
|
|
22
21
|
DFSOrderPattern,
|
|
22
|
+
EntryCallback,
|
|
23
23
|
FamilyPosition,
|
|
24
24
|
IterationType,
|
|
25
25
|
NodeDisplayLayout
|
|
@@ -27,20 +27,21 @@ import {
|
|
|
27
27
|
import { IBinaryTree } from '../../interfaces';
|
|
28
28
|
import { trampoline } from '../../utils';
|
|
29
29
|
import { Queue } from '../queue';
|
|
30
|
+
import { IterableEntryBase } from "../base";
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* Represents a node in a binary tree.
|
|
33
34
|
* @template V - The type of data stored in the node.
|
|
34
35
|
* @template N - The type of the family relationship in the binary tree.
|
|
35
36
|
*/
|
|
36
|
-
export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>> {
|
|
37
|
-
key:
|
|
37
|
+
export class BinaryTreeNode<K = any, V = any, N extends BinaryTreeNode<K, V, N> = BinaryTreeNode<K, V, BinaryTreeNodeNested<K, V>>> {
|
|
38
|
+
key: K;
|
|
38
39
|
|
|
39
40
|
value?: V;
|
|
40
41
|
|
|
41
42
|
parent?: N;
|
|
42
43
|
|
|
43
|
-
constructor(key:
|
|
44
|
+
constructor(key: K, value?: V) {
|
|
44
45
|
this.key = key;
|
|
45
46
|
this.value = value;
|
|
46
47
|
}
|
|
@@ -97,14 +98,11 @@ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTree
|
|
|
97
98
|
* 3. Depth and Height: Depth is the number of edges from the root to a node; height is the maximum depth in the tree.
|
|
98
99
|
* 4. Subtrees: Each child of a node forms the root of a subtree.
|
|
99
100
|
* 5. Leaf Nodes: Nodes without children are leaves.
|
|
100
|
-
* 6. Internal Nodes: Nodes with at least one child are internal.
|
|
101
|
-
* 7. Balanced Trees: The heights of the left and right subtrees of any node differ by no more than one.
|
|
102
|
-
* 8. Full Trees: Every node has either 0 or 2 children.
|
|
103
|
-
* 9. Complete Trees: All levels are fully filled except possibly the last, filled from left to right.
|
|
104
101
|
*/
|
|
105
|
-
export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>, TREE extends BinaryTree<V, N, TREE> = BinaryTree<V, N, BinaryTreeNested<V, N>>>
|
|
106
|
-
implements IBinaryTree<V, N, TREE> {
|
|
107
102
|
|
|
103
|
+
export class BinaryTree<K = any, V = any, N extends BinaryTreeNode<K, V, N> = BinaryTreeNode<K, V, BinaryTreeNodeNested<K, V>>, TREE extends BinaryTree<K, V, N, TREE> = BinaryTree<K, V, N, BinaryTreeNested<K, V, N>>> extends IterableEntryBase<K, V | undefined>
|
|
104
|
+
|
|
105
|
+
implements IBinaryTree<K, V, N, TREE> {
|
|
108
106
|
iterationType = IterationType.ITERATIVE
|
|
109
107
|
|
|
110
108
|
/**
|
|
@@ -116,13 +114,16 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
116
114
|
* `Partial<BinaryTreeOptions>`, which means that not all properties of `BinaryTreeOptions` are
|
|
117
115
|
* required.
|
|
118
116
|
*/
|
|
119
|
-
constructor(elements?: Iterable<BTNodeExemplar<V, N>>, options?: Partial<BinaryTreeOptions
|
|
120
|
-
|
|
117
|
+
constructor(elements?: Iterable<BTNodeExemplar<K, V, N>>, options?: Partial<BinaryTreeOptions<K>>) {
|
|
118
|
+
super();
|
|
121
119
|
if (options) {
|
|
122
|
-
const { iterationType } = options;
|
|
120
|
+
const { iterationType, extractor } = options;
|
|
123
121
|
if (iterationType) {
|
|
124
122
|
this.iterationType = iterationType;
|
|
125
123
|
}
|
|
124
|
+
if (extractor) {
|
|
125
|
+
this._extractor = extractor;
|
|
126
|
+
}
|
|
126
127
|
}
|
|
127
128
|
|
|
128
129
|
this._size = 0;
|
|
@@ -130,6 +131,12 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
130
131
|
if (elements) this.addMany(elements);
|
|
131
132
|
}
|
|
132
133
|
|
|
134
|
+
protected _extractor = (key: K) => Number(key)
|
|
135
|
+
|
|
136
|
+
get extractor() {
|
|
137
|
+
return this._extractor;
|
|
138
|
+
}
|
|
139
|
+
|
|
133
140
|
protected _root?: N | null;
|
|
134
141
|
|
|
135
142
|
get root(): N | null | undefined {
|
|
@@ -144,12 +151,12 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
144
151
|
|
|
145
152
|
/**
|
|
146
153
|
* Creates a new instance of BinaryTreeNode with the given key and value.
|
|
147
|
-
* @param {
|
|
154
|
+
* @param {K} key - The key for the new node.
|
|
148
155
|
* @param {V} value - The value for the new node.
|
|
149
156
|
* @returns {N} - The newly created BinaryTreeNode.
|
|
150
157
|
*/
|
|
151
|
-
createNode(key:
|
|
152
|
-
return new BinaryTreeNode<V, N>(key, value) as N;
|
|
158
|
+
createNode(key: K, value?: V): N {
|
|
159
|
+
return new BinaryTreeNode<K, V, N>(key, value) as N;
|
|
153
160
|
}
|
|
154
161
|
|
|
155
162
|
/**
|
|
@@ -159,27 +166,28 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
159
166
|
* you can provide only a subset of the properties defined in the `BinaryTreeOptions` interface.
|
|
160
167
|
* @returns a new instance of a binary tree.
|
|
161
168
|
*/
|
|
162
|
-
createTree(options?: Partial<BinaryTreeOptions
|
|
163
|
-
return new BinaryTree<V, N, TREE>([], { iterationType: this.iterationType, ...options }) as TREE;
|
|
169
|
+
createTree(options?: Partial<BinaryTreeOptions<K>>): TREE {
|
|
170
|
+
return new BinaryTree<K, V, N, TREE>([], { iterationType: this.iterationType, ...options }) as TREE;
|
|
164
171
|
}
|
|
165
172
|
|
|
166
173
|
/**
|
|
167
174
|
* The function "isNode" checks if an exemplar is an instance of the BinaryTreeNode class.
|
|
168
|
-
* @param exemplar - The `exemplar` parameter is a variable of type `BTNodeExemplar<V,
|
|
175
|
+
* @param exemplar - The `exemplar` parameter is a variable of type `BTNodeExemplar<K, V,N>`.
|
|
169
176
|
* @returns a boolean value indicating whether the exemplar is an instance of the class N.
|
|
170
177
|
*/
|
|
171
|
-
isNode(exemplar: BTNodeExemplar<V, N>): exemplar is N {
|
|
178
|
+
isNode(exemplar: BTNodeExemplar<K, V, N>): exemplar is N {
|
|
172
179
|
return exemplar instanceof BinaryTreeNode;
|
|
173
180
|
}
|
|
174
181
|
|
|
175
182
|
/**
|
|
176
|
-
* The function `exemplarToNode` converts an exemplar
|
|
177
|
-
*
|
|
178
|
-
* @param
|
|
179
|
-
* function. It
|
|
180
|
-
*
|
|
183
|
+
* The function `exemplarToNode` converts an exemplar object into a node object.
|
|
184
|
+
* @param exemplar - The `exemplar` parameter is of type `BTNodeExemplar<K, V, N>`.
|
|
185
|
+
* @param {V} [value] - The `value` parameter is an optional value that can be passed to the
|
|
186
|
+
* `exemplarToNode` function. It represents the value associated with the exemplar node. If no value
|
|
187
|
+
* is provided, it will be `undefined`.
|
|
188
|
+
* @returns a value of type N (node), or null, or undefined.
|
|
181
189
|
*/
|
|
182
|
-
exemplarToNode(exemplar: BTNodeExemplar<V, N
|
|
190
|
+
exemplarToNode(exemplar: BTNodeExemplar<K, V, N>, value?: V): N | null | undefined {
|
|
183
191
|
if (exemplar === undefined) return;
|
|
184
192
|
|
|
185
193
|
let node: N | null | undefined;
|
|
@@ -196,8 +204,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
196
204
|
}
|
|
197
205
|
} else if (this.isNode(exemplar)) {
|
|
198
206
|
node = exemplar;
|
|
199
|
-
} else if (this.
|
|
200
|
-
node = this.createNode(exemplar);
|
|
207
|
+
} else if (this.isNotNodeInstance(exemplar)) {
|
|
208
|
+
node = this.createNode(exemplar, value);
|
|
201
209
|
} else {
|
|
202
210
|
return;
|
|
203
211
|
}
|
|
@@ -206,11 +214,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
206
214
|
|
|
207
215
|
/**
|
|
208
216
|
* The function checks if a given value is an entry in a binary tree node.
|
|
209
|
-
* @param kne - BTNodeExemplar<V,
|
|
217
|
+
* @param kne - BTNodeExemplar<K, V,N> - A generic type representing a node in a binary tree. It has
|
|
210
218
|
* two type parameters V and N, representing the value and node type respectively.
|
|
211
219
|
* @returns a boolean value.
|
|
212
220
|
*/
|
|
213
|
-
isEntry(kne: BTNodeExemplar<V, N>): kne is BTNodeEntry<V> {
|
|
221
|
+
isEntry(kne: BTNodeExemplar<K, V, N>): kne is BTNodeEntry<K, V> {
|
|
214
222
|
return Array.isArray(kne) && kne.length === 2;
|
|
215
223
|
}
|
|
216
224
|
|
|
@@ -223,88 +231,116 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
223
231
|
* Time Complexity O(log n) - O(n)
|
|
224
232
|
* Space Complexity O(1)
|
|
225
233
|
*
|
|
226
|
-
* The `add` function adds a new node to a binary tree, either by
|
|
227
|
-
*
|
|
228
|
-
* @
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
const newNode = this.exemplarToNode(keyOrNodeOrEntry);
|
|
234
|
+
* The `add` function adds a new node to a binary tree, either by creating a new node or replacing an
|
|
235
|
+
* existing node with the same key.
|
|
236
|
+
* @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter can be one of the following:
|
|
237
|
+
* @param {V} [value] - The value to be inserted into the binary tree.
|
|
238
|
+
* @returns The function `add` returns either a node (`N`), `null`, or `undefined`.
|
|
239
|
+
*/
|
|
240
|
+
add(keyOrNodeOrEntry: BTNodeExemplar<K, V, N>, value?: V): N | null | undefined {
|
|
241
|
+
const newNode = this.exemplarToNode(keyOrNodeOrEntry, value);
|
|
234
242
|
if (newNode === undefined) return;
|
|
235
243
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
244
|
+
// If the tree is empty, directly set the new node as the root node
|
|
245
|
+
if (!this.root) {
|
|
246
|
+
this._root = newNode;
|
|
247
|
+
this._size = 1;
|
|
248
|
+
return newNode;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const queue = new Queue<N>([this.root]);
|
|
252
|
+
let potentialParent: N | undefined; // Record the parent node of the potential insertion location
|
|
253
|
+
|
|
254
|
+
while (queue.size > 0) {
|
|
255
|
+
const cur = queue.shift();
|
|
256
|
+
|
|
257
|
+
if (!cur) continue;
|
|
258
|
+
|
|
259
|
+
// Check for duplicate keys when newNode is not null
|
|
260
|
+
if (newNode !== null && cur.key === newNode.key) {
|
|
261
|
+
this._replaceNode(cur, newNode);
|
|
262
|
+
return newNode; // If duplicate keys are found, no insertion is performed
|
|
248
263
|
}
|
|
249
|
-
};
|
|
250
264
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
265
|
+
// Record the first possible insertion location found
|
|
266
|
+
if (potentialParent === undefined && (cur.left === undefined || cur.right === undefined)) {
|
|
267
|
+
potentialParent = cur;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Continue traversing the left and right subtrees
|
|
271
|
+
if (cur.left !== null) {
|
|
272
|
+
cur.left && queue.push(cur.left);
|
|
273
|
+
}
|
|
274
|
+
if (cur.right !== null) {
|
|
275
|
+
cur.right && queue.push(cur.right);
|
|
259
276
|
}
|
|
260
|
-
inserted = this.root;
|
|
261
277
|
}
|
|
262
|
-
|
|
278
|
+
|
|
279
|
+
// At the end of the traversal, if the insertion position is found, insert
|
|
280
|
+
if (potentialParent) {
|
|
281
|
+
if (potentialParent.left === undefined) {
|
|
282
|
+
potentialParent.left = newNode;
|
|
283
|
+
} else if (potentialParent.right === undefined) {
|
|
284
|
+
potentialParent.right = newNode;
|
|
285
|
+
}
|
|
286
|
+
this._size++;
|
|
287
|
+
return newNode;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return undefined; // If the insertion position cannot be found, return undefined
|
|
263
291
|
}
|
|
264
292
|
|
|
293
|
+
|
|
265
294
|
/**
|
|
266
295
|
* Time Complexity: O(k log n) - O(k * n)
|
|
267
296
|
* Space Complexity: O(1)
|
|
268
297
|
* Comments: The time complexity for adding a node depends on the depth of the tree. In the best case (when the tree is empty), it's O(1). In the worst case (when the tree is a degenerate tree), it's O(n). The space complexity is constant.
|
|
269
298
|
*/
|
|
270
299
|
|
|
271
|
-
|
|
272
300
|
/**
|
|
273
301
|
* Time Complexity: O(k log n) - O(k * n)
|
|
274
302
|
* Space Complexity: O(1)
|
|
275
303
|
*
|
|
276
|
-
* The
|
|
277
|
-
*
|
|
278
|
-
* @param nodes -
|
|
279
|
-
*
|
|
280
|
-
* @returns The function `addMany` returns an array of
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
addMany(nodes: Iterable<BTNodeExemplar<V, N>>): (N | null | undefined)[] {
|
|
304
|
+
* The `addMany` function takes in a collection of nodes and an optional collection of values, and
|
|
305
|
+
* adds each node with its corresponding value to the data structure.
|
|
306
|
+
* @param nodes - An iterable collection of BTNodeExemplar objects.
|
|
307
|
+
* @param [values] - An optional iterable of values that will be assigned to each node being added.
|
|
308
|
+
* @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values.
|
|
309
|
+
*/
|
|
310
|
+
addMany(nodes: Iterable<BTNodeExemplar<K, V, N>>, values?: Iterable<V | undefined>): (N | null | undefined)[] {
|
|
284
311
|
// TODO not sure addMany not be run multi times
|
|
285
312
|
const inserted: (N | null | undefined)[] = [];
|
|
313
|
+
|
|
314
|
+
let valuesIterator: Iterator<V | undefined> | undefined;
|
|
315
|
+
if (values) {
|
|
316
|
+
valuesIterator = values[Symbol.iterator]();
|
|
317
|
+
}
|
|
318
|
+
|
|
286
319
|
for (const kne of nodes) {
|
|
287
|
-
|
|
320
|
+
let value: V | undefined | null = undefined;
|
|
321
|
+
|
|
322
|
+
if (valuesIterator) {
|
|
323
|
+
const valueResult = valuesIterator.next();
|
|
324
|
+
if (!valueResult.done) {
|
|
325
|
+
value = valueResult.value;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
inserted.push(this.add(kne, value));
|
|
288
330
|
}
|
|
331
|
+
|
|
289
332
|
return inserted;
|
|
290
333
|
}
|
|
291
334
|
|
|
292
|
-
/**
|
|
293
|
-
* Time Complexity: O(k * n) "n" is the number of nodes in the tree, and "k" is the number of keys to be inserted.
|
|
294
|
-
* Space Complexity: O(1)
|
|
295
|
-
*/
|
|
296
335
|
|
|
297
336
|
/**
|
|
298
337
|
* Time Complexity: O(k * n) "n" is the number of nodes in the tree, and "k" is the number of keys to be inserted.
|
|
299
338
|
* Space Complexity: O(1)
|
|
300
|
-
*
|
|
301
|
-
* The `refill` function clears the current collection and adds new nodes, keys, or entries to it.
|
|
302
|
-
* @param nodesOrKeysOrEntries - The parameter `nodesOrKeysOrEntries` is an iterable object that can
|
|
303
|
-
* contain either `BTNodeExemplar` objects, keys, or entries.
|
|
304
339
|
*/
|
|
305
|
-
|
|
340
|
+
|
|
341
|
+
refill(nodesOrKeysOrEntries: Iterable<BTNodeExemplar<K, V, N>>, values?: Iterable<V | undefined>): void {
|
|
306
342
|
this.clear();
|
|
307
|
-
this.addMany(nodesOrKeysOrEntries);
|
|
343
|
+
this.addMany(nodesOrKeysOrEntries, values);
|
|
308
344
|
}
|
|
309
345
|
|
|
310
346
|
/**
|
|
@@ -312,7 +348,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
312
348
|
* Space Complexity: O(1)
|
|
313
349
|
*/
|
|
314
350
|
|
|
315
|
-
delete<C extends BTNCallback<N,
|
|
351
|
+
delete<C extends BTNCallback<N, K>>(identifier: K, callback?: C): BiTreeDeleteResult<N>[];
|
|
316
352
|
|
|
317
353
|
delete<C extends BTNCallback<N, N>>(identifier: N | null | undefined, callback?: C): BiTreeDeleteResult<N>[];
|
|
318
354
|
|
|
@@ -393,15 +429,15 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
393
429
|
* Space Complexity: O(1)
|
|
394
430
|
*
|
|
395
431
|
* The function calculates the depth of a given node in a binary tree.
|
|
396
|
-
* @param {
|
|
397
|
-
* the binary tree whose depth we want to find. It can be of type `
|
|
432
|
+
* @param {K | N | null | undefined} distNode - The `distNode` parameter represents the node in
|
|
433
|
+
* the binary tree whose depth we want to find. It can be of type `K`, `N`, `null`, or
|
|
398
434
|
* `undefined`.
|
|
399
|
-
* @param {
|
|
400
|
-
* from which we want to calculate the depth. It can be either a `
|
|
435
|
+
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node
|
|
436
|
+
* from which we want to calculate the depth. It can be either a `K` (binary tree node key) or
|
|
401
437
|
* `N` (binary tree node) or `null` or `undefined`. If no value is provided for `beginRoot
|
|
402
438
|
* @returns the depth of the `distNode` relative to the `beginRoot`.
|
|
403
439
|
*/
|
|
404
|
-
getDepth(distNode: BTNodeKeyOrNode<N>, beginRoot: BTNodeKeyOrNode<N> = this.root): number {
|
|
440
|
+
getDepth(distNode: BTNodeKeyOrNode<K, N>, beginRoot: BTNodeKeyOrNode<K, N> = this.root): number {
|
|
405
441
|
distNode = this.ensureNode(distNode);
|
|
406
442
|
beginRoot = this.ensureNode(beginRoot);
|
|
407
443
|
let depth = 0;
|
|
@@ -426,15 +462,15 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
426
462
|
*
|
|
427
463
|
* The function `getHeight` calculates the maximum height of a binary tree using either recursive or
|
|
428
464
|
* iterative traversal.
|
|
429
|
-
* @param {
|
|
465
|
+
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
430
466
|
* starting node of the binary tree from which we want to calculate the height. It can be of type
|
|
431
|
-
* `
|
|
467
|
+
* `K`, `N`, `null`, or `undefined`. If not provided, it defaults to `this.root`.
|
|
432
468
|
* @param iterationType - The `iterationType` parameter is used to determine whether to calculate the
|
|
433
469
|
* height of the tree using a recursive approach or an iterative approach. It can have two possible
|
|
434
470
|
* values:
|
|
435
471
|
* @returns the height of the binary tree.
|
|
436
472
|
*/
|
|
437
|
-
getHeight(beginRoot: BTNodeKeyOrNode<N> = this.root, iterationType = this.iterationType): number {
|
|
473
|
+
getHeight(beginRoot: BTNodeKeyOrNode<K, N> = this.root, iterationType = this.iterationType): number {
|
|
438
474
|
beginRoot = this.ensureNode(beginRoot);
|
|
439
475
|
if (!beginRoot) return -1;
|
|
440
476
|
|
|
@@ -476,14 +512,14 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
476
512
|
*
|
|
477
513
|
* The `getMinHeight` function calculates the minimum height of a binary tree using either a
|
|
478
514
|
* recursive or iterative approach.
|
|
479
|
-
* @param {
|
|
515
|
+
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
480
516
|
* starting node of the binary tree from which we want to calculate the minimum height. It can be of
|
|
481
|
-
* type `
|
|
517
|
+
* type `K`, `N`, `null`, or `undefined`. If no value is provided, it defaults to `this.root`.
|
|
482
518
|
* @param iterationType - The `iterationType` parameter is used to determine the method of iteration
|
|
483
519
|
* to calculate the minimum height of a binary tree. It can have two possible values:
|
|
484
520
|
* @returns The function `getMinHeight` returns the minimum height of a binary tree.
|
|
485
521
|
*/
|
|
486
|
-
getMinHeight(beginRoot: BTNodeKeyOrNode<N> = this.root, iterationType = this.iterationType): number {
|
|
522
|
+
getMinHeight(beginRoot: BTNodeKeyOrNode<K, N> = this.root, iterationType = this.iterationType): number {
|
|
487
523
|
beginRoot = this.ensureNode(beginRoot);
|
|
488
524
|
if (!beginRoot) return -1;
|
|
489
525
|
|
|
@@ -538,12 +574,12 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
538
574
|
*
|
|
539
575
|
* The function checks if a binary tree is perfectly balanced by comparing the minimum height and the
|
|
540
576
|
* height of the tree.
|
|
541
|
-
* @param {
|
|
542
|
-
* for calculating the height and minimum height of a binary tree. It can be either a `
|
|
577
|
+
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
|
|
578
|
+
* for calculating the height and minimum height of a binary tree. It can be either a `K` (a key
|
|
543
579
|
* value of a binary tree node), `N` (a node of a binary tree), `null`, or `undefined`. If
|
|
544
580
|
* @returns a boolean value.
|
|
545
581
|
*/
|
|
546
|
-
isPerfectlyBalanced(beginRoot: BTNodeKeyOrNode<N> = this.root): boolean {
|
|
582
|
+
isPerfectlyBalanced(beginRoot: BTNodeKeyOrNode<K, N> = this.root): boolean {
|
|
547
583
|
return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);
|
|
548
584
|
}
|
|
549
585
|
|
|
@@ -552,11 +588,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
552
588
|
* Space Complexity: O(log n)
|
|
553
589
|
*/
|
|
554
590
|
|
|
555
|
-
getNodes<C extends BTNCallback<N,
|
|
556
|
-
identifier:
|
|
591
|
+
getNodes<C extends BTNCallback<N, K>>(
|
|
592
|
+
identifier: K,
|
|
557
593
|
callback?: C,
|
|
558
594
|
onlyOne?: boolean,
|
|
559
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
595
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
560
596
|
iterationType?: IterationType
|
|
561
597
|
): N[];
|
|
562
598
|
|
|
@@ -564,7 +600,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
564
600
|
identifier: N | null | undefined,
|
|
565
601
|
callback?: C,
|
|
566
602
|
onlyOne?: boolean,
|
|
567
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
603
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
568
604
|
iterationType?: IterationType
|
|
569
605
|
): N[];
|
|
570
606
|
|
|
@@ -572,7 +608,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
572
608
|
identifier: ReturnType<C>,
|
|
573
609
|
callback: C,
|
|
574
610
|
onlyOne?: boolean,
|
|
575
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
611
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
576
612
|
iterationType?: IterationType
|
|
577
613
|
): N[];
|
|
578
614
|
|
|
@@ -594,7 +630,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
594
630
|
* matches the identifier. If set to true, the function will stop iterating once it finds a matching
|
|
595
631
|
* node and return that node. If set to false (default), the function will continue iterating and
|
|
596
632
|
* return all nodes that match the identifier.
|
|
597
|
-
* @param {
|
|
633
|
+
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
598
634
|
* starting node for the traversal. It can be either a key, a node object, or `null`/`undefined`. If
|
|
599
635
|
* it is `null` or `undefined`, an empty array will be returned.
|
|
600
636
|
* @param iterationType - The `iterationType` parameter determines the type of iteration used to
|
|
@@ -605,7 +641,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
605
641
|
identifier: ReturnType<C> | null | undefined,
|
|
606
642
|
callback: C = this._defaultOneParamCallback as C,
|
|
607
643
|
onlyOne = false,
|
|
608
|
-
beginRoot: BTNodeKeyOrNode<N> = this.root,
|
|
644
|
+
beginRoot: BTNodeKeyOrNode<K, N> = this.root,
|
|
609
645
|
iterationType = this.iterationType
|
|
610
646
|
): N[] {
|
|
611
647
|
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
@@ -650,24 +686,24 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
650
686
|
* Space Complexity: O(log n).
|
|
651
687
|
*/
|
|
652
688
|
|
|
653
|
-
has<C extends BTNCallback<N,
|
|
654
|
-
identifier:
|
|
689
|
+
has<C extends BTNCallback<N, K>>(
|
|
690
|
+
identifier: K,
|
|
655
691
|
callback?: C,
|
|
656
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
692
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
657
693
|
iterationType?: IterationType
|
|
658
694
|
): boolean;
|
|
659
695
|
|
|
660
696
|
has<C extends BTNCallback<N, N>>(
|
|
661
697
|
identifier: N | null | undefined,
|
|
662
698
|
callback?: C,
|
|
663
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
699
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
664
700
|
iterationType?: IterationType
|
|
665
701
|
): boolean;
|
|
666
702
|
|
|
667
703
|
has<C extends BTNCallback<N>>(
|
|
668
704
|
identifier: ReturnType<C> | null | undefined,
|
|
669
705
|
callback: C,
|
|
670
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
706
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
671
707
|
iterationType?: IterationType
|
|
672
708
|
): boolean;
|
|
673
709
|
|
|
@@ -683,8 +719,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
683
719
|
* the binary tree. It is used to filter the nodes based on certain conditions. The `callback`
|
|
684
720
|
* function should return a boolean value indicating whether the node should be included in the
|
|
685
721
|
* result or not.
|
|
686
|
-
* @param {
|
|
687
|
-
* for the search in the binary tree. It can be specified as a `
|
|
722
|
+
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
|
|
723
|
+
* for the search in the binary tree. It can be specified as a `K` (a unique identifier for a
|
|
688
724
|
* node in the binary tree), a node object (`N`), or `null`/`undefined` to start the search from
|
|
689
725
|
* @param iterationType - The `iterationType` parameter is a variable that determines the type of
|
|
690
726
|
* iteration to be performed on the binary tree. It is used to specify whether the iteration should
|
|
@@ -694,7 +730,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
694
730
|
has<C extends BTNCallback<N>>(
|
|
695
731
|
identifier: ReturnType<C> | null | undefined,
|
|
696
732
|
callback: C = this._defaultOneParamCallback as C,
|
|
697
|
-
beginRoot: BTNodeKeyOrNode<N> = this.root,
|
|
733
|
+
beginRoot: BTNodeKeyOrNode<K, N> = this.root,
|
|
698
734
|
iterationType = this.iterationType
|
|
699
735
|
): boolean {
|
|
700
736
|
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
@@ -708,24 +744,24 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
708
744
|
* Space Complexity: O(log n).
|
|
709
745
|
*/
|
|
710
746
|
|
|
711
|
-
getNode<C extends BTNCallback<N,
|
|
712
|
-
identifier:
|
|
747
|
+
getNode<C extends BTNCallback<N, K>>(
|
|
748
|
+
identifier: K,
|
|
713
749
|
callback?: C,
|
|
714
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
750
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
715
751
|
iterationType?: IterationType
|
|
716
752
|
): N | null | undefined;
|
|
717
753
|
|
|
718
754
|
getNode<C extends BTNCallback<N, N>>(
|
|
719
755
|
identifier: N | null | undefined,
|
|
720
756
|
callback?: C,
|
|
721
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
757
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
722
758
|
iterationType?: IterationType
|
|
723
759
|
): N | null | undefined;
|
|
724
760
|
|
|
725
761
|
getNode<C extends BTNCallback<N>>(
|
|
726
762
|
identifier: ReturnType<C>,
|
|
727
763
|
callback: C,
|
|
728
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
764
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
729
765
|
iterationType?: IterationType
|
|
730
766
|
): N | null | undefined;
|
|
731
767
|
|
|
@@ -742,7 +778,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
742
778
|
* @param {C} callback - The `callback` parameter is a function that will be called for each node in
|
|
743
779
|
* the binary tree. It is used to determine if a node matches the given identifier. The `callback`
|
|
744
780
|
* function should take a single parameter of type `N` (the type of the nodes in the binary tree) and
|
|
745
|
-
* @param {
|
|
781
|
+
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
|
|
746
782
|
* for searching the binary tree. It can be either a key value, a node object, or `null`/`undefined`.
|
|
747
783
|
* If `null` or `undefined` is passed, the search will start from the root of the binary tree.
|
|
748
784
|
* @param iterationType - The `iterationType` parameter is used to specify the type of iteration to
|
|
@@ -753,7 +789,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
753
789
|
getNode<C extends BTNCallback<N>>(
|
|
754
790
|
identifier: ReturnType<C> | null | undefined,
|
|
755
791
|
callback: C = this._defaultOneParamCallback as C,
|
|
756
|
-
beginRoot: BTNodeKeyOrNode<N> = this.root,
|
|
792
|
+
beginRoot: BTNodeKeyOrNode<K, N> = this.root,
|
|
757
793
|
iterationType = this.iterationType
|
|
758
794
|
): N | null | undefined {
|
|
759
795
|
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
@@ -773,7 +809,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
773
809
|
*
|
|
774
810
|
* The function `getNodeByKey` searches for a node in a binary tree by its key, using either
|
|
775
811
|
* recursive or iterative iteration.
|
|
776
|
-
* @param {
|
|
812
|
+
* @param {K} key - The `key` parameter is the key value that we are searching for in the tree.
|
|
777
813
|
* It is used to find the node with the matching key value.
|
|
778
814
|
* @param iterationType - The `iterationType` parameter is used to determine whether the search for
|
|
779
815
|
* the node with the given key should be performed iteratively or recursively. It has two possible
|
|
@@ -781,7 +817,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
781
817
|
* @returns The function `getNodeByKey` returns a node (`N`) if a node with the specified key is
|
|
782
818
|
* found in the binary tree. If no node is found, it returns `undefined`.
|
|
783
819
|
*/
|
|
784
|
-
getNodeByKey(key:
|
|
820
|
+
getNodeByKey(key: K, iterationType = IterationType.ITERATIVE): N | undefined {
|
|
785
821
|
if (!this.root) return undefined;
|
|
786
822
|
if (iterationType === IterationType.RECURSIVE) {
|
|
787
823
|
const _dfs = (cur: N): N | undefined => {
|
|
@@ -814,7 +850,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
814
850
|
/**
|
|
815
851
|
* The function `ensureNode` returns the node corresponding to the given key if it is a valid node
|
|
816
852
|
* key, otherwise it returns the key itself.
|
|
817
|
-
* @param {
|
|
853
|
+
* @param {K | N | null | undefined} key - The `key` parameter can be of type `K`, `N`,
|
|
818
854
|
* `null`, or `undefined`. It represents a key used to identify a node in a binary tree.
|
|
819
855
|
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
|
|
820
856
|
* type of iteration to be used when searching for a node by key. It has a default value of
|
|
@@ -822,28 +858,28 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
822
858
|
* @returns either the node corresponding to the given key if it is a valid node key, or the key
|
|
823
859
|
* itself if it is not a valid node key.
|
|
824
860
|
*/
|
|
825
|
-
ensureNode(key: BTNodeKeyOrNode<N>, iterationType = IterationType.ITERATIVE): N | null | undefined {
|
|
826
|
-
return this.
|
|
861
|
+
ensureNode(key: BTNodeKeyOrNode<K, N>, iterationType = IterationType.ITERATIVE): N | null | undefined {
|
|
862
|
+
return this.isNotNodeInstance(key) ? this.getNodeByKey(key, iterationType) : key;
|
|
827
863
|
}
|
|
828
864
|
|
|
829
|
-
get<C extends BTNCallback<N,
|
|
830
|
-
identifier:
|
|
865
|
+
get<C extends BTNCallback<N, K>>(
|
|
866
|
+
identifier: K,
|
|
831
867
|
callback?: C,
|
|
832
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
868
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
833
869
|
iterationType?: IterationType
|
|
834
870
|
): V | undefined;
|
|
835
871
|
|
|
836
872
|
get<C extends BTNCallback<N, N>>(
|
|
837
873
|
identifier: N | null | undefined,
|
|
838
874
|
callback?: C,
|
|
839
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
875
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
840
876
|
iterationType?: IterationType
|
|
841
877
|
): V | undefined;
|
|
842
878
|
|
|
843
879
|
get<C extends BTNCallback<N>>(
|
|
844
880
|
identifier: ReturnType<C>,
|
|
845
881
|
callback: C,
|
|
846
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
882
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
847
883
|
iterationType?: IterationType
|
|
848
884
|
): V | undefined;
|
|
849
885
|
|
|
@@ -860,8 +896,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
860
896
|
* the binary tree. It is used to determine whether a node matches the given identifier. The callback
|
|
861
897
|
* function should return a value that can be compared to the identifier to determine if it is a
|
|
862
898
|
* match.
|
|
863
|
-
* @param {
|
|
864
|
-
* for the search in the binary tree. It can be specified as a `
|
|
899
|
+
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
|
|
900
|
+
* for the search in the binary tree. It can be specified as a `K` (a unique identifier for a
|
|
865
901
|
* node), a node object of type `N`, or `null`/`undefined` to start the search from the root of
|
|
866
902
|
* @param iterationType - The `iterationType` parameter is used to specify the type of iteration to
|
|
867
903
|
* be performed when searching for a node in the binary tree. It is an optional parameter with a
|
|
@@ -872,7 +908,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
872
908
|
get<C extends BTNCallback<N>>(
|
|
873
909
|
identifier: ReturnType<C> | null | undefined,
|
|
874
910
|
callback: C = this._defaultOneParamCallback as C,
|
|
875
|
-
beginRoot: BTNodeKeyOrNode<N> = this.root,
|
|
911
|
+
beginRoot: BTNodeKeyOrNode<K, N> = this.root,
|
|
876
912
|
iterationType = this.iterationType
|
|
877
913
|
): V | undefined {
|
|
878
914
|
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
@@ -908,15 +944,15 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
908
944
|
*
|
|
909
945
|
* The function `getPathToRoot` returns an array of nodes from a given node to the root of a tree
|
|
910
946
|
* structure, with the option to reverse the order of the nodes.
|
|
911
|
-
* @param {
|
|
912
|
-
* starting node from which you want to find the path to the root. It can be of type `
|
|
947
|
+
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
948
|
+
* starting node from which you want to find the path to the root. It can be of type `K`, `N`,
|
|
913
949
|
* `null`, or `undefined`.
|
|
914
950
|
* @param [isReverse=true] - The `isReverse` parameter is a boolean flag that determines whether the
|
|
915
951
|
* resulting path should be reversed or not. If `isReverse` is set to `true`, the path will be
|
|
916
952
|
* reversed before returning it. If `isReverse` is set to `false`, the path will be returned as is
|
|
917
953
|
* @returns The function `getPathToRoot` returns an array of nodes (`N[]`).
|
|
918
954
|
*/
|
|
919
|
-
getPathToRoot(beginRoot: BTNodeKeyOrNode<N>, isReverse = true): N[] {
|
|
955
|
+
getPathToRoot(beginRoot: BTNodeKeyOrNode<K, N>, isReverse = true): N[] {
|
|
920
956
|
// TODO to support get path through passing key
|
|
921
957
|
const result: N[] = [];
|
|
922
958
|
beginRoot = this.ensureNode(beginRoot);
|
|
@@ -944,8 +980,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
944
980
|
*
|
|
945
981
|
* The function `getLeftMost` returns the leftmost node in a binary tree, either recursively or
|
|
946
982
|
* iteratively.
|
|
947
|
-
* @param {
|
|
948
|
-
* for finding the leftmost node in a binary tree. It can be either a `
|
|
983
|
+
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
|
|
984
|
+
* for finding the leftmost node in a binary tree. It can be either a `K` (a key value), `N` (a
|
|
949
985
|
* node), `null`, or `undefined`. If not provided, it defaults to `this.root`,
|
|
950
986
|
* @param iterationType - The `iterationType` parameter is used to determine the type of iteration to
|
|
951
987
|
* be performed when finding the leftmost node in a binary tree. It can have two possible values:
|
|
@@ -953,7 +989,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
953
989
|
* is no leftmost node, it returns `null` or `undefined` depending on the input.
|
|
954
990
|
*/
|
|
955
991
|
getLeftMost(
|
|
956
|
-
beginRoot: BTNodeKeyOrNode<N> = this.root,
|
|
992
|
+
beginRoot: BTNodeKeyOrNode<K, N> = this.root,
|
|
957
993
|
iterationType = this.iterationType
|
|
958
994
|
): N | null | undefined {
|
|
959
995
|
beginRoot = this.ensureNode(beginRoot);
|
|
@@ -989,8 +1025,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
989
1025
|
*
|
|
990
1026
|
* The function `getRightMost` returns the rightmost node in a binary tree, either recursively or
|
|
991
1027
|
* iteratively.
|
|
992
|
-
* @param {
|
|
993
|
-
* starting node from which we want to find the rightmost node. It can be of type `
|
|
1028
|
+
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
1029
|
+
* starting node from which we want to find the rightmost node. It can be of type `K`, `N`,
|
|
994
1030
|
* `null`, or `undefined`. If not provided, it defaults to `this.root`, which is a property of the
|
|
995
1031
|
* current object.
|
|
996
1032
|
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
|
|
@@ -999,7 +1035,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
999
1035
|
* is no rightmost node, it returns `null` or `undefined`, depending on the input.
|
|
1000
1036
|
*/
|
|
1001
1037
|
getRightMost(
|
|
1002
|
-
beginRoot: BTNodeKeyOrNode<N> = this.root,
|
|
1038
|
+
beginRoot: BTNodeKeyOrNode<K, N> = this.root,
|
|
1003
1039
|
iterationType = this.iterationType
|
|
1004
1040
|
): N | null | undefined {
|
|
1005
1041
|
// TODO support get right most by passing key in
|
|
@@ -1034,23 +1070,24 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1034
1070
|
* Space Complexity: O(1)
|
|
1035
1071
|
*
|
|
1036
1072
|
* The function `isSubtreeBST` checks if a given binary tree is a valid binary search tree.
|
|
1037
|
-
* @param {
|
|
1073
|
+
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the root
|
|
1038
1074
|
* node of the binary search tree (BST) that you want to check if it is a subtree of another BST.
|
|
1039
1075
|
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
|
|
1040
1076
|
* type of iteration to use when checking if a subtree is a binary search tree (BST). It can have two
|
|
1041
1077
|
* possible values:
|
|
1042
1078
|
* @returns a boolean value.
|
|
1043
1079
|
*/
|
|
1044
|
-
isSubtreeBST(beginRoot: BTNodeKeyOrNode<N>, iterationType = this.iterationType): boolean {
|
|
1080
|
+
isSubtreeBST(beginRoot: BTNodeKeyOrNode<K, N>, iterationType = this.iterationType): boolean {
|
|
1045
1081
|
// TODO there is a bug
|
|
1046
1082
|
beginRoot = this.ensureNode(beginRoot);
|
|
1047
1083
|
if (!beginRoot) return true;
|
|
1048
1084
|
|
|
1049
1085
|
if (iterationType === IterationType.RECURSIVE) {
|
|
1050
|
-
const dfs = (cur: N | null | undefined, min:
|
|
1086
|
+
const dfs = (cur: N | null | undefined, min: number, max: number): boolean => {
|
|
1051
1087
|
if (!cur) return true;
|
|
1052
|
-
|
|
1053
|
-
|
|
1088
|
+
const numKey = this.extractor(cur.key);
|
|
1089
|
+
if (numKey <= min || numKey >= max) return false;
|
|
1090
|
+
return dfs(cur.left, min, numKey) && dfs(cur.right, numKey, max);
|
|
1054
1091
|
};
|
|
1055
1092
|
|
|
1056
1093
|
return dfs(beginRoot, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
|
|
@@ -1064,8 +1101,9 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1064
1101
|
curr = curr.left;
|
|
1065
1102
|
}
|
|
1066
1103
|
curr = stack.pop()!;
|
|
1067
|
-
|
|
1068
|
-
prev
|
|
1104
|
+
const numKey = this.extractor(curr.key);
|
|
1105
|
+
if (!curr || prev >= numKey) return false;
|
|
1106
|
+
prev = numKey;
|
|
1069
1107
|
curr = curr.right;
|
|
1070
1108
|
}
|
|
1071
1109
|
return true;
|
|
@@ -1100,21 +1138,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1100
1138
|
|
|
1101
1139
|
subTreeTraverse<C extends BTNCallback<N>>(
|
|
1102
1140
|
callback?: C,
|
|
1103
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
1141
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
1104
1142
|
iterationType?: IterationType,
|
|
1105
1143
|
includeNull?: false
|
|
1106
1144
|
): ReturnType<C>[];
|
|
1107
1145
|
|
|
1108
1146
|
subTreeTraverse<C extends BTNCallback<N>>(
|
|
1109
1147
|
callback?: C,
|
|
1110
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
1148
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
1111
1149
|
iterationType?: IterationType,
|
|
1112
1150
|
includeNull?: undefined
|
|
1113
1151
|
): ReturnType<C>[];
|
|
1114
1152
|
|
|
1115
1153
|
subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
|
|
1116
1154
|
callback?: C,
|
|
1117
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
1155
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
1118
1156
|
iterationType?: IterationType,
|
|
1119
1157
|
includeNull?: true
|
|
1120
1158
|
): ReturnType<C>[];
|
|
@@ -1128,8 +1166,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1128
1166
|
* @param {C} callback - The `callback` parameter is a function that will be called for each node in
|
|
1129
1167
|
* the subtree traversal. It takes a single parameter, which is the current node being traversed, and
|
|
1130
1168
|
* returns a value of any type.
|
|
1131
|
-
* @param {
|
|
1132
|
-
* starting node or key from which the subtree traversal should begin. It can be of type `
|
|
1169
|
+
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
1170
|
+
* starting node or key from which the subtree traversal should begin. It can be of type `K`,
|
|
1133
1171
|
* `N`, `null`, or `undefined`. If not provided, the `root` property of the current object is used as
|
|
1134
1172
|
* the default value.
|
|
1135
1173
|
* @param iterationType - The `iterationType` parameter determines the type of traversal to be
|
|
@@ -1143,7 +1181,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1143
1181
|
*/
|
|
1144
1182
|
subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
|
|
1145
1183
|
callback: C = this._defaultOneParamCallback as C,
|
|
1146
|
-
beginRoot: BTNodeKeyOrNode<N> = this.root,
|
|
1184
|
+
beginRoot: BTNodeKeyOrNode<K, N> = this.root,
|
|
1147
1185
|
iterationType = this.iterationType,
|
|
1148
1186
|
includeNull = false
|
|
1149
1187
|
): ReturnType<C>[] {
|
|
@@ -1198,8 +1236,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1198
1236
|
* @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
|
|
1199
1237
|
* @returns a boolean value.
|
|
1200
1238
|
*/
|
|
1201
|
-
isRealNode(node:
|
|
1202
|
-
return node instanceof BinaryTreeNode && node.key
|
|
1239
|
+
isRealNode(node: BTNodeExemplar<K, V, N>): node is N {
|
|
1240
|
+
return node instanceof BinaryTreeNode && String(node.key) !== 'NaN';
|
|
1203
1241
|
}
|
|
1204
1242
|
|
|
1205
1243
|
/**
|
|
@@ -1207,8 +1245,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1207
1245
|
* @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
|
|
1208
1246
|
* @returns a boolean value.
|
|
1209
1247
|
*/
|
|
1210
|
-
isNIL(node:
|
|
1211
|
-
return node instanceof BinaryTreeNode && node.key
|
|
1248
|
+
isNIL(node: BTNodeExemplar<K, V, N>) {
|
|
1249
|
+
return node instanceof BinaryTreeNode && String(node.key) === 'NaN';
|
|
1212
1250
|
}
|
|
1213
1251
|
|
|
1214
1252
|
/**
|
|
@@ -1216,24 +1254,24 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1216
1254
|
* @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
|
|
1217
1255
|
* @returns a boolean value.
|
|
1218
1256
|
*/
|
|
1219
|
-
isNodeOrNull(node:
|
|
1257
|
+
isNodeOrNull(node: BTNodeExemplar<K, V, N>): node is N | null {
|
|
1220
1258
|
return this.isRealNode(node) || node === null;
|
|
1221
1259
|
}
|
|
1222
1260
|
|
|
1223
1261
|
/**
|
|
1224
|
-
* The function "
|
|
1262
|
+
* The function "isNotNodeInstance" checks if a potential key is a K.
|
|
1225
1263
|
* @param {any} potentialKey - The potentialKey parameter is of type any, which means it can be any
|
|
1226
1264
|
* data type.
|
|
1227
1265
|
* @returns a boolean value indicating whether the potentialKey is of type number or not.
|
|
1228
1266
|
*/
|
|
1229
|
-
|
|
1230
|
-
return
|
|
1267
|
+
isNotNodeInstance(potentialKey: BTNodeKeyOrNode<K, N>): potentialKey is K {
|
|
1268
|
+
return !(potentialKey instanceof BinaryTreeNode)
|
|
1231
1269
|
}
|
|
1232
1270
|
|
|
1233
1271
|
dfs<C extends BTNCallback<N>>(
|
|
1234
1272
|
callback?: C,
|
|
1235
1273
|
pattern?: DFSOrderPattern,
|
|
1236
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
1274
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
1237
1275
|
iterationType?: IterationType,
|
|
1238
1276
|
includeNull?: false
|
|
1239
1277
|
): ReturnType<C>[];
|
|
@@ -1241,7 +1279,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1241
1279
|
dfs<C extends BTNCallback<N>>(
|
|
1242
1280
|
callback?: C,
|
|
1243
1281
|
pattern?: DFSOrderPattern,
|
|
1244
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
1282
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
1245
1283
|
iterationType?: IterationType,
|
|
1246
1284
|
includeNull?: undefined
|
|
1247
1285
|
): ReturnType<C>[];
|
|
@@ -1249,7 +1287,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1249
1287
|
dfs<C extends BTNCallback<N | null | undefined>>(
|
|
1250
1288
|
callback?: C,
|
|
1251
1289
|
pattern?: DFSOrderPattern,
|
|
1252
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
1290
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
1253
1291
|
iterationType?: IterationType,
|
|
1254
1292
|
includeNull?: true
|
|
1255
1293
|
): ReturnType<C>[];
|
|
@@ -1266,7 +1304,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1266
1304
|
* `null`, or `undefined`, and returns a value of any type. The default value for this parameter is
|
|
1267
1305
|
* @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter determines the order in which the
|
|
1268
1306
|
* nodes are traversed during the depth-first search. It can have one of the following values:
|
|
1269
|
-
* @param {
|
|
1307
|
+
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node
|
|
1270
1308
|
* for the depth-first search traversal. It can be specified as a key, a node object, or
|
|
1271
1309
|
* `null`/`undefined`. If not provided, the `beginRoot` will default to the root node of the tree.
|
|
1272
1310
|
* @param {IterationType} iterationType - The `iterationType` parameter determines the type of
|
|
@@ -1280,7 +1318,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1280
1318
|
dfs<C extends BTNCallback<N | null | undefined>>(
|
|
1281
1319
|
callback: C = this._defaultOneParamCallback as C,
|
|
1282
1320
|
pattern: DFSOrderPattern = 'in',
|
|
1283
|
-
beginRoot: BTNodeKeyOrNode<N> = this.root,
|
|
1321
|
+
beginRoot: BTNodeKeyOrNode<K, N> = this.root,
|
|
1284
1322
|
iterationType: IterationType = IterationType.ITERATIVE,
|
|
1285
1323
|
includeNull = false
|
|
1286
1324
|
): ReturnType<C>[] {
|
|
@@ -1379,21 +1417,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1379
1417
|
|
|
1380
1418
|
bfs<C extends BTNCallback<N>>(
|
|
1381
1419
|
callback?: C,
|
|
1382
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
1420
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
1383
1421
|
iterationType?: IterationType,
|
|
1384
1422
|
includeNull?: false
|
|
1385
1423
|
): ReturnType<C>[];
|
|
1386
1424
|
|
|
1387
1425
|
bfs<C extends BTNCallback<N>>(
|
|
1388
1426
|
callback?: C,
|
|
1389
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
1427
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
1390
1428
|
iterationType?: IterationType,
|
|
1391
1429
|
includeNull?: undefined
|
|
1392
1430
|
): ReturnType<C>[];
|
|
1393
1431
|
|
|
1394
1432
|
bfs<C extends BTNCallback<N | null | undefined>>(
|
|
1395
1433
|
callback?: C,
|
|
1396
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
1434
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
1397
1435
|
iterationType?: IterationType,
|
|
1398
1436
|
includeNull?: true
|
|
1399
1437
|
): ReturnType<C>[];
|
|
@@ -1407,7 +1445,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1407
1445
|
* @param {C} callback - The `callback` parameter is a function that will be called for each node in
|
|
1408
1446
|
* the breadth-first search traversal. It takes a single parameter, which is the current node being
|
|
1409
1447
|
* visited, and returns a value of any type.
|
|
1410
|
-
* @param {
|
|
1448
|
+
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
1411
1449
|
* starting node for the breadth-first search traversal. It can be specified as a key, a node object,
|
|
1412
1450
|
* or `null`/`undefined` to indicate the root of the tree. If not provided, the `root` property of
|
|
1413
1451
|
* the class is used as
|
|
@@ -1421,7 +1459,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1421
1459
|
*/
|
|
1422
1460
|
bfs<C extends BTNCallback<N | null | undefined>>(
|
|
1423
1461
|
callback: C = this._defaultOneParamCallback as C,
|
|
1424
|
-
beginRoot: BTNodeKeyOrNode<N> = this.root,
|
|
1462
|
+
beginRoot: BTNodeKeyOrNode<K, N> = this.root,
|
|
1425
1463
|
iterationType = this.iterationType,
|
|
1426
1464
|
includeNull = false
|
|
1427
1465
|
): ReturnType<C>[] {
|
|
@@ -1480,21 +1518,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1480
1518
|
|
|
1481
1519
|
listLevels<C extends BTNCallback<N>>(
|
|
1482
1520
|
callback?: C,
|
|
1483
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
1521
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
1484
1522
|
iterationType?: IterationType,
|
|
1485
1523
|
includeNull?: false
|
|
1486
1524
|
): ReturnType<C>[][];
|
|
1487
1525
|
|
|
1488
1526
|
listLevels<C extends BTNCallback<N>>(
|
|
1489
1527
|
callback?: C,
|
|
1490
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
1528
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
1491
1529
|
iterationType?: IterationType,
|
|
1492
1530
|
includeNull?: undefined
|
|
1493
1531
|
): ReturnType<C>[][];
|
|
1494
1532
|
|
|
1495
1533
|
listLevels<C extends BTNCallback<N | null | undefined>>(
|
|
1496
1534
|
callback?: C,
|
|
1497
|
-
beginRoot?: BTNodeKeyOrNode<N>,
|
|
1535
|
+
beginRoot?: BTNodeKeyOrNode<K, N>,
|
|
1498
1536
|
iterationType?: IterationType,
|
|
1499
1537
|
includeNull?: true
|
|
1500
1538
|
): ReturnType<C>[][];
|
|
@@ -1509,9 +1547,9 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1509
1547
|
* @param {C} callback - The `callback` parameter is a function that will be called for each node in
|
|
1510
1548
|
* the tree. It takes a single parameter, which can be of type `N`, `null`, or `undefined`, and
|
|
1511
1549
|
* returns a value of any type.
|
|
1512
|
-
* @param {
|
|
1550
|
+
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
|
|
1513
1551
|
* starting node for traversing the tree. It can be either a node object (`N`), a key value
|
|
1514
|
-
* (`
|
|
1552
|
+
* (`K`), `null`, or `undefined`. If not provided, it defaults to the root node of the tree.
|
|
1515
1553
|
* @param iterationType - The `iterationType` parameter determines the type of iteration to be
|
|
1516
1554
|
* performed on the tree. It can have two possible values:
|
|
1517
1555
|
* @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines
|
|
@@ -1522,7 +1560,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1522
1560
|
*/
|
|
1523
1561
|
listLevels<C extends BTNCallback<N | null | undefined>>(
|
|
1524
1562
|
callback: C = this._defaultOneParamCallback as C,
|
|
1525
|
-
beginRoot: BTNodeKeyOrNode<N> = this.root,
|
|
1563
|
+
beginRoot: BTNodeKeyOrNode<K, N> = this.root,
|
|
1526
1564
|
iterationType = this.iterationType,
|
|
1527
1565
|
includeNull = false
|
|
1528
1566
|
): ReturnType<C>[][] {
|
|
@@ -1568,26 +1606,24 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1568
1606
|
}
|
|
1569
1607
|
|
|
1570
1608
|
/**
|
|
1571
|
-
* Time
|
|
1572
|
-
* Space
|
|
1609
|
+
* Time Complexity: O(log n)
|
|
1610
|
+
* Space Complexity: O(1)
|
|
1573
1611
|
*/
|
|
1574
1612
|
|
|
1575
|
-
getPredecessor(node: N): N;
|
|
1576
|
-
|
|
1577
1613
|
/**
|
|
1578
|
-
*
|
|
1579
|
-
*
|
|
1580
|
-
*
|
|
1581
|
-
*
|
|
1614
|
+
* Time Complexity: O(log n)
|
|
1615
|
+
* Space Complexity: O(1)
|
|
1616
|
+
*
|
|
1617
|
+
* The function returns the predecessor of a given node in a tree.
|
|
1618
|
+
* @param {N} node - The parameter `node` is of type `RedBlackTreeNode`, which represents a node in a
|
|
1619
|
+
* tree.
|
|
1620
|
+
* @returns the predecessor of the given 'node'.
|
|
1582
1621
|
*/
|
|
1583
|
-
getPredecessor(node:
|
|
1584
|
-
|
|
1585
|
-
if (!this.isRealNode(node)) return undefined;
|
|
1586
|
-
|
|
1587
|
-
if (node.left) {
|
|
1622
|
+
getPredecessor(node: N): N {
|
|
1623
|
+
if (this.isRealNode(node.left)) {
|
|
1588
1624
|
let predecessor: N | null | undefined = node.left;
|
|
1589
1625
|
while (!this.isRealNode(predecessor) || (this.isRealNode(predecessor.right) && predecessor.right !== node)) {
|
|
1590
|
-
if (predecessor) {
|
|
1626
|
+
if (this.isRealNode(predecessor)) {
|
|
1591
1627
|
predecessor = predecessor.right;
|
|
1592
1628
|
}
|
|
1593
1629
|
}
|
|
@@ -1599,20 +1635,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1599
1635
|
|
|
1600
1636
|
/**
|
|
1601
1637
|
* The function `getSuccessor` returns the next node in a binary tree given a current node.
|
|
1602
|
-
* @param {
|
|
1638
|
+
* @param {K | N | null} [x] - The parameter `x` can be of type `K`, `N`, or `null`.
|
|
1603
1639
|
* @returns the successor of the given node or key. The successor is the node that comes immediately
|
|
1604
1640
|
* after the given node in the inorder traversal of the binary tree.
|
|
1605
1641
|
*/
|
|
1606
|
-
getSuccessor(x?:
|
|
1642
|
+
getSuccessor(x?: K | N | null): N | null | undefined {
|
|
1643
|
+
|
|
1607
1644
|
x = this.ensureNode(x);
|
|
1608
|
-
if (!x) return undefined;
|
|
1645
|
+
if (!this.isRealNode(x)) return undefined;
|
|
1609
1646
|
|
|
1610
|
-
if (x.right) {
|
|
1647
|
+
if (this.isRealNode(x.right)) {
|
|
1611
1648
|
return this.getLeftMost(x.right);
|
|
1612
1649
|
}
|
|
1613
1650
|
|
|
1614
1651
|
let y: N | null | undefined = x.parent;
|
|
1615
|
-
while (y &&
|
|
1652
|
+
while (this.isRealNode(y) && x === y.right) {
|
|
1616
1653
|
x = y;
|
|
1617
1654
|
y = y.parent;
|
|
1618
1655
|
}
|
|
@@ -1630,7 +1667,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1630
1667
|
* @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter in the `morris` function
|
|
1631
1668
|
* determines the order in which the nodes of a binary tree are traversed. It can have one of the
|
|
1632
1669
|
* following values:
|
|
1633
|
-
* @param {
|
|
1670
|
+
* @param {K | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node
|
|
1634
1671
|
* for the traversal. It can be specified as a key, a node object, or `null`/`undefined` to indicate
|
|
1635
1672
|
* the root of the tree. If no value is provided, the default value is the root of the tree.
|
|
1636
1673
|
* @returns The function `morris` returns an array of values that are the result of invoking the
|
|
@@ -1640,7 +1677,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1640
1677
|
morris<C extends BTNCallback<N>>(
|
|
1641
1678
|
callback: C = this._defaultOneParamCallback as C,
|
|
1642
1679
|
pattern: DFSOrderPattern = 'in',
|
|
1643
|
-
beginRoot: BTNodeKeyOrNode<N> = this.root
|
|
1680
|
+
beginRoot: BTNodeKeyOrNode<K, N> = this.root
|
|
1644
1681
|
): ReturnType<C>[] {
|
|
1645
1682
|
beginRoot = this.ensureNode(beginRoot);
|
|
1646
1683
|
if (beginRoot === null) return [];
|
|
@@ -1725,33 +1762,48 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1725
1762
|
|
|
1726
1763
|
/**
|
|
1727
1764
|
* Time complexity: O(n)
|
|
1728
|
-
* Space complexity: O(
|
|
1765
|
+
* Space complexity: O(n)
|
|
1729
1766
|
*/
|
|
1730
1767
|
|
|
1731
1768
|
/**
|
|
1732
|
-
*
|
|
1733
|
-
*
|
|
1734
|
-
*
|
|
1735
|
-
*
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1769
|
+
* Time complexity: O(n)
|
|
1770
|
+
* Space complexity: O(n)
|
|
1771
|
+
*
|
|
1772
|
+
* The `clone` function creates a new tree object and copies all the nodes from the original tree to
|
|
1773
|
+
* the new tree.
|
|
1774
|
+
* @returns The `clone()` method is returning a cloned instance of the `TREE` object.
|
|
1775
|
+
*/
|
|
1776
|
+
clone(): TREE {
|
|
1777
|
+
const cloned = this.createTree();
|
|
1778
|
+
this.bfs(node => cloned.add([node.key, node.value]));
|
|
1779
|
+
return cloned;
|
|
1741
1780
|
}
|
|
1742
1781
|
|
|
1743
1782
|
/**
|
|
1744
|
-
*
|
|
1745
|
-
*
|
|
1746
|
-
* @param predicate - The `predicate` parameter is a function that takes two arguments: `entry` and
|
|
1747
|
-
* `tree`.
|
|
1748
|
-
* @returns The `filter` method is returning a new tree object that contains only the entries that
|
|
1749
|
-
* satisfy the given predicate function.
|
|
1783
|
+
* Time Complexity: O(n)
|
|
1784
|
+
* Space Complexity: O(n)
|
|
1750
1785
|
*/
|
|
1751
|
-
|
|
1786
|
+
|
|
1787
|
+
/**
|
|
1788
|
+
* Time Complexity: O(n)
|
|
1789
|
+
* Space Complexity: O(n)
|
|
1790
|
+
*
|
|
1791
|
+
* The `filter` function creates a new tree by iterating over the elements of the current tree and
|
|
1792
|
+
* adding only the elements that satisfy the given predicate function.
|
|
1793
|
+
* @param predicate - The `predicate` parameter is a function that takes three arguments: `value`,
|
|
1794
|
+
* `key`, and `index`. It should return a boolean value indicating whether the pair should be
|
|
1795
|
+
* included in the filtered tree or not.
|
|
1796
|
+
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
|
1797
|
+
* to be used as the `this` value when executing the `predicate` function. If `thisArg` is provided,
|
|
1798
|
+
* it will be passed as the first argument to the `predicate` function. If `thisArg` is
|
|
1799
|
+
* @returns The `filter` method is returning a new tree object that contains the key-value pairs that
|
|
1800
|
+
* pass the given predicate function.
|
|
1801
|
+
*/
|
|
1802
|
+
filter(predicate: EntryCallback<K, V | undefined, boolean>, thisArg?: any) {
|
|
1752
1803
|
const newTree = this.createTree();
|
|
1804
|
+
let index = 0;
|
|
1753
1805
|
for (const [key, value] of this) {
|
|
1754
|
-
if (predicate(
|
|
1806
|
+
if (predicate.call(thisArg, value, key, index++, this)) {
|
|
1755
1807
|
newTree.add([key, value]);
|
|
1756
1808
|
}
|
|
1757
1809
|
}
|
|
@@ -1759,58 +1811,74 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1759
1811
|
}
|
|
1760
1812
|
|
|
1761
1813
|
/**
|
|
1762
|
-
*
|
|
1763
|
-
*
|
|
1764
|
-
|
|
1814
|
+
* Time Complexity: O(n)
|
|
1815
|
+
* Space Complexity: O(n)
|
|
1816
|
+
*/
|
|
1817
|
+
|
|
1818
|
+
/**
|
|
1819
|
+
* Time Complexity: O(n)
|
|
1820
|
+
* Space Complexity: O(n)
|
|
1821
|
+
*
|
|
1822
|
+
* The `map` function creates a new tree by applying a callback function to each key-value pair in
|
|
1823
|
+
* the original tree.
|
|
1824
|
+
* @param callback - The callback parameter is a function that will be called for each key-value pair
|
|
1825
|
+
* in the tree. It takes four arguments: the value of the current pair, the key of the current pair,
|
|
1826
|
+
* the index of the current pair, and a reference to the tree itself. The callback function should
|
|
1827
|
+
* return a new
|
|
1828
|
+
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
|
1829
|
+
* specify the value of `this` within the callback function. If you pass a value for `thisArg`, it
|
|
1830
|
+
* will be used as the `this` value when the callback function is called. If you don't pass a value
|
|
1765
1831
|
* @returns The `map` method is returning a new tree object.
|
|
1766
1832
|
*/
|
|
1767
|
-
map(callback:
|
|
1833
|
+
map(callback: EntryCallback<K, V | undefined, V>, thisArg?: any) {
|
|
1768
1834
|
const newTree = this.createTree();
|
|
1835
|
+
let index = 0;
|
|
1769
1836
|
for (const [key, value] of this) {
|
|
1770
|
-
newTree.add([key, callback(
|
|
1837
|
+
newTree.add([key, callback.call(thisArg, value, key, index++, this)]);
|
|
1771
1838
|
}
|
|
1772
1839
|
return newTree;
|
|
1773
1840
|
}
|
|
1774
1841
|
|
|
1775
|
-
// TODO Type error, need to return a TREE<NV> that is a value type only for callback function.
|
|
1776
|
-
// map<NV>(callback: (entry: [
|
|
1777
|
-
// const newTree = this.createTree();
|
|
1778
|
-
// for (const [key, value] of this) {
|
|
1779
|
-
// newTree.add(key, callback([key, value], this));
|
|
1780
|
-
// }
|
|
1781
|
-
// return newTree;
|
|
1782
|
-
// }
|
|
1783
|
-
|
|
1784
|
-
/**
|
|
1785
|
-
* The `reduce` function iterates over the entries of a tree and applies a callback function to each
|
|
1786
|
-
* entry, accumulating a single value.
|
|
1787
|
-
* @param callback - The callback parameter is a function that takes three arguments: accumulator,
|
|
1788
|
-
* entry, and tree. It is called for each entry in the tree and is used to accumulate a single value
|
|
1789
|
-
* based on the logic defined in the callback function.
|
|
1790
|
-
* @param {T} initialValue - The initialValue parameter is the initial value of the accumulator. It
|
|
1791
|
-
* is the value that will be passed as the first argument to the callback function when reducing the
|
|
1792
|
-
* elements of the tree.
|
|
1793
|
-
* @returns The `reduce` method is returning the final value of the accumulator after iterating over
|
|
1794
|
-
* all the entries in the tree and applying the callback function to each entry.
|
|
1795
|
-
*/
|
|
1796
|
-
reduce<T>(callback: (accumulator: T, entry: [BTNKey, V | undefined], tree: this) => T, initialValue: T): T {
|
|
1797
|
-
let accumulator = initialValue;
|
|
1798
|
-
for (const [key, value] of this) {
|
|
1799
|
-
accumulator = callback(accumulator, [key, value], this);
|
|
1800
|
-
}
|
|
1801
|
-
return accumulator;
|
|
1802
|
-
}
|
|
1842
|
+
// // TODO Type error, need to return a TREE<NV> that is a value type only for callback function.
|
|
1843
|
+
// // map<NV>(callback: (entry: [K, V | undefined], tree: this) => NV) {
|
|
1844
|
+
// // const newTree = this.createTree();
|
|
1845
|
+
// // for (const [key, value] of this) {
|
|
1846
|
+
// // newTree.add(key, callback([key, value], this));
|
|
1847
|
+
// // }
|
|
1848
|
+
// // return newTree;
|
|
1849
|
+
// // }
|
|
1850
|
+
//
|
|
1803
1851
|
|
|
1804
1852
|
/**
|
|
1805
|
-
* The
|
|
1806
|
-
*
|
|
1807
|
-
*
|
|
1808
|
-
*
|
|
1809
|
-
*
|
|
1810
|
-
* @returns The `*[Symbol.iterator]` method returns a generator object that yields the keys of the
|
|
1811
|
-
* binary tree nodes in a specific order.
|
|
1853
|
+
* The `print` function is used to display a binary tree structure in a visually appealing way.
|
|
1854
|
+
* @param {K | N | null | undefined} [beginRoot=this.root] - The `root` parameter is of type `K | N | null |
|
|
1855
|
+
* undefined`. It represents the root node of a binary tree. The root node can have one of the
|
|
1856
|
+
* following types:
|
|
1857
|
+
* @param {BinaryTreePrintOptions} [options={ isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false}] - Options object that controls printing behavior. You can specify whether to display undefined, null, or sentinel nodes.
|
|
1812
1858
|
*/
|
|
1813
|
-
|
|
1859
|
+
print(beginRoot: BTNodeKeyOrNode<K, N> = this.root, options?: BinaryTreePrintOptions): void {
|
|
1860
|
+
const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options };
|
|
1861
|
+
beginRoot = this.ensureNode(beginRoot);
|
|
1862
|
+
if (!beginRoot) return;
|
|
1863
|
+
|
|
1864
|
+
if (opts.isShowUndefined) console.log(`U for undefined
|
|
1865
|
+
`);
|
|
1866
|
+
if (opts.isShowNull) console.log(`N for null
|
|
1867
|
+
`);
|
|
1868
|
+
if (opts.isShowRedBlackNIL) console.log(`S for Sentinel Node
|
|
1869
|
+
`);
|
|
1870
|
+
|
|
1871
|
+
const display = (root: N | null | undefined): void => {
|
|
1872
|
+
const [lines, , ,] = this._displayAux(root, opts);
|
|
1873
|
+
for (const line of lines) {
|
|
1874
|
+
console.log(line);
|
|
1875
|
+
}
|
|
1876
|
+
};
|
|
1877
|
+
|
|
1878
|
+
display(beginRoot);
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
protected* _getIterator(node = this.root): IterableIterator<[K, V | undefined]> {
|
|
1814
1882
|
if (!node) return;
|
|
1815
1883
|
|
|
1816
1884
|
if (this.iterationType === IterationType.ITERATIVE) {
|
|
@@ -1818,58 +1886,29 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1818
1886
|
let current: N | null | undefined = node;
|
|
1819
1887
|
|
|
1820
1888
|
while (current || stack.length > 0) {
|
|
1821
|
-
while (current && !isNaN(current.key)) {
|
|
1889
|
+
while (current && !isNaN(this.extractor(current.key))) {
|
|
1822
1890
|
stack.push(current);
|
|
1823
1891
|
current = current.left;
|
|
1824
1892
|
}
|
|
1825
1893
|
|
|
1826
1894
|
current = stack.pop();
|
|
1827
1895
|
|
|
1828
|
-
if (current && !isNaN(current.key)) {
|
|
1896
|
+
if (current && !isNaN(this.extractor(current.key))) {
|
|
1829
1897
|
yield [current.key, current.value];
|
|
1830
1898
|
current = current.right;
|
|
1831
1899
|
}
|
|
1832
1900
|
}
|
|
1833
1901
|
} else {
|
|
1834
|
-
if (node.left && !isNaN(node.key)) {
|
|
1902
|
+
if (node.left && !isNaN(this.extractor(node.key))) {
|
|
1835
1903
|
yield* this[Symbol.iterator](node.left);
|
|
1836
1904
|
}
|
|
1837
1905
|
yield [node.key, node.value];
|
|
1838
|
-
if (node.right && !isNaN(node.key)) {
|
|
1906
|
+
if (node.right && !isNaN(this.extractor(node.key))) {
|
|
1839
1907
|
yield* this[Symbol.iterator](node.right);
|
|
1840
1908
|
}
|
|
1841
1909
|
}
|
|
1842
1910
|
}
|
|
1843
1911
|
|
|
1844
|
-
/**
|
|
1845
|
-
* The `print` function is used to display a binary tree structure in a visually appealing way.
|
|
1846
|
-
* @param {BTNKey | N | null | undefined} [beginRoot=this.root] - The `root` parameter is of type `BTNKey | N | null |
|
|
1847
|
-
* undefined`. It represents the root node of a binary tree. The root node can have one of the
|
|
1848
|
-
* following types:
|
|
1849
|
-
* @param {BinaryTreePrintOptions} [options={ isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false}] - Options object that controls printing behavior. You can specify whether to display undefined, null, or sentinel nodes.
|
|
1850
|
-
*/
|
|
1851
|
-
print(beginRoot: BTNodeKeyOrNode<N> = this.root, options?: BinaryTreePrintOptions): void {
|
|
1852
|
-
const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options };
|
|
1853
|
-
beginRoot = this.ensureNode(beginRoot);
|
|
1854
|
-
if (!beginRoot) return;
|
|
1855
|
-
|
|
1856
|
-
if (opts.isShowUndefined) console.log(`U for undefined
|
|
1857
|
-
`);
|
|
1858
|
-
if (opts.isShowNull) console.log(`N for null
|
|
1859
|
-
`);
|
|
1860
|
-
if (opts.isShowRedBlackNIL) console.log(`S for Sentinel Node
|
|
1861
|
-
`);
|
|
1862
|
-
|
|
1863
|
-
const display = (root: N | null | undefined): void => {
|
|
1864
|
-
const [lines, , ,] = this._displayAux(root, opts);
|
|
1865
|
-
for (const line of lines) {
|
|
1866
|
-
console.log(line);
|
|
1867
|
-
}
|
|
1868
|
-
};
|
|
1869
|
-
|
|
1870
|
-
display(beginRoot);
|
|
1871
|
-
}
|
|
1872
|
-
|
|
1873
1912
|
protected _displayAux(node: N | null | undefined, options: BinaryTreePrintOptions): NodeDisplayLayout {
|
|
1874
1913
|
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
1875
1914
|
const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];
|
|
@@ -1879,12 +1918,13 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1879
1918
|
return emptyDisplayLayout;
|
|
1880
1919
|
} else if (node === undefined && !isShowUndefined) {
|
|
1881
1920
|
return emptyDisplayLayout;
|
|
1882
|
-
} else if (node !== null && node !== undefined && isNaN(node.key) && !isShowRedBlackNIL) {
|
|
1921
|
+
} else if (node !== null && node !== undefined && isNaN(this.extractor(node.key)) && !isShowRedBlackNIL) {
|
|
1883
1922
|
return emptyDisplayLayout;
|
|
1884
1923
|
} else if (node !== null && node !== undefined) {
|
|
1885
1924
|
// Display logic of normal nodes
|
|
1886
1925
|
|
|
1887
|
-
const key = node.key, line = isNaN(key) ? 'S' : key.toString(),
|
|
1926
|
+
const key = node.key, line = isNaN(this.extractor(key)) ? 'S' : this.extractor(key).toString(),
|
|
1927
|
+
width = line.length;
|
|
1888
1928
|
|
|
1889
1929
|
return _buildNodeDisplay(line, width, this._displayAux(node.left, options), this._displayAux(node.right, options))
|
|
1890
1930
|
|
|
@@ -1928,7 +1968,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1928
1968
|
* @param {N} destNode - The destination node to swap.
|
|
1929
1969
|
* @returns {N} - The destination node after the swap.
|
|
1930
1970
|
*/
|
|
1931
|
-
protected _swapProperties(srcNode: BTNodeKeyOrNode<N>, destNode: BTNodeKeyOrNode<N>): N | undefined {
|
|
1971
|
+
protected _swapProperties(srcNode: BTNodeKeyOrNode<K, N>, destNode: BTNodeKeyOrNode<K, N>): N | undefined {
|
|
1932
1972
|
srcNode = this.ensureNode(srcNode);
|
|
1933
1973
|
destNode = this.ensureNode(destNode);
|
|
1934
1974
|
|
|
@@ -1986,8 +2026,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1986
2026
|
* the binary tree. If neither the left nor right child is available, the function returns undefined.
|
|
1987
2027
|
* If the parent node is null, the function also returns undefined.
|
|
1988
2028
|
*/
|
|
1989
|
-
protected _addTo(newNode: N | null | undefined, parent: BTNodeKeyOrNode<N>): N | null | undefined {
|
|
1990
|
-
if (this.
|
|
2029
|
+
protected _addTo(newNode: N | null | undefined, parent: BTNodeKeyOrNode<K, N>): N | null | undefined {
|
|
2030
|
+
if (this.isNotNodeInstance(parent)) parent = this.getNode(parent);
|
|
1991
2031
|
|
|
1992
2032
|
if (parent) {
|
|
1993
2033
|
// When all leaf nodes are null, it will no longer be possible to add new entity nodes to this binary tree.
|