data-structure-typed 1.36.9 → 1.37.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +100 -504
- package/src/data-structures/binary-tree/bst.ts +58 -128
- package/src/data-structures/binary-tree/tree-multiset.ts +2 -312
- package/src/data-structures/graph/abstract-graph.ts +4 -3
- package/src/data-structures/heap/heap.ts +1 -1
- package/src/types/data-structures/binary-tree.ts +4 -0
- package/src/types/data-structures/index.ts +3 -0
- package/test/unit/data-structures/binary-tree/avl-tree.test.ts +14 -9
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +1 -1
- package/test/unit/data-structures/binary-tree/bst.test.ts +85 -18
- package/test/unit/data-structures/binary-tree/overall.test.ts +3 -2
- package/test/unit/data-structures/binary-tree/rb-tree.test.ts +5 -5
- package/test/unit/data-structures/binary-tree/tree-multiset.test.ts +43 -18
- package/test/unit/data-structures/priority-queue/max-priority-queue.test.ts +1 -1
- 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,9 +1,9 @@
|
|
|
1
|
-
import {AVLTree} from '../../../../src';
|
|
1
|
+
import {AVLTree, CP, AVLTreeNode} from '../../../../src';
|
|
2
2
|
|
|
3
3
|
describe('AVL Tree Test', () => {
|
|
4
4
|
it('should perform various operations on a AVL Tree', () => {
|
|
5
5
|
const arr = [11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5];
|
|
6
|
-
const tree = new AVLTree();
|
|
6
|
+
const tree = new AVLTree<AVLTreeNode<number>>();
|
|
7
7
|
|
|
8
8
|
for (const i of arr) tree.add(i, i);
|
|
9
9
|
|
|
@@ -12,7 +12,7 @@ describe('AVL Tree Test', () => {
|
|
|
12
12
|
expect(node6 && tree.getHeight(node6)).toBe(3);
|
|
13
13
|
expect(node6 && tree.getDepth(node6)).toBe(1);
|
|
14
14
|
|
|
15
|
-
const getNodeById = tree.get(10
|
|
15
|
+
const getNodeById = tree.get(10);
|
|
16
16
|
expect(getNodeById?.key).toBe(10);
|
|
17
17
|
|
|
18
18
|
const getMinNodeByRoot = tree.getLeftMost();
|
|
@@ -22,21 +22,24 @@ describe('AVL Tree Test', () => {
|
|
|
22
22
|
const getMinNodeBySpecificNode = node15 && tree.getLeftMost(node15);
|
|
23
23
|
expect(getMinNodeBySpecificNode?.key).toBe(12);
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
let subTreeSum = 0;
|
|
26
|
+
node15 && tree.subTreeTraverse(node => (subTreeSum += node.key), node15);
|
|
26
27
|
expect(subTreeSum).toBe(70);
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
let lesserSum = 0;
|
|
30
|
+
tree.lesserOrGreaterTraverse(node => (lesserSum += node.key), CP.lt, 10);
|
|
29
31
|
expect(lesserSum).toBe(45);
|
|
30
32
|
|
|
31
33
|
// node15 has type problem. After the uniform design, the generics of containers (DirectedGraph, BST) are based on the type of value. However, this design has a drawback: when I attempt to inherit from the Vertex or BSTNode classes, the types of the results obtained by all methods are those of the parent class.
|
|
32
34
|
expect(node15?.val).toBe(15);
|
|
33
35
|
|
|
34
|
-
const dfs = tree.dfs(
|
|
36
|
+
const dfs = tree.dfs(node => node, 'in');
|
|
35
37
|
expect(dfs[0].key).toBe(1);
|
|
36
38
|
expect(dfs[dfs.length - 1].key).toBe(16);
|
|
37
39
|
|
|
38
40
|
tree.perfectlyBalance();
|
|
39
|
-
const bfs =
|
|
41
|
+
const bfs: AVLTreeNode<number>[] = [];
|
|
42
|
+
tree.bfs(node => bfs.push(node));
|
|
40
43
|
expect(tree.isPerfectlyBalanced()).toBe(true);
|
|
41
44
|
expect(bfs[0].key).toBe(8);
|
|
42
45
|
expect(bfs[bfs.length - 1].key).toBe(16);
|
|
@@ -95,12 +98,14 @@ describe('AVL Tree Test', () => {
|
|
|
95
98
|
expect(tree.getHeight()).toBe(1);
|
|
96
99
|
|
|
97
100
|
expect(tree.isAVLBalanced()).toBe(true);
|
|
98
|
-
const lastBFSIds =
|
|
101
|
+
const lastBFSIds = new Array<number>();
|
|
102
|
+
tree.bfs(node => lastBFSIds.push(node.key));
|
|
99
103
|
expect(lastBFSIds[0]).toBe(12);
|
|
100
104
|
expect(lastBFSIds[1]).toBe(2);
|
|
101
105
|
expect(lastBFSIds[2]).toBe(16);
|
|
102
106
|
|
|
103
|
-
const lastBFSNodes =
|
|
107
|
+
const lastBFSNodes: AVLTreeNode<number>[] = [];
|
|
108
|
+
tree.bfs(node => lastBFSNodes.push(node));
|
|
104
109
|
expect(lastBFSNodes[0].key).toBe(12);
|
|
105
110
|
expect(lastBFSNodes[1].key).toBe(2);
|
|
106
111
|
expect(lastBFSNodes[2].key).toBe(16);
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {BST, BSTNode} from '../../../../src';
|
|
1
|
+
import {BST, BSTNode, CP} from '../../../../src';
|
|
2
|
+
|
|
3
|
+
const isDebug = true;
|
|
2
4
|
|
|
3
5
|
describe('BST operations test', () => {
|
|
4
6
|
it('should perform various operations on a Binary Search Tree with numeric values', () => {
|
|
@@ -7,7 +9,7 @@ describe('BST operations test', () => {
|
|
|
7
9
|
bst.add(11, 11);
|
|
8
10
|
bst.add(3, 3);
|
|
9
11
|
const idsAndValues = [15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5];
|
|
10
|
-
bst.addMany(idsAndValues, idsAndValues);
|
|
12
|
+
bst.addMany(idsAndValues, idsAndValues, false);
|
|
11
13
|
expect(bst.root).toBeInstanceOf(BSTNode);
|
|
12
14
|
|
|
13
15
|
if (bst.root) expect(bst.root.key).toBe(11);
|
|
@@ -23,7 +25,7 @@ describe('BST operations test', () => {
|
|
|
23
25
|
const nodeId10 = bst.get(10);
|
|
24
26
|
expect(nodeId10?.key).toBe(10);
|
|
25
27
|
|
|
26
|
-
const nodeVal9 = bst.get(9,
|
|
28
|
+
const nodeVal9 = bst.get(9, node => node.val);
|
|
27
29
|
expect(nodeVal9?.key).toBe(9);
|
|
28
30
|
|
|
29
31
|
const leftMost = bst.getLeftMost();
|
|
@@ -33,10 +35,12 @@ describe('BST operations test', () => {
|
|
|
33
35
|
const minNodeBySpecificNode = node15 && bst.getLeftMost(node15);
|
|
34
36
|
expect(minNodeBySpecificNode?.key).toBe(12);
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
let subTreeSum = 0;
|
|
39
|
+
node15 && bst.subTreeTraverse(node => (subTreeSum += node.key), 15);
|
|
37
40
|
expect(subTreeSum).toBe(70);
|
|
38
41
|
|
|
39
|
-
|
|
42
|
+
let lesserSum = 0;
|
|
43
|
+
bst.lesserOrGreaterTraverse(node => (lesserSum += node.key), CP.lt, 10);
|
|
40
44
|
expect(lesserSum).toBe(45);
|
|
41
45
|
|
|
42
46
|
expect(node15).toBeInstanceOf(BSTNode);
|
|
@@ -44,14 +48,15 @@ describe('BST operations test', () => {
|
|
|
44
48
|
const node11 = bst.get(11);
|
|
45
49
|
expect(node11).toBeInstanceOf(BSTNode);
|
|
46
50
|
|
|
47
|
-
const dfsInorderNodes = bst.dfs(
|
|
51
|
+
const dfsInorderNodes = bst.dfs(node => node, 'in');
|
|
48
52
|
expect(dfsInorderNodes[0].key).toBe(1);
|
|
49
53
|
expect(dfsInorderNodes[dfsInorderNodes.length - 1].key).toBe(16);
|
|
50
54
|
|
|
51
55
|
bst.perfectlyBalance();
|
|
52
56
|
expect(bst.isPerfectlyBalanced()).toBe(true);
|
|
53
57
|
|
|
54
|
-
const bfsNodesAfterBalanced =
|
|
58
|
+
const bfsNodesAfterBalanced: BSTNode<number>[] = [];
|
|
59
|
+
bst.bfs(node => bfsNodesAfterBalanced.push(node));
|
|
55
60
|
expect(bfsNodesAfterBalanced[0].key).toBe(8);
|
|
56
61
|
expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16);
|
|
57
62
|
|
|
@@ -169,12 +174,14 @@ describe('BST operations test', () => {
|
|
|
169
174
|
|
|
170
175
|
expect(bst.isAVLBalanced()).toBe(false);
|
|
171
176
|
|
|
172
|
-
const bfsIDs =
|
|
177
|
+
const bfsIDs: number[] = [];
|
|
178
|
+
bst.bfs(node => bfsIDs.push(node.key));
|
|
173
179
|
expect(bfsIDs[0]).toBe(2);
|
|
174
180
|
expect(bfsIDs[1]).toBe(12);
|
|
175
181
|
expect(bfsIDs[2]).toBe(16);
|
|
176
182
|
|
|
177
|
-
const bfsNodes =
|
|
183
|
+
const bfsNodes: BSTNode<number>[] = [];
|
|
184
|
+
bst.bfs(node => bfsNodes.push(node));
|
|
178
185
|
expect(bfsNodes[0].key).toBe(2);
|
|
179
186
|
expect(bfsNodes[1].key).toBe(12);
|
|
180
187
|
expect(bfsNodes[2].key).toBe(16);
|
|
@@ -204,7 +211,8 @@ describe('BST operations test', () => {
|
|
|
204
211
|
|
|
205
212
|
objBST.addMany(
|
|
206
213
|
values.map(item => item.key),
|
|
207
|
-
values
|
|
214
|
+
values,
|
|
215
|
+
false
|
|
208
216
|
);
|
|
209
217
|
|
|
210
218
|
expect(objBST.root).toBeInstanceOf(BSTNode);
|
|
@@ -217,10 +225,10 @@ describe('BST operations test', () => {
|
|
|
217
225
|
expect(node6 && objBST.getHeight(node6)).toBe(2);
|
|
218
226
|
expect(node6 && objBST.getDepth(node6)).toBe(3);
|
|
219
227
|
|
|
220
|
-
const nodeId10 = objBST.get(10
|
|
228
|
+
const nodeId10 = objBST.get(10);
|
|
221
229
|
expect(nodeId10?.key).toBe(10);
|
|
222
230
|
|
|
223
|
-
const nodeVal9 = objBST.get(9
|
|
231
|
+
const nodeVal9 = objBST.get(9);
|
|
224
232
|
expect(nodeVal9?.key).toBe(9);
|
|
225
233
|
|
|
226
234
|
const leftMost = objBST.getLeftMost();
|
|
@@ -231,10 +239,12 @@ describe('BST operations test', () => {
|
|
|
231
239
|
const minNodeBySpecificNode = node15 && objBST.getLeftMost(node15);
|
|
232
240
|
expect(minNodeBySpecificNode?.key).toBe(12);
|
|
233
241
|
|
|
234
|
-
|
|
242
|
+
let subTreeSum = 0;
|
|
243
|
+
node15 && objBST.subTreeTraverse(node => (subTreeSum += node.key), node15);
|
|
235
244
|
expect(subTreeSum).toBe(70);
|
|
236
245
|
|
|
237
|
-
|
|
246
|
+
let lesserSum = 0;
|
|
247
|
+
objBST.lesserOrGreaterTraverse(node => (lesserSum += node.key), CP.lt, 10);
|
|
238
248
|
expect(lesserSum).toBe(45);
|
|
239
249
|
|
|
240
250
|
expect(node15).toBeInstanceOf(BSTNode);
|
|
@@ -242,14 +252,15 @@ describe('BST operations test', () => {
|
|
|
242
252
|
const node11 = objBST.get(11);
|
|
243
253
|
expect(node11).toBeInstanceOf(BSTNode);
|
|
244
254
|
|
|
245
|
-
const dfsInorderNodes = objBST.dfs(
|
|
255
|
+
const dfsInorderNodes = objBST.dfs(node => node, 'in');
|
|
246
256
|
expect(dfsInorderNodes[0].key).toBe(1);
|
|
247
257
|
expect(dfsInorderNodes[dfsInorderNodes.length - 1].key).toBe(16);
|
|
248
258
|
|
|
249
259
|
objBST.perfectlyBalance();
|
|
250
260
|
expect(objBST.isPerfectlyBalanced()).toBe(true);
|
|
251
261
|
|
|
252
|
-
const bfsNodesAfterBalanced =
|
|
262
|
+
const bfsNodesAfterBalanced: BSTNode<{key: number; keyA: number}>[] = [];
|
|
263
|
+
objBST.bfs(node => bfsNodesAfterBalanced.push(node));
|
|
253
264
|
expect(bfsNodesAfterBalanced[0].key).toBe(8);
|
|
254
265
|
expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16);
|
|
255
266
|
|
|
@@ -367,14 +378,70 @@ describe('BST operations test', () => {
|
|
|
367
378
|
|
|
368
379
|
expect(objBST.isAVLBalanced()).toBe(false);
|
|
369
380
|
|
|
370
|
-
const bfsIDs =
|
|
381
|
+
const bfsIDs: number[] = [];
|
|
382
|
+
objBST.bfs(node => bfsIDs.push(node.key));
|
|
371
383
|
expect(bfsIDs[0]).toBe(2);
|
|
372
384
|
expect(bfsIDs[1]).toBe(12);
|
|
373
385
|
expect(bfsIDs[2]).toBe(16);
|
|
374
386
|
|
|
375
|
-
const bfsNodes =
|
|
387
|
+
const bfsNodes: BSTNode<{key: number; keyA: number}>[] = [];
|
|
388
|
+
objBST.bfs(node => bfsNodes.push(node));
|
|
376
389
|
expect(bfsNodes[0].key).toBe(2);
|
|
377
390
|
expect(bfsNodes[1].key).toBe(12);
|
|
378
391
|
expect(bfsNodes[2].key).toBe(16);
|
|
379
392
|
});
|
|
380
393
|
});
|
|
394
|
+
|
|
395
|
+
describe('BST Performance test', function () {
|
|
396
|
+
const bst = new BST<BSTNode<number>>();
|
|
397
|
+
const inputSize = 10000; // Adjust input sizes as needed
|
|
398
|
+
|
|
399
|
+
beforeEach(() => {
|
|
400
|
+
bst.clear();
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
it(`Observe the time consumption of BST.dfs be good`, function () {
|
|
404
|
+
const startDFS = performance.now();
|
|
405
|
+
const dfs = bst.dfs(node => node);
|
|
406
|
+
isDebug && console.log('---bfs', performance.now() - startDFS, dfs.length);
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
it('Should the time consumption of lesserOrGreaterTraverse fitting O(n log n)', function () {
|
|
410
|
+
const nodes: number[] = [];
|
|
411
|
+
for (let i = 0; i < inputSize; i++) {
|
|
412
|
+
nodes.push(i);
|
|
413
|
+
}
|
|
414
|
+
const start = performance.now();
|
|
415
|
+
bst.addMany(nodes);
|
|
416
|
+
isDebug && console.log('---add', performance.now() - start);
|
|
417
|
+
const startL = performance.now();
|
|
418
|
+
bst.lesserOrGreaterTraverse(
|
|
419
|
+
node => {
|
|
420
|
+
node.key - 1;
|
|
421
|
+
},
|
|
422
|
+
CP.lt,
|
|
423
|
+
inputSize / 2
|
|
424
|
+
);
|
|
425
|
+
isDebug && console.log('---lesserOrGreaterTraverse', performance.now() - startL);
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
it('Should the time consumption of listLevels fitting well', function () {
|
|
429
|
+
const nodes: number[] = [];
|
|
430
|
+
for (let i = 0; i < inputSize; i++) {
|
|
431
|
+
nodes.push(i);
|
|
432
|
+
}
|
|
433
|
+
const start = performance.now();
|
|
434
|
+
bst.addMany(nodes);
|
|
435
|
+
isDebug && console.log('---add', performance.now() - start);
|
|
436
|
+
const startL = performance.now();
|
|
437
|
+
const arr: number[][] = [];
|
|
438
|
+
bst.bfs((node, level) => {
|
|
439
|
+
if (level !== undefined) {
|
|
440
|
+
if (!arr[level]) arr[level] = [];
|
|
441
|
+
arr[level].push(node.key);
|
|
442
|
+
}
|
|
443
|
+
}, true);
|
|
444
|
+
isDebug && console.log('---listLevels', arr);
|
|
445
|
+
isDebug && console.log('---listLevels', performance.now() - startL);
|
|
446
|
+
});
|
|
447
|
+
});
|
|
@@ -5,7 +5,7 @@ describe('Overall BinaryTree Test', () => {
|
|
|
5
5
|
const bst = new BST();
|
|
6
6
|
bst.add(11);
|
|
7
7
|
bst.add(3);
|
|
8
|
-
bst.addMany([15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
|
|
8
|
+
bst.addMany([15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5], undefined, false);
|
|
9
9
|
bst.size === 16; // true
|
|
10
10
|
expect(bst.size).toBe(16); // true
|
|
11
11
|
bst.has(6); // true
|
|
@@ -24,7 +24,8 @@ describe('Overall BinaryTree Test', () => {
|
|
|
24
24
|
expect(bst.get(6)).toBeNull();
|
|
25
25
|
bst.isAVLBalanced(); // true or false
|
|
26
26
|
expect(bst.isAVLBalanced()).toBe(true);
|
|
27
|
-
const bfsIDs =
|
|
27
|
+
const bfsIDs: number[] = [];
|
|
28
|
+
bst.bfs(node => bfsIDs.push(node.key));
|
|
28
29
|
bfsIDs[0] === 11; // true
|
|
29
30
|
expect(bfsIDs[0]).toBe(11);
|
|
30
31
|
|
|
@@ -7,7 +7,7 @@ describe('Red-Black Tree Tests', () => {
|
|
|
7
7
|
// tree = new RBTree<RBTreeNode<number>>();
|
|
8
8
|
// });
|
|
9
9
|
|
|
10
|
-
test('Insertion and In-order
|
|
10
|
+
test('Insertion and In-order Traverse', () => {
|
|
11
11
|
// tree.add(5);
|
|
12
12
|
// tree.add(3);
|
|
13
13
|
// tree.add(7);
|
|
@@ -16,9 +16,9 @@ describe('Red-Black Tree Tests', () => {
|
|
|
16
16
|
// tree.add(6);
|
|
17
17
|
// tree.add(8);
|
|
18
18
|
//
|
|
19
|
-
// const
|
|
19
|
+
// const inOrderTraverse: number[] = tree.DFS('in')
|
|
20
20
|
//
|
|
21
|
-
// expect(
|
|
21
|
+
// expect(inOrderTraverse).toEqual([2, 3, 4, 5, 6, 7, 8]);
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
test('Deletion', () => {
|
|
@@ -35,9 +35,9 @@ describe('Red-Black Tree Tests', () => {
|
|
|
35
35
|
// expect(tree.has(3)).toBe(false);
|
|
36
36
|
//
|
|
37
37
|
// // Perform in-order traversal to check if the tree is still balanced
|
|
38
|
-
// const
|
|
38
|
+
// const inOrderTraverse: number[] = tree.DFS('in');
|
|
39
39
|
//
|
|
40
40
|
//
|
|
41
|
-
// expect(
|
|
41
|
+
// expect(inOrderTraverse).toEqual([2, 4, 5, 6, 7, 8]);
|
|
42
42
|
});
|
|
43
43
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {TreeMultiset, TreeMultisetNode} from '../../../../src';
|
|
1
|
+
import {CP, TreeMultiset, TreeMultisetNode} from '../../../../src';
|
|
2
2
|
|
|
3
|
+
const isDebug = false;
|
|
3
4
|
describe('TreeMultiset operations test', () => {
|
|
4
5
|
it('should perform various operations on a Binary Search Tree with numeric values', () => {
|
|
5
6
|
const treeMultiset = new TreeMultiset();
|
|
@@ -15,7 +16,6 @@ describe('TreeMultiset operations test', () => {
|
|
|
15
16
|
|
|
16
17
|
expect(treeMultiset.size).toBe(16);
|
|
17
18
|
expect(treeMultiset.count).toBe(18);
|
|
18
|
-
expect(treeMultiset.bfs('key'));
|
|
19
19
|
|
|
20
20
|
expect(treeMultiset.has(6));
|
|
21
21
|
|
|
@@ -24,13 +24,13 @@ describe('TreeMultiset operations test', () => {
|
|
|
24
24
|
const nodeId10 = treeMultiset.get(10);
|
|
25
25
|
expect(nodeId10?.key).toBe(10);
|
|
26
26
|
|
|
27
|
-
const nodeVal9 = treeMultiset.get(9,
|
|
27
|
+
const nodeVal9 = treeMultiset.get(9, node => node.val);
|
|
28
28
|
expect(nodeVal9?.key).toBe(9);
|
|
29
29
|
|
|
30
|
-
const nodesByCount1 = treeMultiset.
|
|
30
|
+
const nodesByCount1 = treeMultiset.getNodes(1, node => node.count);
|
|
31
31
|
expect(nodesByCount1.length).toBe(14);
|
|
32
32
|
|
|
33
|
-
const nodesByCount2 = treeMultiset.
|
|
33
|
+
const nodesByCount2 = treeMultiset.getNodes(2, node => node.count);
|
|
34
34
|
expect(nodesByCount2.length).toBe(2);
|
|
35
35
|
const leftMost = treeMultiset.getLeftMost();
|
|
36
36
|
expect(leftMost?.key).toBe(1);
|
|
@@ -39,24 +39,26 @@ describe('TreeMultiset operations test', () => {
|
|
|
39
39
|
const minNodeBySpecificNode = node15 && treeMultiset.getLeftMost(node15);
|
|
40
40
|
expect(minNodeBySpecificNode?.key).toBe(12);
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
let subTreeSum = 0;
|
|
43
|
+
node15 && treeMultiset.subTreeTraverse((node: TreeMultisetNode<number>) => (subTreeSum += node.key), 15);
|
|
43
44
|
expect(subTreeSum).toBe(70);
|
|
44
|
-
|
|
45
|
+
let lesserSum = 0;
|
|
46
|
+
treeMultiset.lesserOrGreaterTraverse((node: TreeMultisetNode<number>) => (lesserSum += node.key), CP.lt, 10);
|
|
45
47
|
expect(lesserSum).toBe(45);
|
|
46
48
|
|
|
47
49
|
expect(node15 instanceof TreeMultisetNode);
|
|
48
50
|
if (node15 instanceof TreeMultisetNode) {
|
|
49
|
-
const subTreeAdd = treeMultiset.
|
|
51
|
+
const subTreeAdd = treeMultiset.subTreeTraverse((node: TreeMultisetNode<number>) => (node.count += 1), 15);
|
|
50
52
|
expect(subTreeAdd);
|
|
51
53
|
}
|
|
52
54
|
const node11 = treeMultiset.get(11);
|
|
53
55
|
expect(node11 instanceof TreeMultisetNode);
|
|
54
56
|
if (node11 instanceof TreeMultisetNode) {
|
|
55
|
-
const allGreaterNodesAdded = treeMultiset.
|
|
57
|
+
const allGreaterNodesAdded = treeMultiset.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 11);
|
|
56
58
|
expect(allGreaterNodesAdded);
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
const dfsInorderNodes = treeMultiset.dfs(
|
|
61
|
+
const dfsInorderNodes = treeMultiset.dfs(node => node, 'in');
|
|
60
62
|
expect(dfsInorderNodes[0].key).toBe(1);
|
|
61
63
|
expect(dfsInorderNodes[dfsInorderNodes.length - 1].key).toBe(16);
|
|
62
64
|
expect(treeMultiset.isPerfectlyBalanced()).toBe(false);
|
|
@@ -66,7 +68,7 @@ describe('TreeMultiset operations test', () => {
|
|
|
66
68
|
expect(treeMultiset.isPerfectlyBalanced()).toBe(true);
|
|
67
69
|
expect(treeMultiset.isAVLBalanced()).toBe(true);
|
|
68
70
|
|
|
69
|
-
const bfsNodesAfterBalanced = treeMultiset.bfs(
|
|
71
|
+
const bfsNodesAfterBalanced = treeMultiset.bfs(node => node);
|
|
70
72
|
expect(bfsNodesAfterBalanced[0].key).toBe(8);
|
|
71
73
|
expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16);
|
|
72
74
|
|
|
@@ -187,13 +189,13 @@ describe('TreeMultiset operations test', () => {
|
|
|
187
189
|
|
|
188
190
|
expect(treeMultiset.isAVLBalanced()).toBe(true);
|
|
189
191
|
|
|
190
|
-
const bfsIDs = treeMultiset.bfs();
|
|
192
|
+
const bfsIDs = treeMultiset.bfs(node => node.key);
|
|
191
193
|
|
|
192
194
|
expect(bfsIDs[0]).toBe(12);
|
|
193
195
|
expect(bfsIDs[1]).toBe(2);
|
|
194
196
|
expect(bfsIDs[2]).toBe(16);
|
|
195
197
|
|
|
196
|
-
const bfsNodes = treeMultiset.bfs(
|
|
198
|
+
const bfsNodes = treeMultiset.bfs(node => node);
|
|
197
199
|
|
|
198
200
|
expect(bfsNodes[0].key).toBe(12);
|
|
199
201
|
expect(bfsNodes[1].key).toBe(2);
|
|
@@ -277,7 +279,7 @@ describe('TreeMultiset operations test', () => {
|
|
|
277
279
|
// expect(allGreaterNodesAdded).toBeDefined();
|
|
278
280
|
// }
|
|
279
281
|
//
|
|
280
|
-
// const dfsInorderNodes = objTreeMultiset.dfs(
|
|
282
|
+
// const dfsInorderNodes = objTreeMultiset.dfs(node => node, 'in');
|
|
281
283
|
// expect(dfsInorderNodes[0].key).toBe(1);
|
|
282
284
|
// expect(dfsInorderNodes[dfsInorderNodes.length - 1].key).toBe(16);
|
|
283
285
|
//
|
|
@@ -419,13 +421,19 @@ describe('TreeMultiset operations test', () => {
|
|
|
419
421
|
|
|
420
422
|
describe('TreeMultiset Performance test', function () {
|
|
421
423
|
// const treeMS = new TreeMultiset<TreeMultisetNode<number>>();
|
|
422
|
-
// const
|
|
424
|
+
// const inputSize = [100]; // Adjust input sizes as needed
|
|
423
425
|
//
|
|
424
426
|
// // Define a function to calculate the expected O(n log n) time
|
|
425
427
|
// function expectedTime(n: number): number {
|
|
426
428
|
// return n * Math.log(n);
|
|
427
429
|
// }
|
|
428
430
|
|
|
431
|
+
const treeMS = new TreeMultiset<TreeMultisetNode<number>>();
|
|
432
|
+
const inputSize = 100000; // Adjust input sizes as needed
|
|
433
|
+
|
|
434
|
+
beforeEach(() => {
|
|
435
|
+
treeMS.clear();
|
|
436
|
+
});
|
|
429
437
|
it(`Observe the time consumption of TreeMultiset.add fitting O(n log n)`, function () {
|
|
430
438
|
// // Create a benchmark suite
|
|
431
439
|
// const suite = new Benchmark.Suite();
|
|
@@ -437,9 +445,9 @@ describe('TreeMultiset Performance test', function () {
|
|
|
437
445
|
// }
|
|
438
446
|
// return arr;
|
|
439
447
|
// }
|
|
440
|
-
// const inputArray = generateRandomArray(
|
|
448
|
+
// const inputArray = generateRandomArray(inputSize[0]);
|
|
441
449
|
//
|
|
442
|
-
// suite.add(`TreeMultiset addMany (n=${
|
|
450
|
+
// suite.add(`TreeMultiset addMany (n=${inputSize[0]})`, () => {
|
|
443
451
|
// treeMS.addMany([...inputArray]);
|
|
444
452
|
// });
|
|
445
453
|
//
|
|
@@ -453,9 +461,26 @@ describe('TreeMultiset Performance test', function () {
|
|
|
453
461
|
// console.log(`Input size (n): ${n}, Observed time: ${observedTime.toFixed(2)}ms, Expected time: ${expected.toFixed(2)}ms`);
|
|
454
462
|
// })
|
|
455
463
|
// .on('complete', () => {
|
|
456
|
-
// console.log(`Benchmark (n=${
|
|
464
|
+
// console.log(`Benchmark (n=${inputSize[0]}) completed.`);
|
|
457
465
|
// done(); // Call done to indicate the test is complete
|
|
458
466
|
// })
|
|
459
467
|
// .run({async: true});
|
|
460
468
|
});
|
|
469
|
+
|
|
470
|
+
it(`Observe the time consumption of TreeMultiset.dfs be good`, function () {
|
|
471
|
+
const startDFS = performance.now();
|
|
472
|
+
const dfs = treeMS.dfs(node => node);
|
|
473
|
+
isDebug && console.log('---bfs', performance.now() - startDFS, dfs.length);
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
it('Should the time consumption of lesserOrGreaterTraverse fitting O(n log n)', function () {
|
|
477
|
+
const start = performance.now();
|
|
478
|
+
for (let i = 0; i < inputSize; i++) {
|
|
479
|
+
treeMS.add(i);
|
|
480
|
+
}
|
|
481
|
+
isDebug && console.log('---add', performance.now() - start);
|
|
482
|
+
const startL = performance.now();
|
|
483
|
+
treeMS.lesserOrGreaterTraverse((node: TreeMultisetNode<number>) => (node.count += 1), CP.lt, inputSize / 2);
|
|
484
|
+
isDebug && console.log('---lesserOrGreaterTraverse', performance.now() - startL);
|
|
485
|
+
});
|
|
461
486
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {Deque, ArrayDeque, ObjectDeque} from '../../../../src';
|
|
2
|
+
import {bigO} from '../../../utils';
|
|
2
3
|
|
|
3
4
|
describe('Deque Tests', () => {
|
|
4
5
|
// Test cases for the Deque class (DoublyLinkedList-based)
|
|
@@ -128,3 +129,19 @@ describe('Deque Tests', () => {
|
|
|
128
129
|
// Add more test cases as needed
|
|
129
130
|
});
|
|
130
131
|
});
|
|
132
|
+
|
|
133
|
+
describe('Deque Performance Test', () => {
|
|
134
|
+
const dataSize = 10000;
|
|
135
|
+
it('should numeric queue be efficient', function () {
|
|
136
|
+
const startTime = performance.now();
|
|
137
|
+
const queue = new Deque<number>();
|
|
138
|
+
for (let i = 0; i < dataSize; i++) {
|
|
139
|
+
queue.unshift(i);
|
|
140
|
+
}
|
|
141
|
+
for (let i = 0; i < dataSize; i++) {
|
|
142
|
+
queue.pop();
|
|
143
|
+
}
|
|
144
|
+
console.log(`Queue Deque Test: ${performance.now() - startTime} ms`);
|
|
145
|
+
expect(performance.now() - startTime).toBeLessThan(bigO.LINEAR * 100);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
@@ -197,3 +197,45 @@ describe('LinkedListQueue', () => {
|
|
|
197
197
|
|
|
198
198
|
// Add more test cases for other methods of LinkedListQueue.
|
|
199
199
|
});
|
|
200
|
+
|
|
201
|
+
describe('Queue Performance Test', () => {
|
|
202
|
+
const dataSize = 10000;
|
|
203
|
+
it('should numeric queue be efficient', function () {
|
|
204
|
+
const startTime = performance.now();
|
|
205
|
+
const queue = new Queue<number>();
|
|
206
|
+
for (let i = 0; i < dataSize; i++) {
|
|
207
|
+
queue.enqueue(i);
|
|
208
|
+
}
|
|
209
|
+
for (let i = 0; i < dataSize; i++) {
|
|
210
|
+
queue.dequeue();
|
|
211
|
+
}
|
|
212
|
+
console.log(`Queue Performance Test: ${performance.now() - startTime} ms`);
|
|
213
|
+
expect(performance.now() - startTime).toBeLessThan(bigO.LINEAR * 100);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('should numeric Array be more efficient than Queue when the data size is 10000', function () {
|
|
217
|
+
const startTime2 = performance.now();
|
|
218
|
+
const queue2: number[] = [];
|
|
219
|
+
for (let i = 0; i < dataSize; i++) {
|
|
220
|
+
queue2.push(i);
|
|
221
|
+
}
|
|
222
|
+
for (let i = 0; i < dataSize; i++) {
|
|
223
|
+
queue2.shift();
|
|
224
|
+
}
|
|
225
|
+
console.log(`Array Performance Test: ${performance.now() - startTime2} ms`);
|
|
226
|
+
expect(performance.now() - startTime2).toBeLessThan(bigO.CUBED * 100);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it('should numeric LinkedListQueue be efficient', function () {
|
|
230
|
+
const startTime = performance.now();
|
|
231
|
+
const queue = new LinkedListQueue<number>();
|
|
232
|
+
for (let i = 0; i < dataSize; i++) {
|
|
233
|
+
queue.enqueue(i);
|
|
234
|
+
}
|
|
235
|
+
for (let i = 0; i < dataSize; i++) {
|
|
236
|
+
queue.dequeue();
|
|
237
|
+
}
|
|
238
|
+
console.log(`LinkedListQueue Performance Test: ${performance.now() - startTime} ms`);
|
|
239
|
+
expect(performance.now() - startTime).toBeLessThan(bigO.LINEAR * 100);
|
|
240
|
+
});
|
|
241
|
+
});
|
package/test/utils/big-o.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {AnyFunction} from '../types';
|
|
2
2
|
|
|
3
|
+
const isDebug = false;
|
|
3
4
|
const orderReducedBy = 2; // reduction of bigO's order compared to the baseline bigO
|
|
4
5
|
|
|
5
6
|
export const magnitude = {
|
|
@@ -148,12 +149,12 @@ export function logBigOMetricsWrap<F extends AnyFunction>(fn: F, args: Parameter
|
|
|
148
149
|
methodLog.push([runTime, maxDataSize]);
|
|
149
150
|
|
|
150
151
|
if (methodLog.length >= 20) {
|
|
151
|
-
console.log('triggered', methodName, methodLog);
|
|
152
|
+
isDebug && console.log('triggered', methodName, methodLog);
|
|
152
153
|
const bigO = estimateBigO(
|
|
153
154
|
methodLog.map(([runTime]) => runTime),
|
|
154
155
|
methodLog.map(([runTime]) => runTime)
|
|
155
156
|
);
|
|
156
|
-
console.log(`Estimated Big O: ${bigO}`);
|
|
157
|
+
isDebug && console.log(`Estimated Big O: ${bigO}`);
|
|
157
158
|
methodLogs.delete(methodName);
|
|
158
159
|
}
|
|
159
160
|
}
|
|
@@ -182,12 +183,12 @@ export function logBigOMetrics(target: any, propertyKey: string, descriptor: Pro
|
|
|
182
183
|
methodLog.push([runTime, maxDataSize]);
|
|
183
184
|
|
|
184
185
|
if (methodLog.length >= 20) {
|
|
185
|
-
console.log('triggered', methodName, methodLog);
|
|
186
|
+
isDebug && console.log('triggered', methodName, methodLog);
|
|
186
187
|
const bigO = estimateBigO(
|
|
187
188
|
methodLog.map(([runTime]) => runTime),
|
|
188
189
|
methodLog.map(([runTime]) => runTime)
|
|
189
190
|
);
|
|
190
|
-
console.log(`Estimated Big O: ${bigO}`);
|
|
191
|
+
isDebug && console.log(`Estimated Big O: ${bigO}`);
|
|
191
192
|
methodLogs.delete(methodName);
|
|
192
193
|
}
|
|
193
194
|
}
|