graph-typed 1.51.0 → 1.51.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data-structures/binary-tree/avl-tree-multi-map.js +1 -1
- package/dist/data-structures/binary-tree/avl-tree.d.ts +1 -1
- package/dist/data-structures/binary-tree/avl-tree.js +2 -2
- package/dist/data-structures/binary-tree/binary-tree.d.ts +17 -11
- package/dist/data-structures/binary-tree/binary-tree.js +98 -92
- package/dist/data-structures/binary-tree/bst.d.ts +27 -1
- package/dist/data-structures/binary-tree/bst.js +68 -39
- package/dist/data-structures/binary-tree/rb-tree.d.ts +2 -48
- package/dist/data-structures/binary-tree/rb-tree.js +8 -63
- package/dist/data-structures/binary-tree/tree-multi-map.d.ts +1 -1
- package/dist/data-structures/binary-tree/tree-multi-map.js +2 -2
- package/package.json +2 -2
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +1 -1
- package/src/data-structures/binary-tree/avl-tree.ts +2 -2
- package/src/data-structures/binary-tree/binary-tree.ts +98 -93
- package/src/data-structures/binary-tree/bst.ts +69 -34
- package/src/data-structures/binary-tree/rb-tree.ts +8 -74
- package/src/data-structures/binary-tree/tree-multi-map.ts +2 -2
|
@@ -191,6 +191,16 @@ export class BinaryTree<
|
|
|
191
191
|
return this._size;
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
+
protected _NIL: NODE = new BinaryTreeNode<K, V>(NaN as K) as unknown as NODE;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* The function returns the value of the _NIL property.
|
|
198
|
+
* @returns The method is returning the value of the `_NIL` property.
|
|
199
|
+
*/
|
|
200
|
+
get NIL(): NODE {
|
|
201
|
+
return this._NIL;
|
|
202
|
+
}
|
|
203
|
+
|
|
194
204
|
/**
|
|
195
205
|
* Creates a new instance of BinaryTreeNode with the given key and value.
|
|
196
206
|
* @param {K} key - The key for the new node.
|
|
@@ -268,17 +278,26 @@ export class BinaryTree<
|
|
|
268
278
|
keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>,
|
|
269
279
|
iterationType: IterationType = 'ITERATIVE'
|
|
270
280
|
): NODE | null | undefined {
|
|
271
|
-
let res: NODE | null | undefined;
|
|
272
281
|
if (this.isRealNode(keyOrNodeOrEntry)) {
|
|
273
|
-
|
|
282
|
+
return keyOrNodeOrEntry;
|
|
274
283
|
} else if (this.isEntry(keyOrNodeOrEntry)) {
|
|
275
|
-
if (keyOrNodeOrEntry[0] === null)
|
|
276
|
-
|
|
284
|
+
if (keyOrNodeOrEntry[0] === null) return null;
|
|
285
|
+
if (keyOrNodeOrEntry[0] === undefined) return;
|
|
286
|
+
return this.getNodeByKey(keyOrNodeOrEntry[0], iterationType);
|
|
277
287
|
} else {
|
|
278
|
-
if (keyOrNodeOrEntry === null)
|
|
279
|
-
|
|
288
|
+
if (keyOrNodeOrEntry === null) return null;
|
|
289
|
+
if (keyOrNodeOrEntry === undefined) return;
|
|
290
|
+
return this.getNodeByKey(keyOrNodeOrEntry, iterationType);
|
|
280
291
|
}
|
|
281
|
-
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* The function checks if a given node is a real node or null.
|
|
296
|
+
* @param {any} node - The parameter `node` is of type `any`, which means it can be any data type.
|
|
297
|
+
* @returns a boolean value.
|
|
298
|
+
*/
|
|
299
|
+
isNodeOrNull(node: KeyOrNodeOrEntry<K, V, NODE>): node is NODE | null {
|
|
300
|
+
return this.isRealNode(node) || node === null;
|
|
282
301
|
}
|
|
283
302
|
|
|
284
303
|
/**
|
|
@@ -290,16 +309,6 @@ export class BinaryTree<
|
|
|
290
309
|
return keyOrNodeOrEntry instanceof BinaryTreeNode;
|
|
291
310
|
}
|
|
292
311
|
|
|
293
|
-
/**
|
|
294
|
-
* The function checks if a given value is an entry in a binary tree node.
|
|
295
|
-
* @param keyOrNodeOrEntry - KeyOrNodeOrEntry<K, V,NODE> - A generic type representing a node in a binary tree. It has
|
|
296
|
-
* two type parameters V and NODE, representing the value and node type respectively.
|
|
297
|
-
* @returns a boolean value.
|
|
298
|
-
*/
|
|
299
|
-
isEntry(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>): keyOrNodeOrEntry is BTNEntry<K, V> {
|
|
300
|
-
return Array.isArray(keyOrNodeOrEntry) && keyOrNodeOrEntry.length === 2;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
312
|
/**
|
|
304
313
|
* The function checks if a given node is a real node by verifying if it is an instance of
|
|
305
314
|
* BinaryTreeNode and its key is not NaN.
|
|
@@ -307,7 +316,8 @@ export class BinaryTree<
|
|
|
307
316
|
* @returns a boolean value.
|
|
308
317
|
*/
|
|
309
318
|
isRealNode(node: KeyOrNodeOrEntry<K, V, NODE>): node is NODE {
|
|
310
|
-
|
|
319
|
+
if (!this.isNode(node)) return false;
|
|
320
|
+
return node !== this.NIL;
|
|
311
321
|
}
|
|
312
322
|
|
|
313
323
|
/**
|
|
@@ -316,16 +326,17 @@ export class BinaryTree<
|
|
|
316
326
|
* @returns a boolean value.
|
|
317
327
|
*/
|
|
318
328
|
isNIL(node: KeyOrNodeOrEntry<K, V, NODE>) {
|
|
319
|
-
return node
|
|
329
|
+
return node === this.NIL;
|
|
320
330
|
}
|
|
321
331
|
|
|
322
332
|
/**
|
|
323
|
-
* The function checks if a given
|
|
324
|
-
* @param
|
|
333
|
+
* The function checks if a given value is an entry in a binary tree node.
|
|
334
|
+
* @param keyOrNodeOrEntry - KeyOrNodeOrEntry<K, V,NODE> - A generic type representing a node in a binary tree. It has
|
|
335
|
+
* two type parameters V and NODE, representing the value and node type respectively.
|
|
325
336
|
* @returns a boolean value.
|
|
326
337
|
*/
|
|
327
|
-
|
|
328
|
-
return
|
|
338
|
+
isEntry(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>): keyOrNodeOrEntry is BTNEntry<K, V> {
|
|
339
|
+
return Array.isArray(keyOrNodeOrEntry) && keyOrNodeOrEntry.length === 2;
|
|
329
340
|
}
|
|
330
341
|
|
|
331
342
|
/**
|
|
@@ -486,16 +497,16 @@ export class BinaryTree<
|
|
|
486
497
|
* specific node based on its value or object.
|
|
487
498
|
* @param {C} callback - The `callback` parameter is a function that is used to determine the
|
|
488
499
|
* identifier of the node to be deleted. It is optional and has a default value of
|
|
489
|
-
* `this.
|
|
500
|
+
* `this._DEFAULT_CALLBACK`. The `callback` function should return the identifier of the node.
|
|
490
501
|
* @returns an array of `BinaryTreeDeleteResult<NODE>`.
|
|
491
502
|
*/
|
|
492
503
|
delete<C extends BTNCallback<NODE>>(
|
|
493
504
|
identifier: ReturnType<C> | null | undefined,
|
|
494
|
-
callback: C = this.
|
|
505
|
+
callback: C = this._DEFAULT_CALLBACK as C
|
|
495
506
|
): BinaryTreeDeleteResult<NODE>[] {
|
|
496
507
|
const deletedResult: BinaryTreeDeleteResult<NODE>[] = [];
|
|
497
508
|
if (!this.root) return deletedResult;
|
|
498
|
-
if ((!callback || callback === this.
|
|
509
|
+
if ((!callback || callback === this._DEFAULT_CALLBACK) && (identifier as any) instanceof BinaryTreeNode)
|
|
499
510
|
callback = (node => node) as C;
|
|
500
511
|
|
|
501
512
|
const curr = this.getNode(identifier, callback);
|
|
@@ -579,7 +590,7 @@ export class BinaryTree<
|
|
|
579
590
|
* specific value.
|
|
580
591
|
* @param {C} callback - The `callback` parameter is a function that takes a node of type `NODE` as
|
|
581
592
|
* input and returns a value of type `C`. It is used to determine if a node matches the given
|
|
582
|
-
* identifier. If no callback is provided, the `
|
|
593
|
+
* identifier. If no callback is provided, the `_DEFAULT_CALLBACK` function is used as the
|
|
583
594
|
* default
|
|
584
595
|
* @param [onlyOne=false] - A boolean value indicating whether to only return the first node that
|
|
585
596
|
* matches the identifier. If set to true, the function will stop iterating once it finds a matching
|
|
@@ -594,12 +605,12 @@ export class BinaryTree<
|
|
|
594
605
|
*/
|
|
595
606
|
getNodes<C extends BTNCallback<NODE>>(
|
|
596
607
|
identifier: ReturnType<C> | null | undefined,
|
|
597
|
-
callback: C = this.
|
|
608
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
598
609
|
onlyOne = false,
|
|
599
610
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
600
611
|
iterationType: IterationType = this.iterationType
|
|
601
612
|
): NODE[] {
|
|
602
|
-
if ((!callback || callback === this.
|
|
613
|
+
if ((!callback || callback === this._DEFAULT_CALLBACK) && (identifier as any) instanceof BinaryTreeNode)
|
|
603
614
|
callback = (node => node) as C;
|
|
604
615
|
beginRoot = this.ensureNode(beginRoot);
|
|
605
616
|
if (!beginRoot) return [];
|
|
@@ -607,28 +618,28 @@ export class BinaryTree<
|
|
|
607
618
|
const ans: NODE[] = [];
|
|
608
619
|
|
|
609
620
|
if (iterationType === 'RECURSIVE') {
|
|
610
|
-
const
|
|
621
|
+
const dfs = (cur: NODE) => {
|
|
611
622
|
if (callback(cur) === identifier) {
|
|
612
623
|
ans.push(cur);
|
|
613
624
|
if (onlyOne) return;
|
|
614
625
|
}
|
|
615
|
-
if (!cur.left && !cur.right) return;
|
|
616
|
-
cur.left &&
|
|
617
|
-
cur.right &&
|
|
626
|
+
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
|
|
627
|
+
this.isRealNode(cur.left) && dfs(cur.left);
|
|
628
|
+
this.isRealNode(cur.right) && dfs(cur.right);
|
|
618
629
|
};
|
|
619
630
|
|
|
620
|
-
|
|
631
|
+
dfs(beginRoot);
|
|
621
632
|
} else {
|
|
622
|
-
const
|
|
623
|
-
while (
|
|
624
|
-
const cur =
|
|
625
|
-
if (cur) {
|
|
633
|
+
const stack = [beginRoot];
|
|
634
|
+
while (stack.length > 0) {
|
|
635
|
+
const cur = stack.pop();
|
|
636
|
+
if (this.isRealNode(cur)) {
|
|
626
637
|
if (callback(cur) === identifier) {
|
|
627
638
|
ans.push(cur);
|
|
628
639
|
if (onlyOne) return ans;
|
|
629
640
|
}
|
|
630
|
-
cur.left &&
|
|
631
|
-
cur.right &&
|
|
641
|
+
this.isRealNode(cur.left) && stack.push(cur.left);
|
|
642
|
+
this.isRealNode(cur.right) && stack.push(cur.right);
|
|
632
643
|
}
|
|
633
644
|
}
|
|
634
645
|
}
|
|
@@ -685,13 +696,10 @@ export class BinaryTree<
|
|
|
685
696
|
*/
|
|
686
697
|
getNode<C extends BTNCallback<NODE>>(
|
|
687
698
|
identifier: ReturnType<C> | null | undefined,
|
|
688
|
-
callback: C = this.
|
|
699
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
689
700
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
690
701
|
iterationType: IterationType = this.iterationType
|
|
691
702
|
): NODE | null | undefined {
|
|
692
|
-
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
693
|
-
callback = (node => node) as C;
|
|
694
|
-
|
|
695
703
|
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null;
|
|
696
704
|
}
|
|
697
705
|
|
|
@@ -717,23 +725,23 @@ export class BinaryTree<
|
|
|
717
725
|
getNodeByKey(key: K, iterationType: IterationType = 'ITERATIVE'): NODE | undefined {
|
|
718
726
|
if (!this.root) return undefined;
|
|
719
727
|
if (iterationType === 'RECURSIVE') {
|
|
720
|
-
const
|
|
728
|
+
const dfs = (cur: NODE): NODE | undefined => {
|
|
721
729
|
if (cur.key === key) return cur;
|
|
722
730
|
|
|
723
731
|
if (!cur.left && !cur.right) return;
|
|
724
|
-
if (cur.left) return
|
|
725
|
-
if (cur.right) return
|
|
732
|
+
if (cur.left) return dfs(cur.left);
|
|
733
|
+
if (cur.right) return dfs(cur.right);
|
|
726
734
|
};
|
|
727
735
|
|
|
728
|
-
return
|
|
736
|
+
return dfs(this.root);
|
|
729
737
|
} else {
|
|
730
|
-
const
|
|
731
|
-
while (
|
|
732
|
-
const cur =
|
|
738
|
+
const stack = [this.root];
|
|
739
|
+
while (stack.length > 0) {
|
|
740
|
+
const cur = stack.pop();
|
|
733
741
|
if (cur) {
|
|
734
742
|
if (cur.key === key) return cur;
|
|
735
|
-
cur.left &&
|
|
736
|
-
cur.right &&
|
|
743
|
+
cur.left && stack.push(cur.left);
|
|
744
|
+
cur.right && stack.push(cur.right);
|
|
737
745
|
}
|
|
738
746
|
}
|
|
739
747
|
}
|
|
@@ -789,13 +797,10 @@ export class BinaryTree<
|
|
|
789
797
|
*/
|
|
790
798
|
override get<C extends BTNCallback<NODE>>(
|
|
791
799
|
identifier: ReturnType<C> | null | undefined,
|
|
792
|
-
callback: C = this.
|
|
800
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
793
801
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
794
802
|
iterationType: IterationType = this.iterationType
|
|
795
803
|
): V | undefined {
|
|
796
|
-
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
797
|
-
callback = (node => node) as C;
|
|
798
|
-
|
|
799
804
|
return this.getNode(identifier, callback, beginRoot, iterationType)?.value ?? undefined;
|
|
800
805
|
}
|
|
801
806
|
|
|
@@ -848,11 +853,11 @@ export class BinaryTree<
|
|
|
848
853
|
*/
|
|
849
854
|
override has<C extends BTNCallback<NODE>>(
|
|
850
855
|
identifier: ReturnType<C> | null | undefined,
|
|
851
|
-
callback: C = this.
|
|
856
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
852
857
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
853
858
|
iterationType: IterationType = this.iterationType
|
|
854
859
|
): boolean {
|
|
855
|
-
if ((!callback || callback === this.
|
|
860
|
+
if ((!callback || callback === this._DEFAULT_CALLBACK) && (identifier as any) instanceof BinaryTreeNode)
|
|
856
861
|
callback = (node => node) as C;
|
|
857
862
|
|
|
858
863
|
return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0;
|
|
@@ -1184,20 +1189,20 @@ export class BinaryTree<
|
|
|
1184
1189
|
if (!this.isRealNode(beginRoot)) return beginRoot;
|
|
1185
1190
|
|
|
1186
1191
|
if (iterationType === 'RECURSIVE') {
|
|
1187
|
-
const
|
|
1192
|
+
const dfs = (cur: NODE): NODE => {
|
|
1188
1193
|
if (!this.isRealNode(cur.left)) return cur;
|
|
1189
|
-
return
|
|
1194
|
+
return dfs(cur.left);
|
|
1190
1195
|
};
|
|
1191
1196
|
|
|
1192
|
-
return
|
|
1197
|
+
return dfs(beginRoot);
|
|
1193
1198
|
} else {
|
|
1194
1199
|
// Indirect implementation of iteration using tail recursion optimization
|
|
1195
|
-
const
|
|
1200
|
+
const dfs = trampoline((cur: NODE) => {
|
|
1196
1201
|
if (!this.isRealNode(cur.left)) return cur;
|
|
1197
|
-
return
|
|
1202
|
+
return dfs.cont(cur.left);
|
|
1198
1203
|
});
|
|
1199
1204
|
|
|
1200
|
-
return
|
|
1205
|
+
return dfs(beginRoot);
|
|
1201
1206
|
}
|
|
1202
1207
|
}
|
|
1203
1208
|
|
|
@@ -1231,20 +1236,20 @@ export class BinaryTree<
|
|
|
1231
1236
|
if (!beginRoot) return beginRoot;
|
|
1232
1237
|
|
|
1233
1238
|
if (iterationType === 'RECURSIVE') {
|
|
1234
|
-
const
|
|
1239
|
+
const dfs = (cur: NODE): NODE => {
|
|
1235
1240
|
if (!this.isRealNode(cur.right)) return cur;
|
|
1236
|
-
return
|
|
1241
|
+
return dfs(cur.right);
|
|
1237
1242
|
};
|
|
1238
1243
|
|
|
1239
|
-
return
|
|
1244
|
+
return dfs(beginRoot);
|
|
1240
1245
|
} else {
|
|
1241
1246
|
// Indirect implementation of iteration using tail recursion optimization
|
|
1242
|
-
const
|
|
1247
|
+
const dfs = trampoline((cur: NODE) => {
|
|
1243
1248
|
if (!this.isRealNode(cur.right)) return cur;
|
|
1244
|
-
return
|
|
1249
|
+
return dfs.cont(cur.right);
|
|
1245
1250
|
});
|
|
1246
1251
|
|
|
1247
|
-
return
|
|
1252
|
+
return dfs(beginRoot);
|
|
1248
1253
|
}
|
|
1249
1254
|
}
|
|
1250
1255
|
|
|
@@ -1351,7 +1356,7 @@ export class BinaryTree<
|
|
|
1351
1356
|
* @returns an array of values that are the return values of the callback function.
|
|
1352
1357
|
*/
|
|
1353
1358
|
dfs<C extends BTNCallback<NODE | null | undefined>>(
|
|
1354
|
-
callback: C = this.
|
|
1359
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
1355
1360
|
pattern: DFSOrderPattern = 'IN',
|
|
1356
1361
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1357
1362
|
iterationType: IterationType = 'ITERATIVE',
|
|
@@ -1361,38 +1366,38 @@ export class BinaryTree<
|
|
|
1361
1366
|
if (!beginRoot) return [];
|
|
1362
1367
|
const ans: ReturnType<C>[] = [];
|
|
1363
1368
|
if (iterationType === 'RECURSIVE') {
|
|
1364
|
-
const
|
|
1369
|
+
const dfs = (node: NODE | null | undefined) => {
|
|
1365
1370
|
switch (pattern) {
|
|
1366
1371
|
case 'IN':
|
|
1367
1372
|
if (includeNull) {
|
|
1368
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.left))
|
|
1373
|
+
if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left);
|
|
1369
1374
|
this.isNodeOrNull(node) && ans.push(callback(node));
|
|
1370
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.right))
|
|
1375
|
+
if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right);
|
|
1371
1376
|
} else {
|
|
1372
|
-
if (this.isRealNode(node) && this.isRealNode(node.left))
|
|
1377
|
+
if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left);
|
|
1373
1378
|
this.isRealNode(node) && ans.push(callback(node));
|
|
1374
|
-
if (this.isRealNode(node) && this.isRealNode(node.right))
|
|
1379
|
+
if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right);
|
|
1375
1380
|
}
|
|
1376
1381
|
break;
|
|
1377
1382
|
case 'PRE':
|
|
1378
1383
|
if (includeNull) {
|
|
1379
1384
|
this.isNodeOrNull(node) && ans.push(callback(node));
|
|
1380
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.left))
|
|
1381
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.right))
|
|
1385
|
+
if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left);
|
|
1386
|
+
if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right);
|
|
1382
1387
|
} else {
|
|
1383
1388
|
this.isRealNode(node) && ans.push(callback(node));
|
|
1384
|
-
if (this.isRealNode(node) && this.isRealNode(node.left))
|
|
1385
|
-
if (this.isRealNode(node) && this.isRealNode(node.right))
|
|
1389
|
+
if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left);
|
|
1390
|
+
if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right);
|
|
1386
1391
|
}
|
|
1387
1392
|
break;
|
|
1388
1393
|
case 'POST':
|
|
1389
1394
|
if (includeNull) {
|
|
1390
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.left))
|
|
1391
|
-
if (this.isRealNode(node) && this.isNodeOrNull(node.right))
|
|
1395
|
+
if (this.isRealNode(node) && this.isNodeOrNull(node.left)) dfs(node.left);
|
|
1396
|
+
if (this.isRealNode(node) && this.isNodeOrNull(node.right)) dfs(node.right);
|
|
1392
1397
|
this.isNodeOrNull(node) && ans.push(callback(node));
|
|
1393
1398
|
} else {
|
|
1394
|
-
if (this.isRealNode(node) && this.isRealNode(node.left))
|
|
1395
|
-
if (this.isRealNode(node) && this.isRealNode(node.right))
|
|
1399
|
+
if (this.isRealNode(node) && this.isRealNode(node.left)) dfs(node.left);
|
|
1400
|
+
if (this.isRealNode(node) && this.isRealNode(node.right)) dfs(node.right);
|
|
1396
1401
|
this.isRealNode(node) && ans.push(callback(node));
|
|
1397
1402
|
}
|
|
1398
1403
|
|
|
@@ -1400,7 +1405,7 @@ export class BinaryTree<
|
|
|
1400
1405
|
}
|
|
1401
1406
|
};
|
|
1402
1407
|
|
|
1403
|
-
|
|
1408
|
+
dfs(beginRoot);
|
|
1404
1409
|
} else {
|
|
1405
1410
|
// 0: visit, 1: print
|
|
1406
1411
|
const stack: { opt: 0 | 1; node: NODE | null | undefined }[] = [{ opt: 0, node: beginRoot }];
|
|
@@ -1486,7 +1491,7 @@ export class BinaryTree<
|
|
|
1486
1491
|
* the breadth-first traversal of a binary tree.
|
|
1487
1492
|
*/
|
|
1488
1493
|
bfs<C extends BTNCallback<NODE | null>>(
|
|
1489
|
-
callback: C = this.
|
|
1494
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
1490
1495
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1491
1496
|
iterationType: IterationType = this.iterationType,
|
|
1492
1497
|
includeNull = false
|
|
@@ -1499,7 +1504,7 @@ export class BinaryTree<
|
|
|
1499
1504
|
if (iterationType === 'RECURSIVE') {
|
|
1500
1505
|
const queue: Queue<NODE | null | undefined> = new Queue<NODE | null | undefined>([beginRoot]);
|
|
1501
1506
|
|
|
1502
|
-
const
|
|
1507
|
+
const dfs = (level: number) => {
|
|
1503
1508
|
if (queue.size === 0) return;
|
|
1504
1509
|
|
|
1505
1510
|
const current = queue.shift()!;
|
|
@@ -1513,10 +1518,10 @@ export class BinaryTree<
|
|
|
1513
1518
|
if (this.isRealNode(current.right)) queue.push(current.right);
|
|
1514
1519
|
}
|
|
1515
1520
|
|
|
1516
|
-
|
|
1521
|
+
dfs(level + 1);
|
|
1517
1522
|
};
|
|
1518
1523
|
|
|
1519
|
-
|
|
1524
|
+
dfs(0);
|
|
1520
1525
|
} else {
|
|
1521
1526
|
const queue = new Queue<NODE | null | undefined>([beginRoot]);
|
|
1522
1527
|
while (queue.size > 0) {
|
|
@@ -1580,7 +1585,7 @@ export class BinaryTree<
|
|
|
1580
1585
|
* @returns The function `listLevels` returns a two-dimensional array of type `ReturnType<C>[][]`.
|
|
1581
1586
|
*/
|
|
1582
1587
|
listLevels<C extends BTNCallback<NODE | null>>(
|
|
1583
|
-
callback: C = this.
|
|
1588
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
1584
1589
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1585
1590
|
iterationType: IterationType = this.iterationType,
|
|
1586
1591
|
includeNull = false
|
|
@@ -1651,7 +1656,7 @@ export class BinaryTree<
|
|
|
1651
1656
|
* by the return type of the `callback` function.
|
|
1652
1657
|
*/
|
|
1653
1658
|
morris<C extends BTNCallback<NODE>>(
|
|
1654
|
-
callback: C = this.
|
|
1659
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
1655
1660
|
pattern: DFSOrderPattern = 'IN',
|
|
1656
1661
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root
|
|
1657
1662
|
): ReturnType<C>[] {
|
|
@@ -1995,7 +2000,7 @@ export class BinaryTree<
|
|
|
1995
2000
|
}
|
|
1996
2001
|
}
|
|
1997
2002
|
|
|
1998
|
-
protected
|
|
2003
|
+
protected _DEFAULT_CALLBACK = (node: NODE | null | undefined) => (node ? node.key : undefined);
|
|
1999
2004
|
|
|
2000
2005
|
/**
|
|
2001
2006
|
* Swap the data of two nodes in the binary tree.
|
|
@@ -13,7 +13,7 @@ import type {
|
|
|
13
13
|
BTNodePureExemplar,
|
|
14
14
|
KeyOrNodeOrEntry
|
|
15
15
|
} from '../../types';
|
|
16
|
-
import { BSTVariant, CP, DFSOrderPattern, IterationType } from '../../types';
|
|
16
|
+
import { BSTNKeyOrNode, BSTVariant, CP, DFSOrderPattern, IterationType } from '../../types';
|
|
17
17
|
import { BinaryTree, BinaryTreeNode } from './binary-tree';
|
|
18
18
|
import { IBinaryTree } from '../../interfaces';
|
|
19
19
|
import { Queue } from '../queue';
|
|
@@ -214,15 +214,15 @@ export class BST<
|
|
|
214
214
|
keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>,
|
|
215
215
|
iterationType: IterationType = 'ITERATIVE'
|
|
216
216
|
): NODE | undefined {
|
|
217
|
-
let res: NODE | undefined;
|
|
218
217
|
if (this.isRealNode(keyOrNodeOrEntry)) {
|
|
219
|
-
|
|
218
|
+
return keyOrNodeOrEntry;
|
|
220
219
|
} else if (this.isEntry(keyOrNodeOrEntry)) {
|
|
221
|
-
if (keyOrNodeOrEntry[0]
|
|
220
|
+
if (keyOrNodeOrEntry[0] === null || keyOrNodeOrEntry[0] === undefined) return;
|
|
221
|
+
return this.getNodeByKey(keyOrNodeOrEntry[0], iterationType);
|
|
222
222
|
} else {
|
|
223
|
-
if (keyOrNodeOrEntry
|
|
223
|
+
if (keyOrNodeOrEntry === null || keyOrNodeOrEntry === undefined) return;
|
|
224
|
+
return this.getNodeByKey(keyOrNodeOrEntry, iterationType);
|
|
224
225
|
}
|
|
225
|
-
return res;
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
/**
|
|
@@ -426,26 +426,26 @@ export class BST<
|
|
|
426
426
|
* found in the binary tree. If no node is found, it returns `undefined`.
|
|
427
427
|
*/
|
|
428
428
|
override getNodeByKey(key: K, iterationType: IterationType = 'ITERATIVE'): NODE | undefined {
|
|
429
|
-
// return this.getNodes(key, this.
|
|
430
|
-
if (!this.isRealNode(this.root)) return
|
|
429
|
+
// return this.getNodes(key, this._DEFAULT_CALLBACK, true, this.root, iterationType)[0];
|
|
430
|
+
if (!this.isRealNode(this.root)) return;
|
|
431
431
|
if (iterationType === 'RECURSIVE') {
|
|
432
|
-
const
|
|
432
|
+
const dfs = (cur: NODE): NODE | undefined => {
|
|
433
433
|
if (cur.key === key) return cur;
|
|
434
434
|
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
|
|
435
435
|
|
|
436
|
-
if (this._compare(cur.key, key) === 'GT'
|
|
437
|
-
if (this._compare(cur.key, key) === 'LT'
|
|
436
|
+
if (this.isRealNode(cur.left) && this._compare(cur.key, key) === 'GT') return dfs(cur.left);
|
|
437
|
+
if (this.isRealNode(cur.right) && this._compare(cur.key, key) === 'LT') return dfs(cur.right);
|
|
438
438
|
};
|
|
439
439
|
|
|
440
|
-
return
|
|
440
|
+
return dfs(this.root);
|
|
441
441
|
} else {
|
|
442
|
-
const
|
|
443
|
-
while (
|
|
444
|
-
const cur =
|
|
442
|
+
const stack = [this.root];
|
|
443
|
+
while (stack.length > 0) {
|
|
444
|
+
const cur = stack.pop();
|
|
445
445
|
if (this.isRealNode(cur)) {
|
|
446
446
|
if (this._compare(cur.key, key) === 'EQ') return cur;
|
|
447
|
-
if (this._compare(cur.key, key) === 'GT')
|
|
448
|
-
if (this._compare(cur.key, key) === 'LT')
|
|
447
|
+
if (this.isRealNode(cur.left) && this._compare(cur.key, key) === 'GT') stack.push(cur.left);
|
|
448
|
+
if (this.isRealNode(cur.right) && this._compare(cur.key, key) === 'LT') stack.push(cur.right);
|
|
449
449
|
}
|
|
450
450
|
}
|
|
451
451
|
}
|
|
@@ -481,7 +481,7 @@ export class BST<
|
|
|
481
481
|
*/
|
|
482
482
|
override getNodes<C extends BTNCallback<NODE>>(
|
|
483
483
|
identifier: ReturnType<C> | undefined,
|
|
484
|
-
callback: C = this.
|
|
484
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
485
485
|
onlyOne = false,
|
|
486
486
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
487
487
|
iterationType: IterationType = this.iterationType
|
|
@@ -491,7 +491,7 @@ export class BST<
|
|
|
491
491
|
const ans: NODE[] = [];
|
|
492
492
|
|
|
493
493
|
if (iterationType === 'RECURSIVE') {
|
|
494
|
-
const
|
|
494
|
+
const dfs = (cur: NODE) => {
|
|
495
495
|
const callbackResult = callback(cur);
|
|
496
496
|
if (callbackResult === identifier) {
|
|
497
497
|
ans.push(cur);
|
|
@@ -500,16 +500,16 @@ export class BST<
|
|
|
500
500
|
|
|
501
501
|
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
|
|
502
502
|
// TODO potential bug
|
|
503
|
-
if (callback === this.
|
|
504
|
-
if (this.isRealNode(cur.left) && this._compare(cur.key, identifier as K) === 'GT')
|
|
505
|
-
if (this.isRealNode(cur.right) && this._compare(cur.key, identifier as K) === 'LT')
|
|
503
|
+
if (callback === this._DEFAULT_CALLBACK) {
|
|
504
|
+
if (this.isRealNode(cur.left) && this._compare(cur.key, identifier as K) === 'GT') dfs(cur.left);
|
|
505
|
+
if (this.isRealNode(cur.right) && this._compare(cur.key, identifier as K) === 'LT') dfs(cur.right);
|
|
506
506
|
} else {
|
|
507
|
-
this.isRealNode(cur.left) &&
|
|
508
|
-
this.isRealNode(cur.right) &&
|
|
507
|
+
this.isRealNode(cur.left) && dfs(cur.left);
|
|
508
|
+
this.isRealNode(cur.right) && dfs(cur.right);
|
|
509
509
|
}
|
|
510
510
|
};
|
|
511
511
|
|
|
512
|
-
|
|
512
|
+
dfs(beginRoot);
|
|
513
513
|
} else {
|
|
514
514
|
const stack = [beginRoot];
|
|
515
515
|
while (stack.length > 0) {
|
|
@@ -521,7 +521,7 @@ export class BST<
|
|
|
521
521
|
if (onlyOne) return ans;
|
|
522
522
|
}
|
|
523
523
|
// TODO potential bug
|
|
524
|
-
if (callback === this.
|
|
524
|
+
if (callback === this._DEFAULT_CALLBACK) {
|
|
525
525
|
if (this.isRealNode(cur.right) && this._compare(cur.key, identifier as K) === 'LT') stack.push(cur.right);
|
|
526
526
|
if (this.isRealNode(cur.left) && this._compare(cur.key, identifier as K) === 'GT') stack.push(cur.left);
|
|
527
527
|
|
|
@@ -543,6 +543,41 @@ export class BST<
|
|
|
543
543
|
return ans;
|
|
544
544
|
}
|
|
545
545
|
|
|
546
|
+
/**
|
|
547
|
+
* Time Complexity: O(log n)
|
|
548
|
+
* Space Complexity: O(1)
|
|
549
|
+
*/
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Time Complexity: O(log n)
|
|
553
|
+
* Space Complexity: O(1)
|
|
554
|
+
*
|
|
555
|
+
* The `getNode` function retrieves a node from a Red-Black Tree based on the provided identifier and
|
|
556
|
+
* callback function.
|
|
557
|
+
* @param {ReturnType<C> | undefined} identifier - The `identifier` parameter is the value or key
|
|
558
|
+
* that you want to search for in the binary search tree. It can be of any type that is compatible
|
|
559
|
+
* with the type of nodes in the tree.
|
|
560
|
+
* @param {C} callback - The `callback` parameter is a function that will be called for each node in
|
|
561
|
+
* the tree. It is used to determine whether a node matches the given identifier. The `callback`
|
|
562
|
+
* function should take a node as its parameter and return a value that can be compared to the
|
|
563
|
+
* `identifier` parameter.
|
|
564
|
+
* @param beginRoot - The `beginRoot` parameter is the starting point for the search in the binary
|
|
565
|
+
* search tree. It can be either a key or a node. If it is a key, it will be converted to a node
|
|
566
|
+
* using the `ensureNode` method. If it is not provided, the `root`
|
|
567
|
+
* @param iterationType - The `iterationType` parameter is used to specify the type of iteration to
|
|
568
|
+
* be performed when searching for nodes in the binary search tree. It is an optional parameter and
|
|
569
|
+
* its default value is taken from the `iterationType` property of the class.
|
|
570
|
+
* @returns The method is returning a value of type `NODE | null | undefined`.
|
|
571
|
+
*/
|
|
572
|
+
override getNode<C extends BTNCallback<NODE>>(
|
|
573
|
+
identifier: ReturnType<C> | undefined,
|
|
574
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
575
|
+
beginRoot: BSTNKeyOrNode<K, NODE> = this.root,
|
|
576
|
+
iterationType: IterationType = this.iterationType
|
|
577
|
+
): NODE | undefined {
|
|
578
|
+
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
|
|
579
|
+
}
|
|
580
|
+
|
|
546
581
|
/**
|
|
547
582
|
* Time complexity: O(n)
|
|
548
583
|
* Space complexity: O(n)
|
|
@@ -568,7 +603,7 @@ export class BST<
|
|
|
568
603
|
* @returns The method is returning an array of the return type of the callback function.
|
|
569
604
|
*/
|
|
570
605
|
override dfs<C extends BTNCallback<NODE>>(
|
|
571
|
-
callback: C = this.
|
|
606
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
572
607
|
pattern: DFSOrderPattern = 'IN',
|
|
573
608
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
574
609
|
iterationType: IterationType = 'ITERATIVE'
|
|
@@ -599,7 +634,7 @@ export class BST<
|
|
|
599
634
|
* @returns The method is returning an array of the return type of the callback function.
|
|
600
635
|
*/
|
|
601
636
|
override bfs<C extends BTNCallback<NODE>>(
|
|
602
|
-
callback: C = this.
|
|
637
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
603
638
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
604
639
|
iterationType: IterationType = this.iterationType
|
|
605
640
|
): ReturnType<C>[] {
|
|
@@ -630,7 +665,7 @@ export class BST<
|
|
|
630
665
|
* function.
|
|
631
666
|
*/
|
|
632
667
|
override listLevels<C extends BTNCallback<NODE>>(
|
|
633
|
-
callback: C = this.
|
|
668
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
634
669
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
635
670
|
iterationType: IterationType = this.iterationType
|
|
636
671
|
): ReturnType<C>[][] {
|
|
@@ -700,7 +735,7 @@ export class BST<
|
|
|
700
735
|
* `ReturnType<C>`, which is the return type of the callback function passed as an argument.
|
|
701
736
|
*/
|
|
702
737
|
lesserOrGreaterTraverse<C extends BTNCallback<NODE>>(
|
|
703
|
-
callback: C = this.
|
|
738
|
+
callback: C = this._DEFAULT_CALLBACK as C,
|
|
704
739
|
lesserOrGreater: CP = 'LT',
|
|
705
740
|
targetNode: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
706
741
|
iterationType: IterationType = this.iterationType
|
|
@@ -713,15 +748,15 @@ export class BST<
|
|
|
713
748
|
const targetKey = targetNode.key;
|
|
714
749
|
|
|
715
750
|
if (iterationType === 'RECURSIVE') {
|
|
716
|
-
const
|
|
751
|
+
const dfs = (cur: NODE) => {
|
|
717
752
|
const compared = this._compare(cur.key, targetKey);
|
|
718
753
|
if (compared === lesserOrGreater) ans.push(callback(cur));
|
|
719
754
|
|
|
720
|
-
if (this.isRealNode(cur.left))
|
|
721
|
-
if (this.isRealNode(cur.right))
|
|
755
|
+
if (this.isRealNode(cur.left)) dfs(cur.left);
|
|
756
|
+
if (this.isRealNode(cur.right)) dfs(cur.right);
|
|
722
757
|
};
|
|
723
758
|
|
|
724
|
-
|
|
759
|
+
dfs(this.root);
|
|
725
760
|
return ans;
|
|
726
761
|
} else {
|
|
727
762
|
const queue = new Queue<NODE>([this.root]);
|