data-structure-typed 1.36.9 → 1.37.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/CHANGELOG.md +2 -1
- package/dist/data-structures/binary-tree/binary-tree.d.ts +1 -11
- package/dist/data-structures/binary-tree/binary-tree.js +8 -57
- package/dist/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/data-structures/binary-tree/bst.d.ts +6 -20
- package/dist/data-structures/binary-tree/bst.js +22 -122
- package/dist/data-structures/binary-tree/bst.js.map +1 -1
- package/dist/data-structures/binary-tree/tree-multiset.d.ts +1 -55
- package/dist/data-structures/binary-tree/tree-multiset.js +3 -240
- package/dist/data-structures/binary-tree/tree-multiset.js.map +1 -1
- package/dist/data-structures/graph/abstract-graph.js +4 -3
- package/dist/data-structures/graph/abstract-graph.js.map +1 -1
- package/lib/data-structures/binary-tree/binary-tree.d.ts +1 -11
- package/lib/data-structures/binary-tree/binary-tree.js +8 -57
- package/lib/data-structures/binary-tree/bst.d.ts +6 -20
- package/lib/data-structures/binary-tree/bst.js +22 -122
- package/lib/data-structures/binary-tree/tree-multiset.d.ts +1 -55
- package/lib/data-structures/binary-tree/tree-multiset.js +3 -240
- package/lib/data-structures/graph/abstract-graph.js +4 -3
- package/package.json +9 -7
- package/src/data-structures/binary-tree/binary-tree.ts +8 -62
- package/src/data-structures/binary-tree/bst.ts +22 -106
- package/src/data-structures/binary-tree/tree-multiset.ts +3 -231
- package/src/data-structures/graph/abstract-graph.ts +4 -3
- package/test/unit/data-structures/binary-tree/avl-tree.test.ts +5 -3
- package/test/unit/data-structures/binary-tree/bst.test.ts +44 -7
- package/test/unit/data-structures/binary-tree/overall.test.ts +1 -1
- package/test/unit/data-structures/binary-tree/tree-multiset.test.ts +39 -9
- package/test/unit/data-structures/queue/deque.test.ts +17 -0
- package/test/unit/data-structures/queue/queue.test.ts +42 -0
- package/test/utils/big-o.ts +5 -4
- package/umd/bundle.min.js +1 -1
- package/umd/bundle.min.js.map +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CP, FamilyPosition, LoopType } from '../../types';
|
|
2
2
|
import { AVLTree, AVLTreeNode } from './avl-tree';
|
|
3
|
+
import { Queue } from '../queue';
|
|
3
4
|
export class TreeMultisetNode extends AVLTreeNode {
|
|
4
5
|
/**
|
|
5
6
|
* The constructor function initializes a BinaryTreeNode object with a key, value, and count.
|
|
@@ -321,110 +322,6 @@ export class TreeMultiset extends AVLTree {
|
|
|
321
322
|
}
|
|
322
323
|
return bstDeletedResult;
|
|
323
324
|
}
|
|
324
|
-
/**
|
|
325
|
-
* The function `getSubTreeCount` calculates the number of nodes and the sum of their counts in a subtree, using either
|
|
326
|
-
* recursive or iterative traversal.
|
|
327
|
-
* @param {N | null | undefined} subTreeRoot - The `subTreeRoot` parameter represents the root node of a subtree in a
|
|
328
|
-
* binary tree.
|
|
329
|
-
* @returns The function `getSubTreeCount` returns an array `[number, number]`.
|
|
330
|
-
*/
|
|
331
|
-
getSubTreeCount(subTreeRoot) {
|
|
332
|
-
const res = [0, 0];
|
|
333
|
-
if (!subTreeRoot)
|
|
334
|
-
return res;
|
|
335
|
-
if (this.loopType === LoopType.RECURSIVE) {
|
|
336
|
-
const _traverse = (cur) => {
|
|
337
|
-
res[0]++;
|
|
338
|
-
res[1] += cur.count;
|
|
339
|
-
cur.left && _traverse(cur.left);
|
|
340
|
-
cur.right && _traverse(cur.right);
|
|
341
|
-
};
|
|
342
|
-
_traverse(subTreeRoot);
|
|
343
|
-
return res;
|
|
344
|
-
}
|
|
345
|
-
else {
|
|
346
|
-
const stack = [subTreeRoot];
|
|
347
|
-
while (stack.length > 0) {
|
|
348
|
-
const cur = stack.pop();
|
|
349
|
-
res[0]++;
|
|
350
|
-
res[1] += cur.count;
|
|
351
|
-
cur.right && stack.push(cur.right);
|
|
352
|
-
cur.left && stack.push(cur.left);
|
|
353
|
-
}
|
|
354
|
-
return res;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
/**
|
|
358
|
-
* The function `subTreeSumCount` calculates the sum of the `count` property of each node in a subtree, either
|
|
359
|
-
* recursively or iteratively.
|
|
360
|
-
* @param {N | BinaryTreeNodeKey | null} subTreeRoot - The `subTreeRoot` parameter represents the root node of a subtree
|
|
361
|
-
* in a binary tree. It can be either a `BinaryTreeNodeKey` (a unique identifier for a node in the binary tree) or
|
|
362
|
-
* `null` if the subtree is empty.
|
|
363
|
-
* @returns the sum of the count values of all nodes in the subtree rooted at `subTreeRoot`.
|
|
364
|
-
*/
|
|
365
|
-
subTreeSumCount(subTreeRoot) {
|
|
366
|
-
if (typeof subTreeRoot === 'number')
|
|
367
|
-
subTreeRoot = this.get(subTreeRoot, 'key');
|
|
368
|
-
if (!subTreeRoot)
|
|
369
|
-
return 0;
|
|
370
|
-
let sum = 0;
|
|
371
|
-
if (this.loopType === LoopType.RECURSIVE) {
|
|
372
|
-
const _traverse = (cur) => {
|
|
373
|
-
sum += cur.count;
|
|
374
|
-
cur.left && _traverse(cur.left);
|
|
375
|
-
cur.right && _traverse(cur.right);
|
|
376
|
-
};
|
|
377
|
-
_traverse(subTreeRoot);
|
|
378
|
-
}
|
|
379
|
-
else {
|
|
380
|
-
const stack = [subTreeRoot];
|
|
381
|
-
while (stack.length > 0) {
|
|
382
|
-
const cur = stack.pop();
|
|
383
|
-
sum += cur.count;
|
|
384
|
-
cur.right && stack.push(cur.right);
|
|
385
|
-
cur.left && stack.push(cur.left);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
return sum;
|
|
389
|
-
}
|
|
390
|
-
/**
|
|
391
|
-
* The function `subTreeAddCount` recursively or iteratively traverses a binary tree and adds a given delta value to
|
|
392
|
-
* the `count` property of each node.
|
|
393
|
-
* @param {N | BinaryTreeNodeKey | null} subTreeRoot - The `subTreeRoot` parameter represents the root node of a subtree
|
|
394
|
-
* in a binary tree. It can be either a `BinaryTreeNodeKey` (a unique identifier for a node in the binary tree), a
|
|
395
|
-
* `BinaryTreeNode` object, or `null` if the subtree is empty.
|
|
396
|
-
* @param {number} delta - The delta parameter is a number that represents the amount by which the count of each node
|
|
397
|
-
* in the subtree should be increased or decreased.
|
|
398
|
-
* @returns a boolean value.
|
|
399
|
-
*/
|
|
400
|
-
subTreeAddCount(subTreeRoot, delta) {
|
|
401
|
-
if (typeof subTreeRoot === 'number')
|
|
402
|
-
subTreeRoot = this.get(subTreeRoot, 'key');
|
|
403
|
-
if (!subTreeRoot)
|
|
404
|
-
return false;
|
|
405
|
-
const _addByProperty = (cur) => {
|
|
406
|
-
cur.count += delta;
|
|
407
|
-
this._setCount(this.count + delta);
|
|
408
|
-
};
|
|
409
|
-
if (this.loopType === LoopType.RECURSIVE) {
|
|
410
|
-
const _traverse = (cur) => {
|
|
411
|
-
_addByProperty(cur);
|
|
412
|
-
cur.left && _traverse(cur.left);
|
|
413
|
-
cur.right && _traverse(cur.right);
|
|
414
|
-
};
|
|
415
|
-
_traverse(subTreeRoot);
|
|
416
|
-
}
|
|
417
|
-
else {
|
|
418
|
-
const stack = [subTreeRoot];
|
|
419
|
-
while (stack.length > 0) {
|
|
420
|
-
const cur = stack.pop();
|
|
421
|
-
_addByProperty(cur);
|
|
422
|
-
cur.right && stack.push(cur.right);
|
|
423
|
-
cur.left && stack.push(cur.left);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
return true;
|
|
427
|
-
}
|
|
428
325
|
/**
|
|
429
326
|
* The function `getNodesByCount` returns an array of nodes that have a specific count property, either recursively or
|
|
430
327
|
* using a queue.
|
|
@@ -454,8 +351,8 @@ export class TreeMultiset extends AVLTree {
|
|
|
454
351
|
_traverse(this.root);
|
|
455
352
|
}
|
|
456
353
|
else {
|
|
457
|
-
const queue = [this.root];
|
|
458
|
-
while (queue.
|
|
354
|
+
const queue = new Queue([this.root]);
|
|
355
|
+
while (queue.size > 0) {
|
|
459
356
|
const cur = queue.shift();
|
|
460
357
|
if (cur) {
|
|
461
358
|
if (cur.count === nodeProperty) {
|
|
@@ -502,140 +399,6 @@ export class TreeMultiset extends AVLTree {
|
|
|
502
399
|
const nodes = super.morris(pattern, 'node');
|
|
503
400
|
return nodes.map(node => node.count);
|
|
504
401
|
}
|
|
505
|
-
/**
|
|
506
|
-
* The function dfsCountIterative performs an iterative depth-first search and returns an array of node counts based on
|
|
507
|
-
* the specified traversal pattern.
|
|
508
|
-
* @param {'in' | 'pre' | 'post'} [pattern] - The pattern parameter is a string that specifies the traversal order for
|
|
509
|
-
* the Depth-First Search (dfs) algorithm. It can have three possible values: 'in', 'pre', or 'post'.
|
|
510
|
-
* @param loopType - The loopType parameter is a string that specifies the type of loop to use when traversing the
|
|
511
|
-
* @returns The dfsCountIterative function returns an array of numbers, which represents the count property of each node
|
|
512
|
-
* in the dfs traversal.
|
|
513
|
-
*/
|
|
514
|
-
dfsCount(pattern = 'in', loopType = LoopType.ITERATIVE) {
|
|
515
|
-
const nodes = super.dfs(pattern, 'node', loopType);
|
|
516
|
-
return nodes.map(node => node.count);
|
|
517
|
-
}
|
|
518
|
-
/**
|
|
519
|
-
* The `lesserSumCount` function calculates the sum of the counts of all nodes in a binary tree that have a lesser
|
|
520
|
-
* value than a given node.
|
|
521
|
-
* @param {N | BinaryTreeNodeKey | null} beginNode - The `beginNode` parameter can be one of the following:
|
|
522
|
-
* @returns the sum of the counts of nodes in the binary tree that have a lesser value than the given beginNode.
|
|
523
|
-
*/
|
|
524
|
-
lesserSumCount(beginNode) {
|
|
525
|
-
if (typeof beginNode === 'number')
|
|
526
|
-
beginNode = this.get(beginNode, 'key');
|
|
527
|
-
if (!beginNode)
|
|
528
|
-
return 0;
|
|
529
|
-
if (!this.root)
|
|
530
|
-
return 0;
|
|
531
|
-
const key = beginNode.key;
|
|
532
|
-
let sum = 0;
|
|
533
|
-
if (this.loopType === LoopType.RECURSIVE) {
|
|
534
|
-
const _traverse = (cur) => {
|
|
535
|
-
const compared = this._compare(cur.key, key);
|
|
536
|
-
if (compared === CP.eq) {
|
|
537
|
-
if (cur.right)
|
|
538
|
-
sum += this.subTreeSumCount(cur.right);
|
|
539
|
-
return;
|
|
540
|
-
}
|
|
541
|
-
else if (compared === CP.lt) {
|
|
542
|
-
if (cur.left)
|
|
543
|
-
sum += this.subTreeSumCount(cur.left);
|
|
544
|
-
sum += cur.count;
|
|
545
|
-
if (cur.right)
|
|
546
|
-
_traverse(cur.right);
|
|
547
|
-
else
|
|
548
|
-
return;
|
|
549
|
-
}
|
|
550
|
-
else {
|
|
551
|
-
if (cur.left)
|
|
552
|
-
_traverse(cur.left);
|
|
553
|
-
else
|
|
554
|
-
return;
|
|
555
|
-
}
|
|
556
|
-
};
|
|
557
|
-
_traverse(this.root);
|
|
558
|
-
}
|
|
559
|
-
else {
|
|
560
|
-
const queue = [this.root];
|
|
561
|
-
while (queue.length > 0) {
|
|
562
|
-
const cur = queue.shift();
|
|
563
|
-
if (cur) {
|
|
564
|
-
const compared = this._compare(cur.key, key);
|
|
565
|
-
if (compared === CP.eq) {
|
|
566
|
-
if (cur.right)
|
|
567
|
-
sum += this.subTreeSumCount(cur.right);
|
|
568
|
-
return sum;
|
|
569
|
-
}
|
|
570
|
-
else if (compared === CP.lt) {
|
|
571
|
-
// todo maybe a bug
|
|
572
|
-
if (cur.left)
|
|
573
|
-
sum += this.subTreeSumCount(cur.left);
|
|
574
|
-
sum += cur.count;
|
|
575
|
-
if (cur.right)
|
|
576
|
-
queue.push(cur.right);
|
|
577
|
-
else
|
|
578
|
-
return sum;
|
|
579
|
-
}
|
|
580
|
-
else {
|
|
581
|
-
if (cur.left)
|
|
582
|
-
queue.push(cur.left);
|
|
583
|
-
else
|
|
584
|
-
return sum;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
return sum;
|
|
590
|
-
}
|
|
591
|
-
/**
|
|
592
|
-
* The function `allGreaterNodesAddCount` updates the count property of all nodes in a binary tree that have an ID
|
|
593
|
-
* greater than a given ID by a specified delta value.
|
|
594
|
-
* @param {N | BinaryTreeNodeKey | null} node - The `node` parameter can be one of the following:
|
|
595
|
-
* @param {number} delta - The `delta` parameter is a number that represents the amount by which the `count` property
|
|
596
|
-
* of each node should be increased.
|
|
597
|
-
* @returns a boolean value.
|
|
598
|
-
*/
|
|
599
|
-
allGreaterNodesAddCount(node, delta) {
|
|
600
|
-
if (typeof node === 'number')
|
|
601
|
-
node = this.get(node, 'key');
|
|
602
|
-
if (!node)
|
|
603
|
-
return false;
|
|
604
|
-
const key = node.key;
|
|
605
|
-
if (!this.root)
|
|
606
|
-
return false;
|
|
607
|
-
if (this.loopType === LoopType.RECURSIVE) {
|
|
608
|
-
const _traverse = (cur) => {
|
|
609
|
-
const compared = this._compare(cur.key, key);
|
|
610
|
-
if (compared === CP.gt)
|
|
611
|
-
cur.count += delta;
|
|
612
|
-
if (!cur.left && !cur.right)
|
|
613
|
-
return;
|
|
614
|
-
if (cur.left && this._compare(cur.left.key, key) === CP.gt)
|
|
615
|
-
_traverse(cur.left);
|
|
616
|
-
if (cur.right && this._compare(cur.right.key, key) === CP.gt)
|
|
617
|
-
_traverse(cur.right);
|
|
618
|
-
};
|
|
619
|
-
_traverse(this.root);
|
|
620
|
-
return true;
|
|
621
|
-
}
|
|
622
|
-
else {
|
|
623
|
-
const queue = [this.root];
|
|
624
|
-
while (queue.length > 0) {
|
|
625
|
-
const cur = queue.shift();
|
|
626
|
-
if (cur) {
|
|
627
|
-
const compared = this._compare(cur.key, key);
|
|
628
|
-
if (compared === CP.gt)
|
|
629
|
-
cur.count += delta;
|
|
630
|
-
if (cur.left && this._compare(cur.left.key, key) === CP.gt)
|
|
631
|
-
queue.push(cur.left);
|
|
632
|
-
if (cur.right && this._compare(cur.right.key, key) === CP.gt)
|
|
633
|
-
queue.push(cur.right);
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
return true;
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
402
|
/**
|
|
640
403
|
* The clear() function clears the data and sets the count to 0.
|
|
641
404
|
*/
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { arrayRemove, uuidV4 } from '../../utils';
|
|
9
9
|
import { PriorityQueue } from '../priority-queue';
|
|
10
|
+
import { Queue } from '../queue';
|
|
10
11
|
export class AbstractVertex {
|
|
11
12
|
/**
|
|
12
13
|
* The function is a protected constructor that takes an key and an optional value as parameters.
|
|
@@ -265,11 +266,11 @@ export class AbstractGraph {
|
|
|
265
266
|
return null;
|
|
266
267
|
}
|
|
267
268
|
const visited = new Map();
|
|
268
|
-
const queue = [vertex1];
|
|
269
|
+
const queue = new Queue([vertex1]);
|
|
269
270
|
visited.set(vertex1, true);
|
|
270
271
|
let cost = 0;
|
|
271
|
-
while (queue.
|
|
272
|
-
for (let i = 0; i < queue.
|
|
272
|
+
while (queue.size > 0) {
|
|
273
|
+
for (let i = 0; i < queue.size; i++) {
|
|
273
274
|
const cur = queue.shift();
|
|
274
275
|
if (cur === vertex2) {
|
|
275
276
|
return cost;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "data-structure-typed",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.37.0",
|
|
4
4
|
"description": "Data Structures of Javascript & TypeScript. Binary Tree, BST, Graph, Heap, Priority Queue, Linked List, Queue, Deque, Stack, AVL Tree, Tree Multiset, Trie, Directed Graph, Undirected Graph, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "lib/index.js",
|
|
@@ -33,8 +33,10 @@
|
|
|
33
33
|
"check:deps": "dependency-cruiser src",
|
|
34
34
|
"changelog": "auto-changelog",
|
|
35
35
|
"coverage:badge": "istanbul-badges-readme",
|
|
36
|
-
"ci": "env && npm run lint && npm run build && npm run update:individuals && npm run test &&
|
|
37
|
-
"publish:
|
|
36
|
+
"ci": "env && git fetch --tags && npm run lint && npm run build && npm run update:individuals && npm run test && npm run changelog",
|
|
37
|
+
"publish:individuals": "sh scripts/publish_all_subs.sh",
|
|
38
|
+
"publish:docs": "sh scripts/publish_docs.sh",
|
|
39
|
+
"publish:all": "npm run ci && npm publish && npm run publish:individuals && npm run publish:docs"
|
|
38
40
|
},
|
|
39
41
|
"repository": {
|
|
40
42
|
"type": "git",
|
|
@@ -56,17 +58,17 @@
|
|
|
56
58
|
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
|
57
59
|
"@typescript-eslint/parser": "^6.7.4",
|
|
58
60
|
"auto-changelog": "^2.4.0",
|
|
59
|
-
"avl-tree-typed": "^1.36.
|
|
61
|
+
"avl-tree-typed": "^1.36.9",
|
|
60
62
|
"benchmark": "^2.1.4",
|
|
61
|
-
"binary-tree-typed": "^1.36.
|
|
62
|
-
"bst-typed": "^1.36.
|
|
63
|
+
"binary-tree-typed": "^1.36.9",
|
|
64
|
+
"bst-typed": "^1.36.9",
|
|
63
65
|
"dependency-cruiser": "^14.1.0",
|
|
64
66
|
"eslint": "^8.50.0",
|
|
65
67
|
"eslint-config-prettier": "^9.0.0",
|
|
66
68
|
"eslint-import-resolver-alias": "^1.1.2",
|
|
67
69
|
"eslint-import-resolver-typescript": "^3.6.1",
|
|
68
70
|
"eslint-plugin-import": "^2.28.1",
|
|
69
|
-
"heap-typed": "^1.36.
|
|
71
|
+
"heap-typed": "^1.36.9",
|
|
70
72
|
"istanbul-badges-readme": "^1.8.5",
|
|
71
73
|
"jest": "^29.7.0",
|
|
72
74
|
"prettier": "^3.0.3",
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
} from '../../types';
|
|
24
24
|
import {IBinaryTree} from '../../interfaces';
|
|
25
25
|
import {trampoline} from '../../utils';
|
|
26
|
+
import {Queue} from '../queue';
|
|
26
27
|
|
|
27
28
|
export class BinaryTreeNode<V = any, FAMILY extends BinaryTreeNode<V, FAMILY> = BinaryTreeNodeNested<V>> {
|
|
28
29
|
/**
|
|
@@ -210,8 +211,8 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
210
211
|
*/
|
|
211
212
|
add(keyOrNode: BinaryTreeNodeKey | N | null, val?: N['val']): N | null | undefined {
|
|
212
213
|
const _bfs = (root: N, newNode: N | null): N | undefined | null => {
|
|
213
|
-
const queue
|
|
214
|
-
while (queue.
|
|
214
|
+
const queue = new Queue<N | null>([root]);
|
|
215
|
+
while (queue.size > 0) {
|
|
215
216
|
const cur = queue.shift();
|
|
216
217
|
if (cur) {
|
|
217
218
|
if (newNode && cur.key === newNode.key) return;
|
|
@@ -509,8 +510,8 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
509
510
|
|
|
510
511
|
_traverse(this.root);
|
|
511
512
|
} else {
|
|
512
|
-
const queue
|
|
513
|
-
while (queue.
|
|
513
|
+
const queue = new Queue<N>([this.root]);
|
|
514
|
+
while (queue.size > 0) {
|
|
514
515
|
const cur = queue.shift();
|
|
515
516
|
if (cur) {
|
|
516
517
|
if (this._pushByPropertyNameStopOrNot(cur, result, nodeProperty, propertyName, onlyOne)) return result;
|
|
@@ -762,65 +763,11 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
762
763
|
}
|
|
763
764
|
}
|
|
764
765
|
|
|
765
|
-
/**
|
|
766
|
-
* The function `subTreeSum` calculates the sum of a specified property in a binary tree or subtree.
|
|
767
|
-
* @param {N | BinaryTreeNodeKey | null} subTreeRoot - The `subTreeRoot` parameter represents the root node of a binary
|
|
768
|
-
* tree or the ID of a binary tree node. It can also be `null` if there is no subtree.
|
|
769
|
-
* @param {BinaryTreeNodePropertyName} [propertyName] - propertyName is an optional parameter that specifies the
|
|
770
|
-
* property of the binary tree node to use for calculating the sum. It can be either 'key' or 'val'. If propertyName is
|
|
771
|
-
* not provided, it defaults to 'key'.
|
|
772
|
-
* @returns a number, which is the sum of the values of the specified property in the subtree rooted at `subTreeRoot`.
|
|
773
|
-
*/
|
|
774
|
-
subTreeSum(subTreeRoot: N | BinaryTreeNodeKey | null, propertyName: BinaryTreeNodePropertyName = 'key'): number {
|
|
775
|
-
if (typeof subTreeRoot === 'number') subTreeRoot = this.get(subTreeRoot, 'key');
|
|
776
|
-
|
|
777
|
-
if (!subTreeRoot) return 0;
|
|
778
|
-
|
|
779
|
-
let sum = 0;
|
|
780
|
-
|
|
781
|
-
const _sumByProperty = (cur: N) => {
|
|
782
|
-
let needSum: number;
|
|
783
|
-
switch (propertyName) {
|
|
784
|
-
case 'key':
|
|
785
|
-
needSum = cur.key;
|
|
786
|
-
break;
|
|
787
|
-
case 'val':
|
|
788
|
-
needSum = typeof cur.val === 'number' ? cur.val : 0;
|
|
789
|
-
break;
|
|
790
|
-
default:
|
|
791
|
-
needSum = cur.key;
|
|
792
|
-
break;
|
|
793
|
-
}
|
|
794
|
-
return needSum;
|
|
795
|
-
};
|
|
796
|
-
|
|
797
|
-
if (this._loopType === LoopType.RECURSIVE) {
|
|
798
|
-
const _traverse = (cur: N): void => {
|
|
799
|
-
sum += _sumByProperty(cur);
|
|
800
|
-
cur.left && _traverse(cur.left);
|
|
801
|
-
cur.right && _traverse(cur.right);
|
|
802
|
-
};
|
|
803
|
-
|
|
804
|
-
_traverse(subTreeRoot);
|
|
805
|
-
} else {
|
|
806
|
-
const stack: N[] = [subTreeRoot];
|
|
807
|
-
|
|
808
|
-
while (stack.length > 0) {
|
|
809
|
-
const cur = stack.pop()!;
|
|
810
|
-
sum += _sumByProperty(cur);
|
|
811
|
-
cur.right && stack.push(cur.right);
|
|
812
|
-
cur.left && stack.push(cur.left);
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
return sum;
|
|
817
|
-
}
|
|
818
|
-
|
|
819
766
|
/**
|
|
820
767
|
* The function `subTreeForeach` adds a delta value to a specified property of each node in a subtree.
|
|
821
768
|
* @param {N | BinaryTreeNodeKey | null} subTreeRoot - The `subTreeRoot` parameter represents the root node of a binary
|
|
822
769
|
* tree or the ID of a node in the binary tree. It can also be `null` if there is no subtree to add to.
|
|
823
|
-
* @param
|
|
770
|
+
* @param callback - The `callback` parameter is a function that takes a node as a parameter and returns a value.
|
|
824
771
|
* specifies the property of the binary tree node that should be modified. If not provided, it defaults to 'key'.
|
|
825
772
|
* @returns a boolean value.
|
|
826
773
|
*/
|
|
@@ -887,10 +834,9 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
887
834
|
*/
|
|
888
835
|
bfs(nodeOrPropertyName: NodeOrPropertyName = 'key'): BinaryTreeNodeProperties<N> {
|
|
889
836
|
this._clearResults();
|
|
890
|
-
const queue
|
|
837
|
+
const queue = new Queue<N | null | undefined>([this.root]);
|
|
891
838
|
|
|
892
|
-
while (queue.
|
|
893
|
-
// TODO Array.shift is not efficient, consider using Deque
|
|
839
|
+
while (queue.size !== 0) {
|
|
894
840
|
const cur = queue.shift();
|
|
895
841
|
if (cur) {
|
|
896
842
|
this._accumulatedByPropertyName(cur, nodeOrPropertyName);
|
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
import {CP, LoopType} from '../../types';
|
|
16
16
|
import {BinaryTree, BinaryTreeNode} from './binary-tree';
|
|
17
17
|
import {IBinaryTree} from '../../interfaces';
|
|
18
|
+
import {Queue} from '../queue';
|
|
18
19
|
|
|
19
20
|
export class BSTNode<V = any, FAMILY extends BSTNode<V, FAMILY> = BSTNodeNested<V>> extends BinaryTreeNode<V, FAMILY> {
|
|
20
21
|
constructor(key: BinaryTreeNodeKey, val?: V) {
|
|
@@ -59,7 +60,7 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|
|
59
60
|
* @returns The function `add` returns the inserted node (`inserted`) which can be of type `N`, `null`, or `undefined`.
|
|
60
61
|
*/
|
|
61
62
|
override add(keyOrNode: BinaryTreeNodeKey | N | null, val?: N['val']): N | null | undefined {
|
|
62
|
-
// TODO support node as a
|
|
63
|
+
// TODO support node as a parameter
|
|
63
64
|
let inserted: N | null = null;
|
|
64
65
|
let newNode: N | null = null;
|
|
65
66
|
if (keyOrNode instanceof BSTNode) {
|
|
@@ -137,8 +138,9 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|
|
137
138
|
override addMany(
|
|
138
139
|
keysOrNodes: (BinaryTreeNodeKey | null)[] | (N | null)[],
|
|
139
140
|
data?: N['val'][],
|
|
140
|
-
isBalanceAdd =
|
|
141
|
+
isBalanceAdd = true
|
|
141
142
|
): (N | null | undefined)[] {
|
|
143
|
+
// TODO this addMany function is inefficient, it should be optimized
|
|
142
144
|
function hasNoNull(arr: (BinaryTreeNodeKey | null)[] | (N | null)[]): arr is BinaryTreeNodeKey[] | N[] {
|
|
143
145
|
return arr.indexOf(null) === -1;
|
|
144
146
|
}
|
|
@@ -265,8 +267,8 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|
|
265
267
|
|
|
266
268
|
_traverse(this.root);
|
|
267
269
|
} else {
|
|
268
|
-
const queue
|
|
269
|
-
while (queue.
|
|
270
|
+
const queue = new Queue<N>([this.root]);
|
|
271
|
+
while (queue.size > 0) {
|
|
270
272
|
const cur = queue.shift();
|
|
271
273
|
if (cur) {
|
|
272
274
|
if (this._pushByPropertyNameStopOrNot(cur, result, nodeProperty, propertyName, onlyOne)) return result;
|
|
@@ -285,133 +287,47 @@ export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N>
|
|
|
285
287
|
}
|
|
286
288
|
|
|
287
289
|
// --- start additional functions
|
|
288
|
-
/**
|
|
289
|
-
* The `lesserSum` function calculates the sum of property values in a binary tree for nodes that have a property value
|
|
290
|
-
* less than a given node.
|
|
291
|
-
* @param {N | BinaryTreeNodeKey | null} beginNode - The `beginNode` parameter can be one of the following:
|
|
292
|
-
* @param {BinaryTreeNodePropertyName} [propertyName] - The `propertyName` parameter is an optional parameter that
|
|
293
|
-
* specifies the property name to use for calculating the sum. If not provided, it defaults to `'key'`.
|
|
294
|
-
* @returns The function `lesserSum` returns a number, which represents the sum of the values of the nodes in the
|
|
295
|
-
* binary tree that have a lesser value than the specified `beginNode` based on the `propertyName`.
|
|
296
|
-
*/
|
|
297
|
-
lesserSum(beginNode: N | BinaryTreeNodeKey | null, propertyName: BinaryTreeNodePropertyName = 'key'): number {
|
|
298
|
-
if (typeof beginNode === 'number') beginNode = this.get(beginNode, 'key');
|
|
299
|
-
if (!beginNode) return 0;
|
|
300
|
-
if (!this.root) return 0;
|
|
301
|
-
const key = beginNode.key;
|
|
302
|
-
const getSumByPropertyName = (cur: N) => {
|
|
303
|
-
let needSum: number;
|
|
304
|
-
switch (propertyName) {
|
|
305
|
-
case 'key':
|
|
306
|
-
needSum = cur.key;
|
|
307
|
-
break;
|
|
308
|
-
default:
|
|
309
|
-
needSum = cur.key;
|
|
310
|
-
break;
|
|
311
|
-
}
|
|
312
|
-
return needSum;
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
let sum = 0;
|
|
316
|
-
|
|
317
|
-
if (this.loopType === LoopType.RECURSIVE) {
|
|
318
|
-
const _traverse = (cur: N): void => {
|
|
319
|
-
const compared = this._compare(cur.key, key);
|
|
320
|
-
if (compared === CP.eq) {
|
|
321
|
-
if (cur.right) sum += this.subTreeSum(cur.right, propertyName);
|
|
322
|
-
return;
|
|
323
|
-
} else if (compared === CP.lt) {
|
|
324
|
-
if (cur.left) sum += this.subTreeSum(cur.left, propertyName);
|
|
325
|
-
sum += getSumByPropertyName(cur);
|
|
326
|
-
if (cur.right) _traverse(cur.right);
|
|
327
|
-
else return;
|
|
328
|
-
} else {
|
|
329
|
-
if (cur.left) _traverse(cur.left);
|
|
330
|
-
else return;
|
|
331
|
-
}
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
_traverse(this.root);
|
|
335
|
-
} else {
|
|
336
|
-
const queue: N[] = [this.root];
|
|
337
|
-
while (queue.length > 0) {
|
|
338
|
-
const cur = queue.shift();
|
|
339
|
-
if (cur) {
|
|
340
|
-
const compared = this._compare(cur.key, key);
|
|
341
|
-
if (compared === CP.eq) {
|
|
342
|
-
if (cur.right) sum += this.subTreeSum(cur.right, propertyName);
|
|
343
|
-
return sum;
|
|
344
|
-
} else if (compared === CP.lt) {
|
|
345
|
-
// todo maybe a bug
|
|
346
|
-
if (cur.left) sum += this.subTreeSum(cur.left, propertyName);
|
|
347
|
-
sum += getSumByPropertyName(cur);
|
|
348
|
-
if (cur.right) queue.push(cur.right);
|
|
349
|
-
else return sum;
|
|
350
|
-
} else {
|
|
351
|
-
if (cur.left) queue.push(cur.left);
|
|
352
|
-
else return sum;
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
return sum;
|
|
359
|
-
}
|
|
360
290
|
|
|
361
291
|
/**
|
|
362
|
-
* The `
|
|
292
|
+
* The `lesserOrGreaterForeach` function adds a delta value to the specified property of all nodes in a binary tree that
|
|
363
293
|
* have a greater value than a given node.
|
|
364
|
-
* @param {N | BinaryTreeNodeKey | null} node - The `node` parameter can be either of type `N` (a generic type),
|
|
365
|
-
*
|
|
366
|
-
* @param
|
|
367
|
-
*
|
|
368
|
-
* @param {BinaryTreeNodePropertyName} [propertyName] - The `propertyName` parameter is an optional parameter that
|
|
369
|
-
* specifies the property name of the nodes in the binary tree that you want to update. If not provided, it defaults to
|
|
370
|
-
* 'key'.
|
|
371
|
-
* @returns a boolean value.
|
|
294
|
+
* @param {N | BinaryTreeNodeKey | null} node - The `node` parameter can be either of type `N` (a generic type), `BinaryTreeNodeKey`, or `null`. It
|
|
295
|
+
* represents the node in the binary tree to which the delta value will be added.
|
|
296
|
+
* @param lesserOrGreater - The `lesserOrGreater` parameter is an optional parameter that specifies whether the delta
|
|
297
|
+
* @param callback - The `callback` parameter is a function that takes a node as a parameter and returns a boolean
|
|
372
298
|
*/
|
|
373
|
-
|
|
299
|
+
lesserOrGreaterForeach(
|
|
374
300
|
node: N | BinaryTreeNodeKey | null,
|
|
375
|
-
|
|
376
|
-
|
|
301
|
+
lesserOrGreater: CP = CP.lt,
|
|
302
|
+
callback: (node: N) => void
|
|
377
303
|
): boolean {
|
|
378
304
|
if (typeof node === 'number') node = this.get(node, 'key');
|
|
379
305
|
if (!node) return false;
|
|
380
306
|
const key = node.key;
|
|
381
307
|
if (!this.root) return false;
|
|
382
308
|
|
|
383
|
-
const _sumByPropertyName = (cur: N) => {
|
|
384
|
-
switch (propertyName) {
|
|
385
|
-
case 'key':
|
|
386
|
-
cur.key += delta;
|
|
387
|
-
break;
|
|
388
|
-
default:
|
|
389
|
-
cur.key += delta;
|
|
390
|
-
break;
|
|
391
|
-
}
|
|
392
|
-
};
|
|
393
309
|
if (this.loopType === LoopType.RECURSIVE) {
|
|
394
310
|
const _traverse = (cur: N) => {
|
|
395
311
|
const compared = this._compare(cur.key, key);
|
|
396
|
-
if (compared ===
|
|
312
|
+
if (compared === lesserOrGreater) callback(cur);
|
|
397
313
|
|
|
398
314
|
if (!cur.left && !cur.right) return;
|
|
399
|
-
if (cur.left && this._compare(cur.left.key, key) ===
|
|
400
|
-
if (cur.right && this._compare(cur.right.key, key) ===
|
|
315
|
+
if (cur.left && this._compare(cur.left.key, key) === lesserOrGreater) _traverse(cur.left);
|
|
316
|
+
if (cur.right && this._compare(cur.right.key, key) === lesserOrGreater) _traverse(cur.right);
|
|
401
317
|
};
|
|
402
318
|
|
|
403
319
|
_traverse(this.root);
|
|
404
320
|
return true;
|
|
405
321
|
} else {
|
|
406
|
-
const queue
|
|
407
|
-
while (queue.
|
|
322
|
+
const queue = new Queue<N>([this.root]);
|
|
323
|
+
while (queue.size > 0) {
|
|
408
324
|
const cur = queue.shift();
|
|
409
325
|
if (cur) {
|
|
410
326
|
const compared = this._compare(cur.key, key);
|
|
411
|
-
if (compared ===
|
|
327
|
+
if (compared === lesserOrGreater) callback(cur);
|
|
412
328
|
|
|
413
|
-
if (cur.left && this._compare(cur.left.key, key) ===
|
|
414
|
-
if (cur.right && this._compare(cur.right.key, key) ===
|
|
329
|
+
if (cur.left && this._compare(cur.left.key, key) === lesserOrGreater) queue.push(cur.left);
|
|
330
|
+
if (cur.right && this._compare(cur.right.key, key) === lesserOrGreater) queue.push(cur.right);
|
|
415
331
|
}
|
|
416
332
|
}
|
|
417
333
|
return true;
|