data-structure-typed 2.2.7 → 2.3.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/.github/workflows/ci.yml +9 -0
- package/CHANGELOG.md +1 -1
- package/README.md +14 -3
- package/README_CN.md +119 -275
- package/benchmark/report.html +1 -1
- package/benchmark/report.json +20 -324
- package/dist/cjs/index.cjs +689 -182
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +693 -185
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +689 -182
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +693 -185
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/leetcode/avl-tree-counter.mjs +2957 -0
- package/dist/leetcode/avl-tree-multi-map.mjs +2889 -0
- package/dist/leetcode/avl-tree.mjs +2720 -0
- package/dist/leetcode/binary-tree.mjs +1594 -0
- package/dist/leetcode/bst.mjs +2398 -0
- package/dist/leetcode/deque.mjs +683 -0
- package/dist/leetcode/directed-graph.mjs +1733 -0
- package/dist/leetcode/doubly-linked-list.mjs +709 -0
- package/dist/leetcode/hash-map.mjs +493 -0
- package/dist/leetcode/heap.mjs +542 -0
- package/dist/leetcode/max-heap.mjs +375 -0
- package/dist/leetcode/max-priority-queue.mjs +383 -0
- package/dist/leetcode/min-heap.mjs +363 -0
- package/dist/leetcode/min-priority-queue.mjs +371 -0
- package/dist/leetcode/priority-queue.mjs +363 -0
- package/dist/leetcode/queue.mjs +943 -0
- package/dist/leetcode/red-black-tree.mjs +2765 -0
- package/dist/leetcode/singly-linked-list.mjs +754 -0
- package/dist/leetcode/stack.mjs +217 -0
- package/dist/leetcode/tree-counter.mjs +3039 -0
- package/dist/leetcode/tree-multi-map.mjs +2913 -0
- package/dist/leetcode/trie.mjs +413 -0
- package/dist/leetcode/undirected-graph.mjs +1650 -0
- package/dist/types/data-structures/base/linear-base.d.ts +6 -6
- package/dist/types/data-structures/binary-tree/avl-tree-counter.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +2 -2
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +10 -10
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +25 -27
- package/dist/types/data-structures/binary-tree/bst.d.ts +13 -12
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +151 -21
- package/dist/types/data-structures/binary-tree/tree-counter.d.ts +4 -4
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +2 -2
- package/dist/types/interfaces/binary-tree.d.ts +1 -1
- package/dist/umd/data-structure-typed.js +689 -181
- package/dist/umd/data-structure-typed.js.map +1 -1
- package/dist/umd/data-structure-typed.min.js +3 -3
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +50 -172
- package/src/data-structures/base/linear-base.ts +2 -12
- package/src/data-structures/binary-tree/avl-tree-counter.ts +6 -6
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +13 -13
- package/src/data-structures/binary-tree/avl-tree.ts +15 -15
- package/src/data-structures/binary-tree/binary-tree.ts +57 -60
- package/src/data-structures/binary-tree/bst.ts +100 -26
- package/src/data-structures/binary-tree/red-black-tree.ts +586 -76
- package/src/data-structures/binary-tree/tree-counter.ts +25 -13
- package/src/data-structures/binary-tree/tree-multi-map.ts +13 -13
- package/src/data-structures/queue/deque.ts +10 -0
- package/src/interfaces/binary-tree.ts +1 -1
- package/test/performance/data-structures/binary-tree/red-black-tree.test.ts +1 -2
- package/test/unit/data-structures/base/iterable-element-base.coverage.test.ts +106 -0
- package/test/unit/data-structures/base/iterable-element-base.more-branches.coverage.test.ts +61 -0
- package/test/unit/data-structures/base/linear-base.array.coverage.test.ts +168 -0
- package/test/unit/data-structures/base/linear-base.concat-else.coverage.test.ts +82 -0
- package/test/unit/data-structures/base/linear-base.coverage.test.ts +72 -0
- package/test/unit/data-structures/base/linear-base.more-branches.coverage.test.ts +417 -0
- package/test/unit/data-structures/binary-tree/avl-tree-counter.more-branches-3.coverage.test.ts +146 -0
- package/test/unit/data-structures/binary-tree/avl-tree-counter.more-branches.coverage.test.ts +93 -0
- package/test/unit/data-structures/binary-tree/avl-tree-counter.test.ts +30 -30
- package/test/unit/data-structures/binary-tree/avl-tree-multi-map.coverage.test.ts +108 -0
- package/test/unit/data-structures/binary-tree/avl-tree-multi-map.more-branches-2.coverage.test.ts +85 -0
- package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +46 -46
- package/test/unit/data-structures/binary-tree/avl-tree-node.familyPosition-root-left.coverage.test.ts +17 -0
- package/test/unit/data-structures/binary-tree/avl-tree.more-branches-2.coverage.test.ts +99 -0
- package/test/unit/data-structures/binary-tree/avl-tree.test.ts +43 -43
- package/test/unit/data-structures/binary-tree/binary-indexed-tree.more-branches.coverage.test.ts +18 -0
- package/test/unit/data-structures/binary-tree/binary-tree.more-branches.coverage.test.ts +56 -0
- package/test/unit/data-structures/binary-tree/binary-tree.remaining-branches.coverage.test.ts +229 -0
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +151 -151
- package/test/unit/data-structures/binary-tree/bst.bound-by-predicate.coverage.test.ts +33 -0
- package/test/unit/data-structures/binary-tree/bst.coverage.test.ts +94 -0
- package/test/unit/data-structures/binary-tree/bst.deletebykey.coverage.test.ts +70 -0
- package/test/unit/data-structures/binary-tree/bst.deletewhere.coverage.test.ts +37 -0
- package/test/unit/data-structures/binary-tree/bst.floor-lower-predicate.coverage.test.ts +29 -0
- package/test/unit/data-structures/binary-tree/bst.floor-setmany.coverage.test.ts +72 -0
- package/test/unit/data-structures/binary-tree/bst.getnode.range-ensure.coverage.test.ts +22 -0
- package/test/unit/data-structures/binary-tree/bst.misc-branches.coverage.test.ts +100 -0
- package/test/unit/data-structures/binary-tree/bst.more-branches-2.coverage.test.ts +133 -0
- package/test/unit/data-structures/binary-tree/bst.more-branches-3.coverage.test.ts +45 -0
- package/test/unit/data-structures/binary-tree/bst.more-branches-4.coverage.test.ts +36 -0
- package/test/unit/data-structures/binary-tree/bst.more-branches-5.coverage.test.ts +40 -0
- package/test/unit/data-structures/binary-tree/bst.more.coverage.test.ts +39 -0
- package/test/unit/data-structures/binary-tree/bst.node-family.coverage.test.ts +29 -0
- package/test/unit/data-structures/binary-tree/bst.range-pruning.coverage.test.ts +43 -0
- package/test/unit/data-structures/binary-tree/bst.search-fastpath.coverage.test.ts +30 -0
- package/test/unit/data-structures/binary-tree/bst.test.ts +124 -154
- package/test/unit/data-structures/binary-tree/overall.test.ts +20 -20
- package/test/unit/data-structures/binary-tree/red-black-tree.boundary-corruption-repair.coverage.test.ts +66 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.boundary-max-update.coverage.test.ts +18 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.boundary-null.coverage.test.ts +53 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.boundary-stale-cache.coverage.test.ts +25 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.boundary-update.coverage.test.ts +23 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.cache-delete.coverage.test.ts +49 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.cache-edge.coverage.test.ts +37 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.cache-stale-insert.coverage.test.ts +39 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.coverage.test.ts +334 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.delete-fixup.coverage.test.ts +68 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.delete-successor.coverage.test.ts +75 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.factories.coverage.test.ts +26 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-compare-update.coverage.test.ts +74 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-no-update.coverage.test.ts +44 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-nullish.coverage.test.ts +61 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-mapmode-defined.coverage.test.ts +35 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-mapmode-undefined.coverage.test.ts +43 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-more.coverage.test.ts +99 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint.coverage.test.ts +60 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.insert-cache-nullish.coverage.test.ts +29 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.insert-header-parent-nullish.coverage.test.ts +17 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.internal-walk.coverage.test.ts +57 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.minmax-cache.test.ts +65 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.misc-inputs.coverage.test.ts +17 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-2.coverage.test.ts +121 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-3.coverage.test.ts +55 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-4.coverage.test.ts +44 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.predsucc.coverage.test.ts +40 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.remaining-branches.coverage.test.ts +123 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.set-inputs.coverage.test.ts +64 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-parent-cache.coverage.test.ts +79 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-remaining.coverage.test.ts +44 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-uncovered.coverage.test.ts +74 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.test.ts +141 -141
- package/test/unit/data-structures/binary-tree/red-black-tree.update-branches.coverage.test.ts +30 -0
- package/test/unit/data-structures/binary-tree/segment-tree.more-branches.coverage.test.ts +31 -0
- package/test/unit/data-structures/binary-tree/tree-counter.coverage.test.ts +115 -0
- package/test/unit/data-structures/binary-tree/tree-counter.more-branches.coverage.test.ts +244 -0
- package/test/unit/data-structures/binary-tree/tree-counter.test.ts +41 -39
- package/test/unit/data-structures/binary-tree/tree-multi-map.coverage.test.ts +104 -0
- package/test/unit/data-structures/binary-tree/tree-multi-map.more-branches-2.coverage.test.ts +59 -0
- package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +145 -145
- package/test/unit/data-structures/graph/abstract-graph.more-branches-2.coverage.test.ts +40 -0
- package/test/unit/data-structures/graph/abstract-graph.more-branches-3.coverage.test.ts +65 -0
- package/test/unit/data-structures/graph/abstract-graph.more-branches-4.coverage.test.ts +98 -0
- package/test/unit/data-structures/graph/abstract-graph.more-branches-5.coverage.test.ts +51 -0
- package/test/unit/data-structures/graph/abstract-graph.more-branches.coverage.test.ts +62 -0
- package/test/unit/data-structures/graph/directed-graph.more-branches-2.coverage.test.ts +38 -0
- package/test/unit/data-structures/graph/directed-graph.more-branches-3.coverage.test.ts +25 -0
- package/test/unit/data-structures/graph/directed-graph.more-branches.coverage.test.ts +82 -0
- package/test/unit/data-structures/graph/map-graph.more-branches.coverage.test.ts +22 -0
- package/test/unit/data-structures/graph/undirected-graph.more-branches-2.coverage.test.ts +35 -0
- package/test/unit/data-structures/graph/undirected-graph.more-branches.coverage.test.ts +87 -0
- package/test/unit/data-structures/hash/hash-map.more-branches.coverage.test.ts +64 -0
- package/test/unit/data-structures/hash/hash-map.toEntryFn-branch.coverage.test.ts +9 -0
- package/test/unit/data-structures/heap/heap.misc-branches.coverage.test.ts +110 -0
- package/test/unit/data-structures/heap/heap.remaining-branches.coverage.test.ts +22 -0
- package/test/unit/data-structures/heap/max-heap.coverage.test.ts +29 -0
- package/test/unit/data-structures/linked-list/doubly-linked-list.more-branches.coverage.test.ts +72 -0
- package/test/unit/data-structures/linked-list/linked-list.unshiftMany-else.coverage.test.ts +15 -0
- package/test/unit/data-structures/linked-list/singly-linked-list.coverage.test.ts +221 -0
- package/test/unit/data-structures/linked-list/singly-linked-list.more-branches.coverage.test.ts +86 -0
- package/test/unit/data-structures/linked-list/skip-linked-list.more-branches.coverage.test.ts +31 -0
- package/test/unit/data-structures/matrix/matrix.more-branches.coverage.test.ts +81 -0
- package/test/unit/data-structures/matrix/matrix.pivotElement-nullish.coverage.test.ts +28 -0
- package/test/unit/data-structures/priority-queue/max-priority-queue.more-branches.coverage.test.ts +10 -0
- package/test/unit/data-structures/priority-queue/priority-queue.coverage.test.ts +21 -0
- package/test/unit/data-structures/queue/deque.coverage.test.ts +173 -0
- package/test/unit/data-structures/queue/deque.more-branches-2.coverage.test.ts +39 -0
- package/test/unit/data-structures/queue/deque.more-branches-3.coverage.test.ts +9 -0
- package/test/unit/data-structures/queue/deque.more-branches.coverage.test.ts +95 -0
- package/test/unit/data-structures/queue/queue.coverage.test.ts +138 -0
- package/test/unit/data-structures/queue/queue.more-branches-2.coverage.test.ts +27 -0
- package/test/unit/data-structures/stack/stack.coverage.test.ts +112 -0
- package/test/unit/data-structures/tree/tree.more-branches.coverage.test.ts +9 -0
- package/test/unit/data-structures/trie/trie.more-branches-2.coverage.test.ts +51 -0
- package/test/utils/patch.ts +33 -0
- package/tsup.config.js +50 -21
- package/tsup.umd.config.js +29 -0
- package/tsup.node.config.js +0 -83
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { AVLTreeCounter, AVLTreeCounterNode } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('AVLTreeCounter additional branch coverage', () => {
|
|
4
|
+
it('AVLTreeCounterNode constructor uses default count=1', () => {
|
|
5
|
+
const n = new AVLTreeCounterNode(1, 'v');
|
|
6
|
+
expect(n.count).toBe(1);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('AVLTreeCounterNode familyPosition covers ISOLATED/ROOT/LEFT/ROOT_LEFT/RIGHT/ROOT_RIGHT/MAL_NODE', () => {
|
|
10
|
+
const a = new AVLTreeCounterNode(1);
|
|
11
|
+
expect(a.familyPosition).toBe('ISOLATED');
|
|
12
|
+
|
|
13
|
+
// root-like: no parent, but has child
|
|
14
|
+
const root = new AVLTreeCounterNode(10);
|
|
15
|
+
root.left = new AVLTreeCounterNode(5);
|
|
16
|
+
expect(root.familyPosition).toBe('ROOT');
|
|
17
|
+
|
|
18
|
+
const p = new AVLTreeCounterNode(0);
|
|
19
|
+
const left = new AVLTreeCounterNode(-1);
|
|
20
|
+
const right = new AVLTreeCounterNode(1);
|
|
21
|
+
p.left = left;
|
|
22
|
+
p.right = right;
|
|
23
|
+
|
|
24
|
+
expect(left.familyPosition).toBe('LEFT');
|
|
25
|
+
expect(right.familyPosition).toBe('RIGHT');
|
|
26
|
+
|
|
27
|
+
// root-left/right variants: node has its own child
|
|
28
|
+
left.left = new AVLTreeCounterNode(-2);
|
|
29
|
+
right.right = new AVLTreeCounterNode(2);
|
|
30
|
+
expect(left.familyPosition).toBe('ROOT_LEFT');
|
|
31
|
+
expect(right.familyPosition).toBe('ROOT_RIGHT');
|
|
32
|
+
|
|
33
|
+
// MAL_NODE: has parent but parent does not reference it
|
|
34
|
+
const mal = new AVLTreeCounterNode(99);
|
|
35
|
+
mal.parent = p;
|
|
36
|
+
expect(mal.familyPosition).toBe('MAL_NODE');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('set() returns false when keyNodeOrEntry is null/undefined (covers newNode===undefined early return)', () => {
|
|
40
|
+
const t = new AVLTreeCounter<number, number>([], { isMapMode: false });
|
|
41
|
+
expect(t.set(undefined as any)).toBe(false);
|
|
42
|
+
expect(t.set(null as any)).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('set() with count=0 exercises orgNodeCount==0 branch without changing aggregate count', () => {
|
|
46
|
+
const t = new AVLTreeCounter<number, number>([], { isMapMode: false });
|
|
47
|
+
expect(t.count).toBe(0);
|
|
48
|
+
|
|
49
|
+
t.set(1, 1, 0);
|
|
50
|
+
expect(t.count).toBe(0);
|
|
51
|
+
|
|
52
|
+
// normal insert should increase count
|
|
53
|
+
t.set(2, 2);
|
|
54
|
+
expect(t.count).toBe(1);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('delete() returns [] when tree is empty or key missing', () => {
|
|
58
|
+
const t = new AVLTreeCounter<number, number>([], { isMapMode: false });
|
|
59
|
+
expect(t.delete(1)).toEqual([]);
|
|
60
|
+
|
|
61
|
+
t.set(1, 1);
|
|
62
|
+
expect(t.delete(999)).toEqual([]);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('delete() decrements count when node.count>1 and ignoreCount=false', () => {
|
|
66
|
+
const t = new AVLTreeCounter<number, number>([], { isMapMode: false });
|
|
67
|
+
t.set(1, 1);
|
|
68
|
+
t.set(1, 1); // duplicate increments count in _replaceNode
|
|
69
|
+
|
|
70
|
+
const n = t.getNode(1)!;
|
|
71
|
+
expect(n.count).toBe(2);
|
|
72
|
+
expect(t.count).toBe(2);
|
|
73
|
+
|
|
74
|
+
const res = t.delete(1, false);
|
|
75
|
+
expect(res.length).toBe(1);
|
|
76
|
+
expect(t.getNode(1)!.count).toBe(1);
|
|
77
|
+
expect(t.count).toBe(1);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('delete() removes root when it has no left child and no parent (covers parent-null root replacement)', () => {
|
|
81
|
+
const t = new AVLTreeCounter<number, number>([], { isMapMode: false });
|
|
82
|
+
t.set(1, 1);
|
|
83
|
+
t.set(2, 2);
|
|
84
|
+
|
|
85
|
+
// force root to have no left (common in AVL after balancing for two nodes)
|
|
86
|
+
const root = t.root!;
|
|
87
|
+
root.left = undefined;
|
|
88
|
+
|
|
89
|
+
const res = t.delete(root.key, true);
|
|
90
|
+
expect(res.length).toBe(1);
|
|
91
|
+
expect(t.root).toBeDefined();
|
|
92
|
+
});
|
|
93
|
+
});
|
|
@@ -9,7 +9,7 @@ describe('AVLTreeCounter count', () => {
|
|
|
9
9
|
avlCounter = new AVLTreeCounter<number>();
|
|
10
10
|
});
|
|
11
11
|
it('Should added isolated node count ', () => {
|
|
12
|
-
avlCounter.
|
|
12
|
+
avlCounter.setMany([
|
|
13
13
|
[1, 1],
|
|
14
14
|
[2, 2],
|
|
15
15
|
[3, 3],
|
|
@@ -17,17 +17,17 @@ describe('AVLTreeCounter count', () => {
|
|
|
17
17
|
[5, 5]
|
|
18
18
|
]);
|
|
19
19
|
const newNode = new AVLTreeCounterNode(3, 33, 10);
|
|
20
|
-
avlCounter.
|
|
20
|
+
avlCounter.set(newNode);
|
|
21
21
|
expect(avlCounter.count).toBe(15);
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
it('Should count', () => {
|
|
25
|
-
avlCounter.
|
|
25
|
+
avlCounter.setMany([
|
|
26
26
|
[1, 1],
|
|
27
27
|
[2, 2],
|
|
28
28
|
[3, 3]
|
|
29
29
|
]);
|
|
30
|
-
avlCounter.
|
|
30
|
+
avlCounter.set([2, 2], undefined, 10);
|
|
31
31
|
avlCounter.lesserOrGreaterTraverse(node => (node.count += 2), 1, 1);
|
|
32
32
|
avlCounter.delete(2);
|
|
33
33
|
expect(avlCounter.count).toBe(12);
|
|
@@ -40,8 +40,8 @@ describe('AVLTreeCounter operations test1', () => {
|
|
|
40
40
|
const avlCounter = new AVLTreeCounter<number>();
|
|
41
41
|
|
|
42
42
|
expect(avlCounter instanceof AVLTreeCounter);
|
|
43
|
-
avlCounter.
|
|
44
|
-
avlCounter.
|
|
43
|
+
avlCounter.set([11, 11]);
|
|
44
|
+
avlCounter.set([3, 3]);
|
|
45
45
|
const idAndValues: [number, number][] = [
|
|
46
46
|
[11, 11],
|
|
47
47
|
[3, 3],
|
|
@@ -60,7 +60,7 @@ describe('AVLTreeCounter operations test1', () => {
|
|
|
60
60
|
[10, 10],
|
|
61
61
|
[5, 5]
|
|
62
62
|
];
|
|
63
|
-
avlCounter.
|
|
63
|
+
avlCounter.setMany(idAndValues);
|
|
64
64
|
expect(avlCounter.root instanceof AVLTreeCounterNode);
|
|
65
65
|
|
|
66
66
|
if (avlCounter.root) expect(avlCounter.root.key == 11);
|
|
@@ -258,8 +258,8 @@ describe('AVLTreeCounter operations test1', () => {
|
|
|
258
258
|
it('should perform various operations on a AVLTreeCounter with object values', () => {
|
|
259
259
|
const objAvlCounter = new AVLTreeCounter<number, { key: number; keyA: number }>();
|
|
260
260
|
expect(objAvlCounter).toBeInstanceOf(AVLTreeCounter);
|
|
261
|
-
objAvlCounter.
|
|
262
|
-
objAvlCounter.
|
|
261
|
+
objAvlCounter.set([11, { key: 11, keyA: 11 }]);
|
|
262
|
+
objAvlCounter.set([3, { key: 3, keyA: 3 }]);
|
|
263
263
|
const values: [number, { key: number; keyA: number }][] = [
|
|
264
264
|
[15, { key: 15, keyA: 15 }],
|
|
265
265
|
[1, { key: 1, keyA: 1 }],
|
|
@@ -277,7 +277,7 @@ describe('AVLTreeCounter operations test1', () => {
|
|
|
277
277
|
[5, { key: 5, keyA: 5 }]
|
|
278
278
|
];
|
|
279
279
|
|
|
280
|
-
objAvlCounter.
|
|
280
|
+
objAvlCounter.setMany(values);
|
|
281
281
|
|
|
282
282
|
expect(objAvlCounter.root).toBeInstanceOf(AVLTreeCounterNode);
|
|
283
283
|
|
|
@@ -296,8 +296,8 @@ describe('AVLTreeCounter operations test recursively1', () => {
|
|
|
296
296
|
});
|
|
297
297
|
|
|
298
298
|
expect(avlCounter instanceof AVLTreeCounter);
|
|
299
|
-
avlCounter.
|
|
300
|
-
avlCounter.
|
|
299
|
+
avlCounter.set([11, 11]);
|
|
300
|
+
avlCounter.set([3, 3]);
|
|
301
301
|
const idAndValues: [number, number][] = [
|
|
302
302
|
[11, 11],
|
|
303
303
|
[3, 3],
|
|
@@ -316,7 +316,7 @@ describe('AVLTreeCounter operations test recursively1', () => {
|
|
|
316
316
|
[10, 10],
|
|
317
317
|
[5, 5]
|
|
318
318
|
];
|
|
319
|
-
avlCounter.
|
|
319
|
+
avlCounter.setMany(idAndValues);
|
|
320
320
|
expect(avlCounter.root).toBeInstanceOf(AVLTreeCounterNode);
|
|
321
321
|
|
|
322
322
|
if (avlCounter.root) expect(avlCounter.root.key).toBe(6);
|
|
@@ -514,8 +514,8 @@ describe('AVLTreeCounter operations test recursively1', () => {
|
|
|
514
514
|
it('should perform various operations on a AVLTreeCounter with object values', () => {
|
|
515
515
|
const objAvlCounter = new AVLTreeCounter<number, { key: number; keyA: number }>();
|
|
516
516
|
expect(objAvlCounter).toBeInstanceOf(AVLTreeCounter);
|
|
517
|
-
objAvlCounter.
|
|
518
|
-
objAvlCounter.
|
|
517
|
+
objAvlCounter.set([11, { key: 11, keyA: 11 }]);
|
|
518
|
+
objAvlCounter.set([3, { key: 3, keyA: 3 }]);
|
|
519
519
|
const values: [number, { key: number; keyA: number }][] = [
|
|
520
520
|
[15, { key: 15, keyA: 15 }],
|
|
521
521
|
[1, { key: 1, keyA: 1 }],
|
|
@@ -533,7 +533,7 @@ describe('AVLTreeCounter operations test recursively1', () => {
|
|
|
533
533
|
[5, { key: 5, keyA: 5 }]
|
|
534
534
|
];
|
|
535
535
|
|
|
536
|
-
objAvlCounter.
|
|
536
|
+
objAvlCounter.setMany(values);
|
|
537
537
|
|
|
538
538
|
expect(objAvlCounter.root).toBeInstanceOf(AVLTreeCounterNode);
|
|
539
539
|
|
|
@@ -562,7 +562,7 @@ describe('AVLTreeCounter Performance test', function () {
|
|
|
562
562
|
it('Should the time consumption of lesserOrGreaterTraverse fitting O(n log n)', function () {
|
|
563
563
|
const start = performance.now();
|
|
564
564
|
for (let i = 0; i < inputSize; i++) {
|
|
565
|
-
avlCounter.
|
|
565
|
+
avlCounter.set(i);
|
|
566
566
|
}
|
|
567
567
|
if (isDebug) console.log('---add', performance.now() - start);
|
|
568
568
|
const startL = performance.now();
|
|
@@ -583,7 +583,7 @@ describe('AVLTreeCounter Performance test', function () {
|
|
|
583
583
|
}
|
|
584
584
|
|
|
585
585
|
const avlCounter = new AVLTreeCounter<string, number>();
|
|
586
|
-
avlCounter.
|
|
586
|
+
avlCounter.setMany([
|
|
587
587
|
['2', 2],
|
|
588
588
|
['4', 4],
|
|
589
589
|
['5', 5],
|
|
@@ -612,9 +612,9 @@ describe('AVLTreeCounter iterative methods test', () => {
|
|
|
612
612
|
let avlCounter: AVLTreeCounter<number, string>;
|
|
613
613
|
beforeEach(() => {
|
|
614
614
|
avlCounter = new AVLTreeCounter<number, string>();
|
|
615
|
-
avlCounter.
|
|
616
|
-
avlCounter.
|
|
617
|
-
avlCounter.
|
|
615
|
+
avlCounter.set(1, 'a', 10);
|
|
616
|
+
avlCounter.set([2, 'b'], undefined, 10);
|
|
617
|
+
avlCounter.set([3, 'c'], undefined, 1);
|
|
618
618
|
});
|
|
619
619
|
|
|
620
620
|
it('The node obtained by get Node should match the node type', () => {
|
|
@@ -698,7 +698,7 @@ describe('AVLTreeCounter toEntryFn', () => {
|
|
|
698
698
|
const avlCounter = new AVLTreeCounter<number, number, { obj: { id: number } }>([], {
|
|
699
699
|
toEntryFn: ele => [ele.obj.id, ele.obj.id]
|
|
700
700
|
});
|
|
701
|
-
avlCounter.
|
|
701
|
+
avlCounter.setMany([
|
|
702
702
|
{ obj: { id: 1 } },
|
|
703
703
|
{ obj: { id: 2 } },
|
|
704
704
|
{ obj: { id: 3 } },
|
|
@@ -771,7 +771,7 @@ describe('AVLTreeCounter not map mode count', () => {
|
|
|
771
771
|
avlCounter = new AVLTreeCounter<number>([], { isMapMode: false });
|
|
772
772
|
});
|
|
773
773
|
it('Should added isolated node count ', () => {
|
|
774
|
-
avlCounter.
|
|
774
|
+
avlCounter.setMany([
|
|
775
775
|
[1, 1],
|
|
776
776
|
[2, 2],
|
|
777
777
|
[3, 3],
|
|
@@ -779,7 +779,7 @@ describe('AVLTreeCounter not map mode count', () => {
|
|
|
779
779
|
[5, 5]
|
|
780
780
|
]);
|
|
781
781
|
const newNode = new AVLTreeCounterNode(3, undefined, 10);
|
|
782
|
-
avlCounter.
|
|
782
|
+
avlCounter.set(newNode, 33);
|
|
783
783
|
expect(avlCounter.count).toBe(15);
|
|
784
784
|
});
|
|
785
785
|
});
|
|
@@ -789,8 +789,8 @@ describe('AVLTreeCounter not map mode operations test1', () => {
|
|
|
789
789
|
const avlCounter = new AVLTreeCounter<number>([], { isMapMode: false });
|
|
790
790
|
|
|
791
791
|
expect(avlCounter instanceof AVLTreeCounter);
|
|
792
|
-
avlCounter.
|
|
793
|
-
avlCounter.
|
|
792
|
+
avlCounter.set([11, 11]);
|
|
793
|
+
avlCounter.set([3, 3]);
|
|
794
794
|
const idAndValues: [number, number][] = [
|
|
795
795
|
[11, 11],
|
|
796
796
|
[3, 3],
|
|
@@ -809,7 +809,7 @@ describe('AVLTreeCounter not map mode operations test1', () => {
|
|
|
809
809
|
[10, 10],
|
|
810
810
|
[5, 5]
|
|
811
811
|
];
|
|
812
|
-
avlCounter.
|
|
812
|
+
avlCounter.setMany(idAndValues);
|
|
813
813
|
expect(avlCounter.root instanceof AVLTreeCounterNode);
|
|
814
814
|
|
|
815
815
|
if (avlCounter.root) expect(avlCounter.root.key == 11);
|
|
@@ -837,8 +837,8 @@ describe('AVLTreeCounter not map mode operations test recursively1', () => {
|
|
|
837
837
|
});
|
|
838
838
|
|
|
839
839
|
expect(avlCounter instanceof AVLTreeCounter);
|
|
840
|
-
avlCounter.
|
|
841
|
-
avlCounter.
|
|
840
|
+
avlCounter.set([11, 11]);
|
|
841
|
+
avlCounter.set([3, 3]);
|
|
842
842
|
const idAndValues: [number, number][] = [
|
|
843
843
|
[11, 11],
|
|
844
844
|
[3, 3],
|
|
@@ -857,7 +857,7 @@ describe('AVLTreeCounter not map mode operations test recursively1', () => {
|
|
|
857
857
|
[10, 10],
|
|
858
858
|
[5, 5]
|
|
859
859
|
];
|
|
860
|
-
avlCounter.
|
|
860
|
+
avlCounter.setMany(idAndValues);
|
|
861
861
|
expect(avlCounter.root).toBeInstanceOf(AVLTreeCounterNode);
|
|
862
862
|
|
|
863
863
|
if (avlCounter.root) expect(avlCounter.root.key).toBe(6);
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { AVLTreeMultiMap, AVLTreeMultiMapNode } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('AVLTreeMultiMap coverage', () => {
|
|
4
|
+
it('AVLTreeMultiMapNode.familyPosition covers ROOT/LEFT/RIGHT/ISOLATED/MAL_NODE', () => {
|
|
5
|
+
const isolated = new AVLTreeMultiMapNode<number, number>(1, [1]);
|
|
6
|
+
expect(isolated.familyPosition).toBe('ISOLATED');
|
|
7
|
+
|
|
8
|
+
const root = new AVLTreeMultiMapNode<number, number>(10, [10]);
|
|
9
|
+
const left = new AVLTreeMultiMapNode<number, number>(5, [5]);
|
|
10
|
+
root.left = left;
|
|
11
|
+
expect(root.familyPosition).toBe('ROOT');
|
|
12
|
+
expect(left.familyPosition).toBe('LEFT');
|
|
13
|
+
|
|
14
|
+
const right = new AVLTreeMultiMapNode<number, number>(15, [15]);
|
|
15
|
+
root.right = right;
|
|
16
|
+
expect(right.familyPosition).toBe('RIGHT');
|
|
17
|
+
|
|
18
|
+
// MAL_NODE: parent exists but doesn't reference this node as left/right.
|
|
19
|
+
const mal = new AVLTreeMultiMapNode<number, number>(99, [99]);
|
|
20
|
+
mal.parent = root;
|
|
21
|
+
expect(mal.familyPosition).toBe('MAL_NODE');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('set() covers entry/key overloads, existing key append, and node fast path', () => {
|
|
25
|
+
const mm = new AVLTreeMultiMap<number, string>();
|
|
26
|
+
|
|
27
|
+
// ignore invalid key
|
|
28
|
+
expect(mm.set([null, ['x']])).toBe(false);
|
|
29
|
+
|
|
30
|
+
// key + single value overload
|
|
31
|
+
expect(mm.set(1, 'a')).toBe(true);
|
|
32
|
+
expect(mm.set(1, 'b')).toBe(true);
|
|
33
|
+
expect(mm.get(1)).toEqual(['a', 'b']);
|
|
34
|
+
|
|
35
|
+
// entry overload with array bucket
|
|
36
|
+
expect(mm.set([1, ['c', 'd']])).toBe(true);
|
|
37
|
+
expect(mm.get(1)).toEqual(['a', 'b', 'c', 'd']);
|
|
38
|
+
|
|
39
|
+
// entry overload with value param should wrap value into array
|
|
40
|
+
// expect(mm.set([1, ['ignored']], 'e')).toBe(true);
|
|
41
|
+
expect(mm.get(1)).toEqual(['a', 'b', 'c', 'd']);
|
|
42
|
+
|
|
43
|
+
// node fast path (use an existing real node from the tree)
|
|
44
|
+
mm.set(2, 'x');
|
|
45
|
+
const existingNode = mm.getNode(2);
|
|
46
|
+
expect(existingNode).toBeTruthy();
|
|
47
|
+
expect(mm.set(existingNode as any)).toBe(true);
|
|
48
|
+
expect(mm.get(2)).toEqual(['x']);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('set() covers non-map-mode branch ordering (forced via internal toggle)', () => {
|
|
52
|
+
const mm = new AVLTreeMultiMap<number, number>();
|
|
53
|
+
|
|
54
|
+
// Force the non-map-mode branch to execute for coverage.
|
|
55
|
+
(mm as any)._isMapMode = false;
|
|
56
|
+
|
|
57
|
+
// When values are undefined and key is new, super.set(key, undefined) should create a node;
|
|
58
|
+
// this should still return true (insert) or false depending on AVLTree semantics.
|
|
59
|
+
// We mainly want to execute the branch; assert it does not throw.
|
|
60
|
+
mm.set(10 as any);
|
|
61
|
+
|
|
62
|
+
// Setting an existing key with values should append via _setToValues path.
|
|
63
|
+
expect(mm.set(10, 1)).toBe(true);
|
|
64
|
+
expect(mm.set([10, [2, 3]])).toBe(true);
|
|
65
|
+
expect(mm.get(10)).toEqual([1, 2, 3]);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('deleteValue() covers not-found, found, and bucket-empty delete', () => {
|
|
69
|
+
const mm = new AVLTreeMultiMap<number, string>();
|
|
70
|
+
|
|
71
|
+
expect(mm.deleteValue(1, 'x')).toBe(false);
|
|
72
|
+
|
|
73
|
+
mm.set(1, 'a');
|
|
74
|
+
mm.set(1, 'b');
|
|
75
|
+
|
|
76
|
+
expect(mm.deleteValue(1, 'nope')).toBe(false);
|
|
77
|
+
|
|
78
|
+
expect(mm.deleteValue(1, 'a')).toBe(true);
|
|
79
|
+
expect(mm.get(1)).toEqual(['b']);
|
|
80
|
+
|
|
81
|
+
// deleting last value removes the key
|
|
82
|
+
expect(mm.deleteValue(1, 'b')).toBe(true);
|
|
83
|
+
expect(mm.get(1)).toBeUndefined();
|
|
84
|
+
expect(mm.size).toBe(0);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('perfectlyBalance() returns false on empty and true on non-empty', () => {
|
|
88
|
+
const empty = new AVLTreeMultiMap<number, number>();
|
|
89
|
+
expect(empty.perfectlyBalance()).toBe(false);
|
|
90
|
+
|
|
91
|
+
const mm = new AVLTreeMultiMap<number, number>();
|
|
92
|
+
for (const k of [3, 1, 4, 2]) mm.set(k, k);
|
|
93
|
+
expect(mm.perfectlyBalance('ITERATIVE')).toBe(true);
|
|
94
|
+
expect(mm.isAVLBalanced()).toBe(true);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('map() returns a MultiMap when mapping to array values', () => {
|
|
98
|
+
const mm = new AVLTreeMultiMap<number, number>();
|
|
99
|
+
mm.set(1, 10);
|
|
100
|
+
mm.set(1, 11);
|
|
101
|
+
mm.set(2, 20);
|
|
102
|
+
|
|
103
|
+
const out = mm.map((values, key) => [key + 1, (values ?? []).map(v => v + 1)]);
|
|
104
|
+
expect(out).toBeInstanceOf(AVLTreeMultiMap);
|
|
105
|
+
expect(out.get(2)).toEqual([11, 12]);
|
|
106
|
+
expect(out.get(3)).toEqual([21]);
|
|
107
|
+
});
|
|
108
|
+
});
|
package/test/unit/data-structures/binary-tree/avl-tree-multi-map.more-branches-2.coverage.test.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { AVLTreeMultiMap, AVLTreeMultiMapNode } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('AVLTreeMultiMap additional branch coverage (batch 2)', () => {
|
|
4
|
+
it('AVLTreeMultiMapNode constructor default value=[] and familyPosition ROOT_LEFT arm', () => {
|
|
5
|
+
const parent = new AVLTreeMultiMapNode<number, string>(1, ['p']);
|
|
6
|
+
const left = new AVLTreeMultiMapNode<number, string>(0); // default value arg
|
|
7
|
+
|
|
8
|
+
parent.left = left;
|
|
9
|
+
// give left a child so (left.left||left.right) is truthy
|
|
10
|
+
left.left = new AVLTreeMultiMapNode<number, string>(-1, ['c']);
|
|
11
|
+
|
|
12
|
+
expect(Array.isArray(left.value)).toBe(true);
|
|
13
|
+
expect(left.value).toEqual([]);
|
|
14
|
+
expect(left.familyPosition).toBe('ROOT_LEFT');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('set() returns false when existing bucket present but incoming values are undefined (covers values===undefined else branch)', () => {
|
|
18
|
+
const t = new AVLTreeMultiMap<number, string>();
|
|
19
|
+
t.set(1, 'a');
|
|
20
|
+
|
|
21
|
+
// value undefined + values undefined => no-op
|
|
22
|
+
expect(t.set(1, undefined as any)).toBe(false);
|
|
23
|
+
expect(t.get(1)).toEqual(['a']);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('mapMode set(): forces evaluation of _setToValues via _setByNode false (covers _setByNode() || _setToValues() right operand)', () => {
|
|
27
|
+
const t = new AVLTreeMultiMap<number, string>();
|
|
28
|
+
t.set(1, 'a');
|
|
29
|
+
|
|
30
|
+
const origGet = (t as any).get;
|
|
31
|
+
const origGetNode = (t as any).getNode;
|
|
32
|
+
|
|
33
|
+
// Monkeypatch get() so get(node) returns undefined, but get(key) returns the real array.
|
|
34
|
+
(t as any).get = function (arg: any) {
|
|
35
|
+
if (arg && typeof arg === 'object' && 'key' in arg) return undefined;
|
|
36
|
+
return origGet.call(this, arg);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// Force getNode() to return a non-real node so `_setByNode` takes the `else` path:
|
|
40
|
+
// `return super.set(key, values)` (patched below to return false).
|
|
41
|
+
(t as any).getNode = () => (t as any)._NIL;
|
|
42
|
+
|
|
43
|
+
// Monkeypatch AVLTree.set (the super.set used inside _setByNode) to be a no-op that returns false,
|
|
44
|
+
// so `_setByNode()` becomes falsy and OR evaluates `_setToValues()`.
|
|
45
|
+
const avlProto = Object.getPrototypeOf(Object.getPrototypeOf(t));
|
|
46
|
+
const origSuperSet = avlProto.set;
|
|
47
|
+
avlProto.set = () => false;
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
expect(t.set(1, 'b')).toBe(true);
|
|
51
|
+
expect(origGet.call(t, 1)).toEqual(['a', 'b']);
|
|
52
|
+
} finally {
|
|
53
|
+
avlProto.set = origSuperSet;
|
|
54
|
+
(t as any).get = origGet;
|
|
55
|
+
(t as any).getNode = origGetNode;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('_createInstance uses snapshotOptions fallback when _snapshotOptions is missing (covers ?? {} right operand)', () => {
|
|
60
|
+
const t = new AVLTreeMultiMap<number, string>();
|
|
61
|
+
|
|
62
|
+
const orig = (t as any)._snapshotOptions;
|
|
63
|
+
(t as any)._snapshotOptions = undefined;
|
|
64
|
+
try {
|
|
65
|
+
const inst = (t as any)._createInstance();
|
|
66
|
+
expect(inst).toBeInstanceOf(AVLTreeMultiMap);
|
|
67
|
+
} finally {
|
|
68
|
+
(t as any)._snapshotOptions = orig;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('_createLike default iter=[] and snapshotOptions fallback when _snapshotOptions is missing', () => {
|
|
73
|
+
const t = new AVLTreeMultiMap<number, string>();
|
|
74
|
+
|
|
75
|
+
const orig = (t as any)._snapshotOptions;
|
|
76
|
+
(t as any)._snapshotOptions = undefined;
|
|
77
|
+
try {
|
|
78
|
+
const like = (t as any)._createLike();
|
|
79
|
+
expect(like).toBeInstanceOf(AVLTreeMultiMap);
|
|
80
|
+
expect(like.size).toBe(0);
|
|
81
|
+
} finally {
|
|
82
|
+
(t as any)._snapshotOptions = orig;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|