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
|
@@ -3,9 +3,9 @@ import { AVLTree, BST, RedBlackTree, TreeMultiMap } from '../../../../src';
|
|
|
3
3
|
describe('Overall BinaryTree Test', () => {
|
|
4
4
|
it('should perform various operations on BinaryTree', () => {
|
|
5
5
|
const bst = new BST<number>();
|
|
6
|
-
bst.
|
|
7
|
-
bst.
|
|
8
|
-
bst.
|
|
6
|
+
bst.set(11);
|
|
7
|
+
bst.set(3);
|
|
8
|
+
bst.setMany([15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5], undefined, false);
|
|
9
9
|
expect(bst.size).toBe(16); // true
|
|
10
10
|
bst.has(6); // true
|
|
11
11
|
expect(bst.has(6)).toBe(true); // true
|
|
@@ -24,10 +24,10 @@ describe('Overall BinaryTree Test', () => {
|
|
|
24
24
|
expect(bfsIDs[0]).toBe(11);
|
|
25
25
|
|
|
26
26
|
const objBST = new BST<number, { key: number; keyA: number }>();
|
|
27
|
-
objBST.
|
|
28
|
-
objBST.
|
|
27
|
+
objBST.set([11, { key: 11, keyA: 11 }]);
|
|
28
|
+
objBST.set([3, { key: 3, keyA: 3 }]);
|
|
29
29
|
|
|
30
|
-
objBST.
|
|
30
|
+
objBST.setMany([
|
|
31
31
|
[15, { key: 15, keyA: 15 }],
|
|
32
32
|
[1, { key: 1, keyA: 1 }],
|
|
33
33
|
[8, { key: 8, keyA: 8 }],
|
|
@@ -47,7 +47,7 @@ describe('Overall BinaryTree Test', () => {
|
|
|
47
47
|
objBST.delete(11);
|
|
48
48
|
|
|
49
49
|
const avlTree = new AVLTree();
|
|
50
|
-
avlTree.
|
|
50
|
+
avlTree.setMany([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
|
|
51
51
|
avlTree.isAVLBalanced(); // true
|
|
52
52
|
expect(avlTree.isAVLBalanced()).toBe(true); // true
|
|
53
53
|
avlTree.delete(10);
|
|
@@ -103,9 +103,9 @@ describe('Overall BinaryTree Test', () => {
|
|
|
103
103
|
comparator: (a, b) => b - a
|
|
104
104
|
});
|
|
105
105
|
expect(avl.size).toBe(5);
|
|
106
|
-
avl.
|
|
107
|
-
avl.
|
|
108
|
-
avl.
|
|
106
|
+
avl.set(2);
|
|
107
|
+
avl.set(5);
|
|
108
|
+
avl.set(4);
|
|
109
109
|
expect(avl.root?.key).toBe(3);
|
|
110
110
|
expect(avl.root?.left?.key).toBe(7);
|
|
111
111
|
expect(avl.root?.left?.left?.key).toBe(9);
|
|
@@ -145,11 +145,11 @@ describe('Overall BinaryTree Test', () => {
|
|
|
145
145
|
iterationType: 'RECURSIVE'
|
|
146
146
|
});
|
|
147
147
|
expect(tmm.size).toBe(5);
|
|
148
|
-
tmm.
|
|
149
|
-
tmm.
|
|
150
|
-
tmm.
|
|
151
|
-
tmm.
|
|
152
|
-
tmm.
|
|
148
|
+
tmm.set(2);
|
|
149
|
+
tmm.set(2);
|
|
150
|
+
tmm.set(2);
|
|
151
|
+
tmm.set(5);
|
|
152
|
+
tmm.set(4);
|
|
153
153
|
expect(tmm.root?.key).toBe(3);
|
|
154
154
|
expect(tmm.root?.left?.key).toBe(1);
|
|
155
155
|
expect(tmm.root?.left?.left?.key).toBe(NaN);
|
|
@@ -190,11 +190,11 @@ describe('Overall BinaryTree Test', () => {
|
|
|
190
190
|
iterationType: 'RECURSIVE'
|
|
191
191
|
});
|
|
192
192
|
expect(rbTree.size).toBe(5);
|
|
193
|
-
rbTree.
|
|
194
|
-
rbTree.
|
|
195
|
-
rbTree.
|
|
196
|
-
rbTree.
|
|
197
|
-
rbTree.
|
|
193
|
+
rbTree.set(2);
|
|
194
|
+
rbTree.set(2);
|
|
195
|
+
rbTree.set(2);
|
|
196
|
+
rbTree.set(5);
|
|
197
|
+
rbTree.set(4);
|
|
198
198
|
expect(rbTree.root?.key).toBe(3);
|
|
199
199
|
expect(rbTree.root?.left?.key).toBe(1);
|
|
200
200
|
expect(rbTree.root?.left?.left?.key).toBe(NaN);
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { RedBlackTree } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('RedBlackTree boundary corruption repair coverage', () => {
|
|
4
|
+
it('min-attach: when header._right is corrupted to NIL, branch mirrors max cache to new min', () => {
|
|
5
|
+
let tree: RedBlackTree<number, number> = new RedBlackTree<number>();
|
|
6
|
+
let active = false;
|
|
7
|
+
let flipped = false;
|
|
8
|
+
const comparator = (a: number, b: number) => {
|
|
9
|
+
// Flip once during the boundary pre-check, before the attach happens.
|
|
10
|
+
if (active && !flipped && tree) {
|
|
11
|
+
flipped = true;
|
|
12
|
+
(tree as any)._header._right = tree.NIL;
|
|
13
|
+
}
|
|
14
|
+
return a - b;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
tree = new RedBlackTree<number, number>([], { isMapMode: false, comparator });
|
|
18
|
+
tree.set(10, 10);
|
|
19
|
+
tree.set(5, 5);
|
|
20
|
+
tree.set(15, 15);
|
|
21
|
+
|
|
22
|
+
// Boundary insert smaller than current min.
|
|
23
|
+
active = true;
|
|
24
|
+
tree.set(1, 1);
|
|
25
|
+
active = false;
|
|
26
|
+
|
|
27
|
+
// Repair branch should have mirrored max cache when header._right was NIL.
|
|
28
|
+
expect((tree as any)._header._right.key).toBe(1);
|
|
29
|
+
|
|
30
|
+
// Restore correct max cache so subsequent tests/users aren't affected.
|
|
31
|
+
const root = (tree as any)._root;
|
|
32
|
+
(tree as any)._setMaxCache(tree.isRealNode(root) ? tree.getRightMost((n: any) => n, root) : undefined);
|
|
33
|
+
expect((tree as any)._header._right.key).toBe(15);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('max-attach: when header._left is corrupted to NIL, branch initializes min cache during max attach', () => {
|
|
37
|
+
let tree: RedBlackTree<number, number> = new RedBlackTree<number>();;
|
|
38
|
+
let active = false;
|
|
39
|
+
let flipped = false;
|
|
40
|
+
const comparator = (a: number, b: number) => {
|
|
41
|
+
if (active && !flipped && tree) {
|
|
42
|
+
flipped = true;
|
|
43
|
+
(tree as any)._header._left = tree.NIL;
|
|
44
|
+
}
|
|
45
|
+
return a - b;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
tree = new RedBlackTree<number, number>([], { isMapMode: false, comparator });
|
|
49
|
+
tree.set(10, 10);
|
|
50
|
+
tree.set(5, 5);
|
|
51
|
+
tree.set(15, 15);
|
|
52
|
+
|
|
53
|
+
// Boundary insert larger than current max.
|
|
54
|
+
active = true;
|
|
55
|
+
tree.set(100, 100);
|
|
56
|
+
active = false;
|
|
57
|
+
|
|
58
|
+
// Observe the branch effect before repairing (min cache got initialized).
|
|
59
|
+
expect((tree as any)._header._left.key).toBe(100);
|
|
60
|
+
|
|
61
|
+
// Restore correct min cache.
|
|
62
|
+
const root = (tree as any)._root;
|
|
63
|
+
(tree as any)._setMinCache(tree.isRealNode(root) ? tree.getLeftMost((n: any) => n, root) : undefined);
|
|
64
|
+
expect((tree as any)._header._left.key).toBe(5);
|
|
65
|
+
});
|
|
66
|
+
});
|
package/test/unit/data-structures/binary-tree/red-black-tree.boundary-max-update.coverage.test.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { RedBlackTree } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('RedBlackTree boundary max update coverage', () => {
|
|
4
|
+
it('mapMode: updating existing max key with defined value hits store.set branch in cMax===0 fast-path', () => {
|
|
5
|
+
const t = new RedBlackTree<number, string>(); // mapMode default
|
|
6
|
+
|
|
7
|
+
t.set(10, 'mid');
|
|
8
|
+
t.set(5, 'min');
|
|
9
|
+
t.set(15, 'max');
|
|
10
|
+
|
|
11
|
+
// Update existing max key with a defined value.
|
|
12
|
+
t.set(15, 'max2');
|
|
13
|
+
|
|
14
|
+
expect(t.get(15)).toBe('max2');
|
|
15
|
+
// Assert store updated (fast-path uses store.set).
|
|
16
|
+
expect((t as any)._store.get(15)).toBe('max2');
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { RedBlackTree } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('RedBlackTree boundary attach null/undefined coverage', () => {
|
|
4
|
+
it('min boundary attach works when min.left is null', () => {
|
|
5
|
+
const t = new RedBlackTree<number, number>([], { isMapMode: false });
|
|
6
|
+
t.set(10, 10);
|
|
7
|
+
t.set(5, 5);
|
|
8
|
+
|
|
9
|
+
const minNode = t.getNode(5)!;
|
|
10
|
+
// Force the boundary condition to treat left as empty via null.
|
|
11
|
+
(minNode as any)._left = null;
|
|
12
|
+
|
|
13
|
+
t.set(1, 1);
|
|
14
|
+
|
|
15
|
+
expect(t.getNode(1)?.parent?.key).toBe(5);
|
|
16
|
+
expect((t as any)._header._left.key).toBe(1);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('min boundary attach works when min.left is undefined', () => {
|
|
20
|
+
const t = new RedBlackTree<number, number>([], { isMapMode: false });
|
|
21
|
+
t.set(10, 10);
|
|
22
|
+
t.set(5, 5);
|
|
23
|
+
|
|
24
|
+
const minNode = t.getNode(5)!;
|
|
25
|
+
// Force the boundary condition to treat left as empty via undefined.
|
|
26
|
+
(minNode as any)._left = undefined;
|
|
27
|
+
|
|
28
|
+
t.set(1, 1);
|
|
29
|
+
|
|
30
|
+
expect(t.getNode(1)?.parent?.key).toBe(5);
|
|
31
|
+
expect((t as any)._header._left.key).toBe(1);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('max boundary attach works when max.right is null/undefined', () => {
|
|
35
|
+
const t = new RedBlackTree<number, number>([], { isMapMode: false });
|
|
36
|
+
t.set(10, 10);
|
|
37
|
+
t.set(15, 15);
|
|
38
|
+
|
|
39
|
+
const maxNode = t.getNode(15)!;
|
|
40
|
+
// First cover null.
|
|
41
|
+
(maxNode as any)._right = null;
|
|
42
|
+
t.set(20, 20);
|
|
43
|
+
expect(t.getNode(20)?.parent?.key).toBe(15);
|
|
44
|
+
expect((t as any)._header._right.key).toBe(20);
|
|
45
|
+
|
|
46
|
+
// Now cover undefined on the new max.
|
|
47
|
+
const maxNode2 = t.getNode(20)!;
|
|
48
|
+
(maxNode2 as any)._right = undefined;
|
|
49
|
+
t.set(25, 25);
|
|
50
|
+
expect(t.getNode(25)?.parent?.key).toBe(20);
|
|
51
|
+
expect((t as any)._header._right.key).toBe(25);
|
|
52
|
+
});
|
|
53
|
+
});
|
package/test/unit/data-structures/binary-tree/red-black-tree.boundary-stale-cache.coverage.test.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { RedBlackTree } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('RedBlackTree boundary attach stale cache coverage', () => {
|
|
4
|
+
it('boundary max attach repairs stale min cache when header._left === NIL', () => {
|
|
5
|
+
const t = new RedBlackTree<number, number>([], { isMapMode: false });
|
|
6
|
+
t.set(10, 10);
|
|
7
|
+
t.set(5, 5);
|
|
8
|
+
|
|
9
|
+
const NIL = (t as any).NIL;
|
|
10
|
+
|
|
11
|
+
// Stale min cache: header._left is NIL, but tree is non-empty.
|
|
12
|
+
(t as any)._header._left = NIL;
|
|
13
|
+
|
|
14
|
+
// Insert new maximum; should take boundary max attach path and hit:
|
|
15
|
+
// if (header._left === NIL) this._setMinCache(newNode)
|
|
16
|
+
t.set(20, 20);
|
|
17
|
+
|
|
18
|
+
expect((t as any)._header._right.key).toBe(20);
|
|
19
|
+
expect((t as any)._header._left).not.toBe(NIL);
|
|
20
|
+
|
|
21
|
+
// Under stale/corrupted cache conditions, the boundary fast path mirrors min to the inserted node.
|
|
22
|
+
// (In normal operation header._left would not be NIL when the tree is non-empty.)
|
|
23
|
+
expect((t as any)._header._left.key).toBe(20);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RedBlackTree } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('RedBlackTree boundary update coverage', () => {
|
|
4
|
+
it('updating existing min/max via boundary cache fast paths does not change size', () => {
|
|
5
|
+
const t = new RedBlackTree<number, string>([], { isMapMode: false });
|
|
6
|
+
|
|
7
|
+
t.set(10, 'a');
|
|
8
|
+
t.set(5, 'min');
|
|
9
|
+
t.set(15, 'max');
|
|
10
|
+
|
|
11
|
+
const size0 = t.size;
|
|
12
|
+
|
|
13
|
+
// Update existing min key: should hit cMin===0 fast-path.
|
|
14
|
+
expect(t.set(5, 'min2')).toBe(true);
|
|
15
|
+
expect(t.size).toBe(size0);
|
|
16
|
+
expect(t.getNode(5)?.value).toBe('min2');
|
|
17
|
+
|
|
18
|
+
// Update existing max key: should hit cMax===0 fast-path.
|
|
19
|
+
expect(t.set(15, 'max2')).toBe(true);
|
|
20
|
+
expect(t.size).toBe(size0);
|
|
21
|
+
expect(t.getNode(15)?.value).toBe('max2');
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { RedBlackTree } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('RedBlackTree delete cache fallback coverage', () => {
|
|
4
|
+
it('forces min/max fallback recomputation branches after deleting min/max', () => {
|
|
5
|
+
const t = new RedBlackTree<number, number>([], { isMapMode: false });
|
|
6
|
+
for (const k of [10, 5, 15, 3, 7, 12, 18]) t.set(k, k);
|
|
7
|
+
|
|
8
|
+
// Delete current min and max to set willDeleteMin/Max paths.
|
|
9
|
+
const NIL = (t as any).NIL;
|
|
10
|
+
const minNode = (t as any)._header._left;
|
|
11
|
+
const maxNode = (t as any)._header._right;
|
|
12
|
+
expect(minNode).not.toBe(NIL);
|
|
13
|
+
expect(maxNode).not.toBe(NIL);
|
|
14
|
+
const minKey = minNode.key as number;
|
|
15
|
+
const maxKey = maxNode.key as number;
|
|
16
|
+
|
|
17
|
+
// After first delete, corrupt caches so fallback recompute branches run.
|
|
18
|
+
t.delete(minKey);
|
|
19
|
+
(t as any)._minNode = undefined;
|
|
20
|
+
|
|
21
|
+
// Delete max and also corrupt max cache.
|
|
22
|
+
t.delete(maxKey);
|
|
23
|
+
(t as any)._maxNode = undefined;
|
|
24
|
+
|
|
25
|
+
// Trigger an additional delete to enter the cache-update block with size>0.
|
|
26
|
+
t.delete(10);
|
|
27
|
+
|
|
28
|
+
// Should still have correct header min/max after recomputation.
|
|
29
|
+
const keys = [...t].map(([k]) => k).sort((a, b) => a - b);
|
|
30
|
+
if (keys.length > 0) {
|
|
31
|
+
expect((t as any)._header._left.key).toBe(keys[0]);
|
|
32
|
+
expect((t as any)._header._right.key).toBe(keys[keys.length - 1]);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('size<=0 branch clears min/max caches', () => {
|
|
37
|
+
const t = new RedBlackTree<number, number>([], { isMapMode: false });
|
|
38
|
+
t.set(1, 1);
|
|
39
|
+
|
|
40
|
+
t.delete(1);
|
|
41
|
+
|
|
42
|
+
expect(t.size).toBe(0);
|
|
43
|
+
// expect(t.min).toBeUndefined();
|
|
44
|
+
// expect(t.max).toBeUndefined();
|
|
45
|
+
const NIL = (t as any).NIL;
|
|
46
|
+
expect((t as any)._header._left).toBe(NIL);
|
|
47
|
+
expect((t as any)._header._right).toBe(NIL);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { RedBlackTree } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('RedBlackTree cache edge coverage', () => {
|
|
4
|
+
it('boundary min attach updates max cache when header._right is stale NIL', () => {
|
|
5
|
+
const t = new RedBlackTree<number, number>();
|
|
6
|
+
t.set(10, 10);
|
|
7
|
+
|
|
8
|
+
// Simulate stale max cache.
|
|
9
|
+
const NIL = (t as any).NIL;
|
|
10
|
+
(t as any)._header._right = NIL;
|
|
11
|
+
|
|
12
|
+
// Insert smaller than current min; min has no left -> boundary min attach path.
|
|
13
|
+
t.set(5, 5);
|
|
14
|
+
|
|
15
|
+
// After insertion, max cache should not remain NIL.
|
|
16
|
+
expect((t as any)._header._right).not.toBe(NIL);
|
|
17
|
+
expect((t as any)._maxNode).toBeDefined();
|
|
18
|
+
expect((t as any)._header._right).toBe((t as any)._maxNode);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('boundary max attach updates min cache when header._left is stale NIL', () => {
|
|
22
|
+
const t = new RedBlackTree<number, number>();
|
|
23
|
+
t.set(10, 10);
|
|
24
|
+
|
|
25
|
+
// Simulate stale min cache.
|
|
26
|
+
const NIL = (t as any).NIL;
|
|
27
|
+
(t as any)._header._left = NIL;
|
|
28
|
+
|
|
29
|
+
// Insert greater than current max; max has no right -> boundary max attach path.
|
|
30
|
+
t.set(15, 15);
|
|
31
|
+
|
|
32
|
+
// After insertion, min cache should not remain NIL.
|
|
33
|
+
expect((t as any)._header._left).not.toBe(NIL);
|
|
34
|
+
expect((t as any)._minNode).toBeDefined();
|
|
35
|
+
expect((t as any)._header._left).toBe((t as any)._minNode);
|
|
36
|
+
});
|
|
37
|
+
});
|
package/test/unit/data-structures/binary-tree/red-black-tree.cache-stale-insert.coverage.test.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { RedBlackTree } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('RedBlackTree stale cache insert coverage', () => {
|
|
4
|
+
it('stale header min/max caches trigger comparison-based cache repair on insertion', () => {
|
|
5
|
+
const t = new RedBlackTree<number, number>([], { isMapMode: false });
|
|
6
|
+
t.set(10, 10);
|
|
7
|
+
t.set(5, 5);
|
|
8
|
+
t.set(15, 15);
|
|
9
|
+
|
|
10
|
+
const n10 = t.getNode(10)!;
|
|
11
|
+
|
|
12
|
+
// Corrupt caches to point at an interior node.
|
|
13
|
+
(t as any)._header._left = n10;
|
|
14
|
+
(t as any)._header._right = n10;
|
|
15
|
+
|
|
16
|
+
// Insert a new min (not a boundary attach, because min cache is stale and minN.left is real).
|
|
17
|
+
t.set(1, 1);
|
|
18
|
+
expect((t as any)._header._left.key).toBe(1);
|
|
19
|
+
|
|
20
|
+
// Re-corrupt and insert a new max.
|
|
21
|
+
(t as any)._header._left = n10;
|
|
22
|
+
(t as any)._header._right = n10;
|
|
23
|
+
|
|
24
|
+
t.set(20, 20);
|
|
25
|
+
expect((t as any)._header._right.key).toBe(20);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('mapMode update with undefined value does not take store-fast-path (no throw)', () => {
|
|
29
|
+
const t = new RedBlackTree<number, string>([], { isMapMode: true });
|
|
30
|
+
t.set(1, 'a');
|
|
31
|
+
expect(t.get(1)).toBe('a');
|
|
32
|
+
|
|
33
|
+
// nextValue is undefined => should bypass map-mode store.has fast-path
|
|
34
|
+
// and go through normal set logic.
|
|
35
|
+
t.set(1, undefined as any);
|
|
36
|
+
// Existing semantics: undefined does not overwrite stored value in mapMode.
|
|
37
|
+
expect(t.get(1)).toBe('a');
|
|
38
|
+
});
|
|
39
|
+
});
|