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.
Files changed (181) hide show
  1. package/.github/workflows/ci.yml +9 -0
  2. package/CHANGELOG.md +1 -1
  3. package/README.md +14 -3
  4. package/README_CN.md +119 -275
  5. package/benchmark/report.html +1 -1
  6. package/benchmark/report.json +20 -324
  7. package/dist/cjs/index.cjs +689 -182
  8. package/dist/cjs/index.cjs.map +1 -1
  9. package/dist/cjs-legacy/index.cjs +693 -185
  10. package/dist/cjs-legacy/index.cjs.map +1 -1
  11. package/dist/esm/index.mjs +689 -182
  12. package/dist/esm/index.mjs.map +1 -1
  13. package/dist/esm-legacy/index.mjs +693 -185
  14. package/dist/esm-legacy/index.mjs.map +1 -1
  15. package/dist/leetcode/avl-tree-counter.mjs +2957 -0
  16. package/dist/leetcode/avl-tree-multi-map.mjs +2889 -0
  17. package/dist/leetcode/avl-tree.mjs +2720 -0
  18. package/dist/leetcode/binary-tree.mjs +1594 -0
  19. package/dist/leetcode/bst.mjs +2398 -0
  20. package/dist/leetcode/deque.mjs +683 -0
  21. package/dist/leetcode/directed-graph.mjs +1733 -0
  22. package/dist/leetcode/doubly-linked-list.mjs +709 -0
  23. package/dist/leetcode/hash-map.mjs +493 -0
  24. package/dist/leetcode/heap.mjs +542 -0
  25. package/dist/leetcode/max-heap.mjs +375 -0
  26. package/dist/leetcode/max-priority-queue.mjs +383 -0
  27. package/dist/leetcode/min-heap.mjs +363 -0
  28. package/dist/leetcode/min-priority-queue.mjs +371 -0
  29. package/dist/leetcode/priority-queue.mjs +363 -0
  30. package/dist/leetcode/queue.mjs +943 -0
  31. package/dist/leetcode/red-black-tree.mjs +2765 -0
  32. package/dist/leetcode/singly-linked-list.mjs +754 -0
  33. package/dist/leetcode/stack.mjs +217 -0
  34. package/dist/leetcode/tree-counter.mjs +3039 -0
  35. package/dist/leetcode/tree-multi-map.mjs +2913 -0
  36. package/dist/leetcode/trie.mjs +413 -0
  37. package/dist/leetcode/undirected-graph.mjs +1650 -0
  38. package/dist/types/data-structures/base/linear-base.d.ts +6 -6
  39. package/dist/types/data-structures/binary-tree/avl-tree-counter.d.ts +1 -1
  40. package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +2 -2
  41. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +10 -10
  42. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +25 -27
  43. package/dist/types/data-structures/binary-tree/bst.d.ts +13 -12
  44. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +151 -21
  45. package/dist/types/data-structures/binary-tree/tree-counter.d.ts +4 -4
  46. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +2 -2
  47. package/dist/types/interfaces/binary-tree.d.ts +1 -1
  48. package/dist/umd/data-structure-typed.js +689 -181
  49. package/dist/umd/data-structure-typed.js.map +1 -1
  50. package/dist/umd/data-structure-typed.min.js +3 -3
  51. package/dist/umd/data-structure-typed.min.js.map +1 -1
  52. package/package.json +50 -172
  53. package/src/data-structures/base/linear-base.ts +2 -12
  54. package/src/data-structures/binary-tree/avl-tree-counter.ts +6 -6
  55. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +13 -13
  56. package/src/data-structures/binary-tree/avl-tree.ts +15 -15
  57. package/src/data-structures/binary-tree/binary-tree.ts +57 -60
  58. package/src/data-structures/binary-tree/bst.ts +100 -26
  59. package/src/data-structures/binary-tree/red-black-tree.ts +586 -76
  60. package/src/data-structures/binary-tree/tree-counter.ts +25 -13
  61. package/src/data-structures/binary-tree/tree-multi-map.ts +13 -13
  62. package/src/data-structures/queue/deque.ts +10 -0
  63. package/src/interfaces/binary-tree.ts +1 -1
  64. package/test/performance/data-structures/binary-tree/red-black-tree.test.ts +1 -2
  65. package/test/unit/data-structures/base/iterable-element-base.coverage.test.ts +106 -0
  66. package/test/unit/data-structures/base/iterable-element-base.more-branches.coverage.test.ts +61 -0
  67. package/test/unit/data-structures/base/linear-base.array.coverage.test.ts +168 -0
  68. package/test/unit/data-structures/base/linear-base.concat-else.coverage.test.ts +82 -0
  69. package/test/unit/data-structures/base/linear-base.coverage.test.ts +72 -0
  70. package/test/unit/data-structures/base/linear-base.more-branches.coverage.test.ts +417 -0
  71. package/test/unit/data-structures/binary-tree/avl-tree-counter.more-branches-3.coverage.test.ts +146 -0
  72. package/test/unit/data-structures/binary-tree/avl-tree-counter.more-branches.coverage.test.ts +93 -0
  73. package/test/unit/data-structures/binary-tree/avl-tree-counter.test.ts +30 -30
  74. package/test/unit/data-structures/binary-tree/avl-tree-multi-map.coverage.test.ts +108 -0
  75. package/test/unit/data-structures/binary-tree/avl-tree-multi-map.more-branches-2.coverage.test.ts +85 -0
  76. package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +46 -46
  77. package/test/unit/data-structures/binary-tree/avl-tree-node.familyPosition-root-left.coverage.test.ts +17 -0
  78. package/test/unit/data-structures/binary-tree/avl-tree.more-branches-2.coverage.test.ts +99 -0
  79. package/test/unit/data-structures/binary-tree/avl-tree.test.ts +43 -43
  80. package/test/unit/data-structures/binary-tree/binary-indexed-tree.more-branches.coverage.test.ts +18 -0
  81. package/test/unit/data-structures/binary-tree/binary-tree.more-branches.coverage.test.ts +56 -0
  82. package/test/unit/data-structures/binary-tree/binary-tree.remaining-branches.coverage.test.ts +229 -0
  83. package/test/unit/data-structures/binary-tree/binary-tree.test.ts +151 -151
  84. package/test/unit/data-structures/binary-tree/bst.bound-by-predicate.coverage.test.ts +33 -0
  85. package/test/unit/data-structures/binary-tree/bst.coverage.test.ts +94 -0
  86. package/test/unit/data-structures/binary-tree/bst.deletebykey.coverage.test.ts +70 -0
  87. package/test/unit/data-structures/binary-tree/bst.deletewhere.coverage.test.ts +37 -0
  88. package/test/unit/data-structures/binary-tree/bst.floor-lower-predicate.coverage.test.ts +29 -0
  89. package/test/unit/data-structures/binary-tree/bst.floor-setmany.coverage.test.ts +72 -0
  90. package/test/unit/data-structures/binary-tree/bst.getnode.range-ensure.coverage.test.ts +22 -0
  91. package/test/unit/data-structures/binary-tree/bst.misc-branches.coverage.test.ts +100 -0
  92. package/test/unit/data-structures/binary-tree/bst.more-branches-2.coverage.test.ts +133 -0
  93. package/test/unit/data-structures/binary-tree/bst.more-branches-3.coverage.test.ts +45 -0
  94. package/test/unit/data-structures/binary-tree/bst.more-branches-4.coverage.test.ts +36 -0
  95. package/test/unit/data-structures/binary-tree/bst.more-branches-5.coverage.test.ts +40 -0
  96. package/test/unit/data-structures/binary-tree/bst.more.coverage.test.ts +39 -0
  97. package/test/unit/data-structures/binary-tree/bst.node-family.coverage.test.ts +29 -0
  98. package/test/unit/data-structures/binary-tree/bst.range-pruning.coverage.test.ts +43 -0
  99. package/test/unit/data-structures/binary-tree/bst.search-fastpath.coverage.test.ts +30 -0
  100. package/test/unit/data-structures/binary-tree/bst.test.ts +124 -154
  101. package/test/unit/data-structures/binary-tree/overall.test.ts +20 -20
  102. package/test/unit/data-structures/binary-tree/red-black-tree.boundary-corruption-repair.coverage.test.ts +66 -0
  103. package/test/unit/data-structures/binary-tree/red-black-tree.boundary-max-update.coverage.test.ts +18 -0
  104. package/test/unit/data-structures/binary-tree/red-black-tree.boundary-null.coverage.test.ts +53 -0
  105. package/test/unit/data-structures/binary-tree/red-black-tree.boundary-stale-cache.coverage.test.ts +25 -0
  106. package/test/unit/data-structures/binary-tree/red-black-tree.boundary-update.coverage.test.ts +23 -0
  107. package/test/unit/data-structures/binary-tree/red-black-tree.cache-delete.coverage.test.ts +49 -0
  108. package/test/unit/data-structures/binary-tree/red-black-tree.cache-edge.coverage.test.ts +37 -0
  109. package/test/unit/data-structures/binary-tree/red-black-tree.cache-stale-insert.coverage.test.ts +39 -0
  110. package/test/unit/data-structures/binary-tree/red-black-tree.coverage.test.ts +334 -0
  111. package/test/unit/data-structures/binary-tree/red-black-tree.delete-fixup.coverage.test.ts +68 -0
  112. package/test/unit/data-structures/binary-tree/red-black-tree.delete-successor.coverage.test.ts +75 -0
  113. package/test/unit/data-structures/binary-tree/red-black-tree.factories.coverage.test.ts +26 -0
  114. package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-compare-update.coverage.test.ts +74 -0
  115. package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-no-update.coverage.test.ts +44 -0
  116. package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-nullish.coverage.test.ts +61 -0
  117. package/test/unit/data-structures/binary-tree/red-black-tree.hint-mapmode-defined.coverage.test.ts +35 -0
  118. package/test/unit/data-structures/binary-tree/red-black-tree.hint-mapmode-undefined.coverage.test.ts +43 -0
  119. package/test/unit/data-structures/binary-tree/red-black-tree.hint-more.coverage.test.ts +99 -0
  120. package/test/unit/data-structures/binary-tree/red-black-tree.hint.coverage.test.ts +60 -0
  121. package/test/unit/data-structures/binary-tree/red-black-tree.insert-cache-nullish.coverage.test.ts +29 -0
  122. package/test/unit/data-structures/binary-tree/red-black-tree.insert-header-parent-nullish.coverage.test.ts +17 -0
  123. package/test/unit/data-structures/binary-tree/red-black-tree.internal-walk.coverage.test.ts +57 -0
  124. package/test/unit/data-structures/binary-tree/red-black-tree.minmax-cache.test.ts +65 -0
  125. package/test/unit/data-structures/binary-tree/red-black-tree.misc-inputs.coverage.test.ts +17 -0
  126. package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-2.coverage.test.ts +121 -0
  127. package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-3.coverage.test.ts +55 -0
  128. package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-4.coverage.test.ts +44 -0
  129. package/test/unit/data-structures/binary-tree/red-black-tree.predsucc.coverage.test.ts +40 -0
  130. package/test/unit/data-structures/binary-tree/red-black-tree.remaining-branches.coverage.test.ts +123 -0
  131. package/test/unit/data-structures/binary-tree/red-black-tree.set-inputs.coverage.test.ts +64 -0
  132. package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-parent-cache.coverage.test.ts +79 -0
  133. package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-remaining.coverage.test.ts +44 -0
  134. package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-uncovered.coverage.test.ts +74 -0
  135. package/test/unit/data-structures/binary-tree/red-black-tree.test.ts +141 -141
  136. package/test/unit/data-structures/binary-tree/red-black-tree.update-branches.coverage.test.ts +30 -0
  137. package/test/unit/data-structures/binary-tree/segment-tree.more-branches.coverage.test.ts +31 -0
  138. package/test/unit/data-structures/binary-tree/tree-counter.coverage.test.ts +115 -0
  139. package/test/unit/data-structures/binary-tree/tree-counter.more-branches.coverage.test.ts +244 -0
  140. package/test/unit/data-structures/binary-tree/tree-counter.test.ts +41 -39
  141. package/test/unit/data-structures/binary-tree/tree-multi-map.coverage.test.ts +104 -0
  142. package/test/unit/data-structures/binary-tree/tree-multi-map.more-branches-2.coverage.test.ts +59 -0
  143. package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +145 -145
  144. package/test/unit/data-structures/graph/abstract-graph.more-branches-2.coverage.test.ts +40 -0
  145. package/test/unit/data-structures/graph/abstract-graph.more-branches-3.coverage.test.ts +65 -0
  146. package/test/unit/data-structures/graph/abstract-graph.more-branches-4.coverage.test.ts +98 -0
  147. package/test/unit/data-structures/graph/abstract-graph.more-branches-5.coverage.test.ts +51 -0
  148. package/test/unit/data-structures/graph/abstract-graph.more-branches.coverage.test.ts +62 -0
  149. package/test/unit/data-structures/graph/directed-graph.more-branches-2.coverage.test.ts +38 -0
  150. package/test/unit/data-structures/graph/directed-graph.more-branches-3.coverage.test.ts +25 -0
  151. package/test/unit/data-structures/graph/directed-graph.more-branches.coverage.test.ts +82 -0
  152. package/test/unit/data-structures/graph/map-graph.more-branches.coverage.test.ts +22 -0
  153. package/test/unit/data-structures/graph/undirected-graph.more-branches-2.coverage.test.ts +35 -0
  154. package/test/unit/data-structures/graph/undirected-graph.more-branches.coverage.test.ts +87 -0
  155. package/test/unit/data-structures/hash/hash-map.more-branches.coverage.test.ts +64 -0
  156. package/test/unit/data-structures/hash/hash-map.toEntryFn-branch.coverage.test.ts +9 -0
  157. package/test/unit/data-structures/heap/heap.misc-branches.coverage.test.ts +110 -0
  158. package/test/unit/data-structures/heap/heap.remaining-branches.coverage.test.ts +22 -0
  159. package/test/unit/data-structures/heap/max-heap.coverage.test.ts +29 -0
  160. package/test/unit/data-structures/linked-list/doubly-linked-list.more-branches.coverage.test.ts +72 -0
  161. package/test/unit/data-structures/linked-list/linked-list.unshiftMany-else.coverage.test.ts +15 -0
  162. package/test/unit/data-structures/linked-list/singly-linked-list.coverage.test.ts +221 -0
  163. package/test/unit/data-structures/linked-list/singly-linked-list.more-branches.coverage.test.ts +86 -0
  164. package/test/unit/data-structures/linked-list/skip-linked-list.more-branches.coverage.test.ts +31 -0
  165. package/test/unit/data-structures/matrix/matrix.more-branches.coverage.test.ts +81 -0
  166. package/test/unit/data-structures/matrix/matrix.pivotElement-nullish.coverage.test.ts +28 -0
  167. package/test/unit/data-structures/priority-queue/max-priority-queue.more-branches.coverage.test.ts +10 -0
  168. package/test/unit/data-structures/priority-queue/priority-queue.coverage.test.ts +21 -0
  169. package/test/unit/data-structures/queue/deque.coverage.test.ts +173 -0
  170. package/test/unit/data-structures/queue/deque.more-branches-2.coverage.test.ts +39 -0
  171. package/test/unit/data-structures/queue/deque.more-branches-3.coverage.test.ts +9 -0
  172. package/test/unit/data-structures/queue/deque.more-branches.coverage.test.ts +95 -0
  173. package/test/unit/data-structures/queue/queue.coverage.test.ts +138 -0
  174. package/test/unit/data-structures/queue/queue.more-branches-2.coverage.test.ts +27 -0
  175. package/test/unit/data-structures/stack/stack.coverage.test.ts +112 -0
  176. package/test/unit/data-structures/tree/tree.more-branches.coverage.test.ts +9 -0
  177. package/test/unit/data-structures/trie/trie.more-branches-2.coverage.test.ts +51 -0
  178. package/test/utils/patch.ts +33 -0
  179. package/tsup.config.js +50 -21
  180. package/tsup.umd.config.js +29 -0
  181. package/tsup.node.config.js +0 -83
@@ -0,0 +1,35 @@
1
+ import { RedBlackTree } from '../../../../src';
2
+
3
+ describe('RedBlackTree setWithHintNode mapMode defined-value branches', () => {
4
+ it('direct attach left/right with defined values uses store.set branches', () => {
5
+ const t = new RedBlackTree<number, number>(); // mapMode default
6
+ t.set(10, 10);
7
+ const h10 = t.getNode(10)!;
8
+
9
+ const n5 = t.setWithHintNode(5, 5, h10);
10
+ expect(n5?.key).toBe(5);
11
+ expect((t as any)._store.get(5)).toBe(5);
12
+
13
+ const n15 = t.setWithHintNode(15, 15, h10);
14
+ expect(n15?.key).toBe(15);
15
+ expect((t as any)._store.get(15)).toBe(15);
16
+ });
17
+
18
+ it('pred.right and succ.left attach with defined values uses store.set branches', () => {
19
+ const t = new RedBlackTree<number, number>();
20
+ t.set(10, 10);
21
+ const h10 = t.getNode(10)!;
22
+
23
+ // Ensure left is real so we take pred path.
24
+ t.setWithHintNode(5, 5, h10);
25
+ const n7 = t.setWithHintNode(7, 7, h10);
26
+ expect(n7?.key).toBe(7);
27
+ expect((t as any)._store.get(7)).toBe(7);
28
+
29
+ // Ensure right is real so we take succ path.
30
+ t.setWithHintNode(15, 15, h10);
31
+ const n12 = t.setWithHintNode(12, 12, h10);
32
+ expect(n12?.key).toBe(12);
33
+ expect((t as any)._store.get(12)).toBe(12);
34
+ });
35
+ });
@@ -0,0 +1,43 @@
1
+ import { RedBlackTree } from '../../../../src';
2
+
3
+ describe('RedBlackTree setWithHintNode mapMode undefined-value branches', () => {
4
+ it('direct attach left/right with undefined value hits _setValue branches (no store entry)', () => {
5
+ const t = new RedBlackTree<number, number>(); // mapMode default
6
+ t.set(10, 10);
7
+ const h10 = t.getNode(10)!;
8
+
9
+ const n5 = t.setWithHintNode(5, undefined as any, h10);
10
+ expect(n5?.key).toBe(5);
11
+ expect(t.getNode(5)).toBeTruthy();
12
+ expect((t as any)._store.has(5)).toBe(false);
13
+
14
+ const n15 = t.setWithHintNode(15, undefined as any, h10);
15
+ expect(n15?.key).toBe(15);
16
+ expect(t.getNode(15)).toBeTruthy();
17
+ expect((t as any)._store.has(15)).toBe(false);
18
+ });
19
+
20
+ it('pred.right and succ.left attach with undefined value hit _setValue branches', () => {
21
+ const t = new RedBlackTree<number, number>();
22
+ t.set(10, 10);
23
+ const h10 = t.getNode(10)!;
24
+
25
+ // Ensure left is real so we take the pred path.
26
+ t.setWithHintNode(5, 5, h10);
27
+
28
+ // Insert between pred(5) and hint(10): attaches as pred.right.
29
+ const n7 = t.setWithHintNode(7, undefined as any, h10);
30
+ expect(n7?.key).toBe(7);
31
+ expect(t.getNode(7)).toBeTruthy();
32
+ expect((t as any)._store.has(7)).toBe(false);
33
+
34
+ // Ensure right is real so we take the succ path.
35
+ t.setWithHintNode(15, 15, h10);
36
+
37
+ // Insert between hint(10) and succ(15): attaches as succ.left.
38
+ const n12 = t.setWithHintNode(12, undefined as any, h10);
39
+ expect(n12?.key).toBe(12);
40
+ expect(t.getNode(12)).toBeTruthy();
41
+ expect((t as any)._store.has(12)).toBe(false);
42
+ });
43
+ });
@@ -0,0 +1,99 @@
1
+ import { RedBlackTree, RedBlackTreeNode } from '../../../../src';
2
+
3
+ class RBTWithBadCreate extends RedBlackTree<number, number> {
4
+ override createNode(key: number, value?: number): any {
5
+ // Simulate unexpected internal failure so setWithHintNode guard branches are covered.
6
+ // Keys chosen to avoid falling back to _setKVNode boundary attach (which assumes createNode always succeeds).
7
+ if (key === 7 || key === 6 || key === 17 || key === 14) return undefined;
8
+ return super.createNode(key, value);
9
+ }
10
+ }
11
+
12
+ describe('RedBlackTree setWithHintNode more branch coverage', () => {
13
+ it('covers c0===0 update (set mode + mapMode undefined/value)', () => {
14
+ // set mode
15
+ const s = new RedBlackTree<number, number>([], { isMapMode: false });
16
+ s.set(10, 1);
17
+ const h10 = s.getNode(10)!;
18
+ s.setWithHintNode(10, 2, h10);
19
+ expect(s.getNode(10)?.value).toBe(2);
20
+
21
+ // mapMode: value !== undefined uses store.set; value === undefined uses _setValue path.
22
+ const m = new RedBlackTree<number, number>();
23
+ m.set(10, 1);
24
+ const mh10 = m.getNode(10)!;
25
+ m.setWithHintNode(10, 3, mh10);
26
+ expect(m.get(10)).toBe(3);
27
+
28
+ // undefined update should preserve existing value (existing semantics).
29
+ m.setWithHintNode(10, undefined as any, mh10);
30
+ expect(m.get(10)).toBe(3);
31
+ });
32
+
33
+ it('covers c0<0: direct attach to hint.left, pred fallback, and pred.right attach', () => {
34
+ const t = new RedBlackTree<number, number>([], { isMapMode: false });
35
+
36
+ // direct attach: hint.left is empty
37
+ t.set(10, 10);
38
+ const h10 = t.getNode(10)!;
39
+ const n5 = t.setWithHintNode(5, 5, h10)!;
40
+ expect(n5.key).toBe(5);
41
+
42
+ // pred fallback: key equals predecessor (cmp(pred.key,key) >= 0)
43
+ t.setWithHintNode(5, 55, h10);
44
+ expect(t.getNode(5)?.value).toBe(55);
45
+
46
+ // pred.right attach: insert between pred(5) and hint(10)
47
+ const n7 = t.setWithHintNode(7, 7, h10)!;
48
+ expect(n7.key).toBe(7);
49
+ expect(t.getNode(7)?.value).toBe(7);
50
+ });
51
+
52
+ it('covers c0>0: direct attach to hint.right, succ fallback, and succ.left attach', () => {
53
+ const t = new RedBlackTree<number, number>([], { isMapMode: false });
54
+
55
+ // direct attach: hint.right is empty
56
+ t.set(10, 10);
57
+ const h10 = t.getNode(10)!;
58
+ const n15 = t.setWithHintNode(15, 15, h10)!;
59
+ expect(n15.key).toBe(15);
60
+
61
+ // succ fallback: key equals successor (cmp(succ.key,key) <= 0)
62
+ t.setWithHintNode(15, 155, h10);
63
+ expect(t.getNode(15)?.value).toBe(155);
64
+
65
+ // succ.left attach: insert between hint(10) and succ(15)
66
+ const n12 = t.setWithHintNode(12, 12, h10)!;
67
+ expect(n12.key).toBe(12);
68
+ expect(t.getNode(12)?.value).toBe(12);
69
+ });
70
+
71
+ it('covers guard branches where createNode unexpectedly fails (returns undefined)', () => {
72
+ const t = new RBTWithBadCreate([], { isMapMode: false });
73
+ t.set(10, 10);
74
+ const h10 = t.getNode(10)!;
75
+
76
+ // c0<0 direct attach guard (newNode not real)
77
+ expect(t.setWithHintNode(7, 7, h10)).toBeUndefined();
78
+
79
+ // ensure left is real so we go pred-right attach guard
80
+ t.setWithHintNode(5, 5, h10);
81
+ expect(t.setWithHintNode(6, 6, h10)).toBeUndefined();
82
+
83
+ // c0>0 direct attach guard (hint.right is empty)
84
+ expect(t.setWithHintNode(17, 17, h10)).toBeUndefined();
85
+
86
+ // ensure right is real so we go succ-left attach guard (key between hint and succ)
87
+ t.setWithHintNode(15, 15, h10);
88
+ expect(t.setWithHintNode(14, 14, h10)).toBeUndefined();
89
+ });
90
+
91
+ it('covers setWithHintNode fallback when hint is not real', () => {
92
+ const t = new RedBlackTree<number, number>([], { isMapMode: false });
93
+ t.set(1, 1);
94
+
95
+ // Passing NIL should be treated as not-real and fallback to normal set.
96
+ const out = t.setWithHintNode(2, 2, t.NIL as any);
97
+ expect(out?.key).toBe(2);
98
+ });
99
+ });
@@ -0,0 +1,60 @@
1
+ import { RedBlackTree } from '../../../../src';
2
+
3
+ describe('RedBlackTree hint/update coverage', () => {
4
+ it('mapMode update fast-path keeps size and node reference stable', () => {
5
+ const t = new RedBlackTree<number, string>([], { isMapMode: true });
6
+ t.set(1, 'a');
7
+ const n1 = t.getNode(1);
8
+ expect(n1).toBeTruthy();
9
+
10
+ t.set(1, 'b');
11
+ const n2 = t.getNode(1);
12
+
13
+ expect(t.size).toBe(1);
14
+ expect(t.get(1)).toBe('b');
15
+ expect(n2).toBe(n1);
16
+ });
17
+
18
+ it('setWithHintNode covers: no hint -> fallback, c0==0 update, and left/right attach branches', () => {
19
+ const t = new RedBlackTree<number, number>([], { isMapMode: false });
20
+ for (const k of [10, 5, 15]) t.set(k, k);
21
+
22
+ // no hint -> fallback
23
+ const n20 = t.setWithHintNode(20, 20, undefined);
24
+ expect(n20?.key).toBe(20);
25
+
26
+ // c0 == 0 update
27
+ const hint10 = t.getNode(10)!;
28
+ const updated10 = t.setWithHintNode(10, 999, hint10);
29
+ expect(updated10).toBe(hint10);
30
+ expect(t.get(10)).toBe(999);
31
+
32
+ // left attach (hint.left is empty)
33
+ const hint5 = t.getNode(5)!;
34
+ const n2 = t.setWithHintNode(2, 2, hint5);
35
+ expect(n2?.parent?.key).toBe(5);
36
+ expect(n2?.key).toBe(2);
37
+
38
+ // predecessor-right attach (hint.left exists)
39
+ // key=7 is <10, pred(10)=5 and pred.right is empty -> attach there.
40
+ const n7 = t.setWithHintNode(7, 7, hint10);
41
+ expect(n7?.key).toBe(7);
42
+ expect(n7?.parent?.key).toBe(5);
43
+
44
+ // successor-left attach (hint.right exists)
45
+ // key=13 is >10, succ(10)=15 and succ.left is empty -> attach there.
46
+ const n13 = t.setWithHintNode(13, 13, hint10);
47
+ expect(n13?.key).toBe(13);
48
+ expect(n13?.parent?.key).toBe(15);
49
+
50
+ // succ.key <= key fallback branch
51
+ const n30 = t.setWithHintNode(30, 30, hint10);
52
+ expect(n30?.key).toBe(30);
53
+ expect(t.getNode(30)).toBeTruthy();
54
+
55
+ // pred.key >= key fallback branch
56
+ const n4 = t.setWithHintNode(4, 4, hint10);
57
+ expect(n4?.key).toBe(4);
58
+ expect(t.getNode(4)).toBeTruthy();
59
+ });
60
+ });
@@ -0,0 +1,29 @@
1
+ import { RedBlackTree } from '../../../../src';
2
+
3
+ describe('RedBlackTree insert cache nullish coverage', () => {
4
+ it('normal insert repairs nullish header._left/_right via (hMin===NIL || hMax===NIL) fast-path', () => {
5
+ const t = new RedBlackTree<number, number>([], { isMapMode: false });
6
+
7
+ // Build a non-empty tree so header.parent/root is real.
8
+ for (const k of [10, 20, 30]) t.set(k, k);
9
+
10
+ // Corrupt caches so boundary fast-path is skipped (minN becomes NIL via ??) and
11
+ // post-insert cache maintenance sees hMin/hMax as NIL.
12
+ (t as any)._header._left = undefined;
13
+ (t as any)._header._right = undefined;
14
+
15
+ t.set(25, 25);
16
+
17
+ // After insertion, cache maintenance should have initialized both caches.
18
+ expect((t as any)._header._left.key).toBe(25);
19
+ expect((t as any)._header._right.key).toBe(25);
20
+
21
+ // Repair caches to avoid polluting subsequent tests/users.
22
+ const root = (t as any)._root;
23
+ (t as any)._setMinCache(t.isRealNode(root) ? t.getLeftMost((n: any) => n, root) : undefined);
24
+ (t as any)._setMaxCache(t.isRealNode(root) ? t.getRightMost((n: any) => n, root) : undefined);
25
+
26
+ expect((t as any)._header._left.key).toBe(10);
27
+ expect((t as any)._header._right.key).toBe(30);
28
+ });
29
+ });
@@ -0,0 +1,17 @@
1
+ import { RedBlackTree, RedBlackTreeNode } from '../../../../src';
2
+
3
+ describe('RedBlackTree _insert header.parent ?? NIL coverage', () => {
4
+ it('covers _insert with header.parent undefined (current starts at NIL)', () => {
5
+ const t = new RedBlackTree<number, number>([], { isMapMode: false });
6
+
7
+ // Force the _insert walk to start from NIL.
8
+ (t as any)._header.parent = undefined;
9
+ (t as any)._root = t.NIL;
10
+
11
+ const n = new RedBlackTreeNode<number, number>(10, 10, 'BLACK');
12
+ expect(t.set(n, 10)).toBe(true);
13
+
14
+ // Should have established a real root via _setRoot.
15
+ expect(t.getNode(10)?.key).toBe(10);
16
+ });
17
+ });
@@ -0,0 +1,57 @@
1
+ import { RedBlackTree, RedBlackTreeNode } from '../../../../src';
2
+
3
+ describe('RedBlackTree internal walk coverage', () => {
4
+ it('_findNodeByKey covers header.parent ?? NIL and child ?? NIL branches', () => {
5
+ const t = new RedBlackTree<number, number>([], { isMapMode: false });
6
+ t.set(10, 10);
7
+
8
+ // header.parent ?? NIL (set to undefined)
9
+ (t as any)._header.parent = undefined;
10
+ expect((t as any)._findNodeByKey(10)).toBeUndefined();
11
+
12
+ // Restore canonical root pointer.
13
+ (t as any)._header.parent = (t as any)._root;
14
+
15
+ // Force missing children to exercise `cur.left ?? NIL` and `cur.right ?? NIL`.
16
+ const root = (t as any)._header.parent;
17
+ root._left = undefined;
18
+ root._right = undefined;
19
+
20
+ expect((t as any)._findNodeByKey(5)).toBeUndefined();
21
+ expect((t as any)._findNodeByKey(15)).toBeUndefined();
22
+ });
23
+
24
+ it('_insert covers current.left/right ?? NIL branches when root child pointers are undefined', () => {
25
+ const t = new RedBlackTree<number, number>([], { isMapMode: false });
26
+ t.set(10, 10);
27
+
28
+ const root = (t as any)._header.parent;
29
+
30
+ // Insert left with root._left undefined
31
+ root._left = undefined;
32
+ const n5 = new RedBlackTreeNode<number, number>(5, 5, 'BLACK');
33
+ expect(t.set(n5)).toBe(true);
34
+
35
+ // Reset to single root
36
+ t.clear();
37
+ t.set(10, 10);
38
+
39
+ const root2 = (t as any)._header.parent;
40
+ // Insert right with root._right undefined
41
+ root2._right = undefined;
42
+ const n15 = new RedBlackTreeNode<number, number>(15, 15, 'BLACK');
43
+ expect(t.set(n15)).toBe(true);
44
+ });
45
+
46
+ it('_setKVNode covers header._left ?? NIL when header._left is undefined (no boundary fast path)', () => {
47
+ const t = new RedBlackTree<number, number>([], { isMapMode: false });
48
+ t.set(10, 10);
49
+
50
+ // Corrupt cache pointer so `header._left ?? NIL` uses NIL.
51
+ (t as any)._header._left = undefined;
52
+
53
+ // Should still insert normally.
54
+ expect(t.set(5, 5)).toBe(true);
55
+ expect(t.getNode(5)).toBeTruthy();
56
+ });
57
+ });
@@ -0,0 +1,65 @@
1
+ import { RedBlackTree } from '../../../../src';
2
+
3
+ /**
4
+ * Regression tests for RedBlackTree min/max cache + boundary fast paths.
5
+ * Focus: correctness when inserting monotonic keys and deleting boundary nodes.
6
+ */
7
+
8
+ describe('RedBlackTree min/max cache regression', () => {
9
+ it('should keep min/max correct across increasing inserts and boundary deletes', () => {
10
+ const rb = new RedBlackTree<number, number>();
11
+
12
+ for (let i = 0; i < 1000; i++) rb.set(i, i);
13
+
14
+ // delete min repeatedly
15
+ for (let i = 0; i < 250; i++) {
16
+ rb.delete(i);
17
+ const min = rb.getLeftMost(n => n, rb.root);
18
+ expect(min?.key).toBe(i + 1);
19
+ }
20
+
21
+ // delete max repeatedly
22
+ for (let i = 999; i >= 750; i--) {
23
+ rb.delete(i);
24
+ const max = rb.getRightMost(n => n, rb.root);
25
+ expect(max?.key).toBe(i - 1);
26
+ }
27
+ });
28
+
29
+ it('should reset min/max on clear and after deleting to empty', () => {
30
+ const rb = new RedBlackTree<number, number>();
31
+ rb.set(1, 1);
32
+ rb.set(2, 2);
33
+
34
+ rb.clear();
35
+ expect(rb.size).toBe(0);
36
+ expect(rb.getLeftMost(n => n, rb.root)).toBe(undefined);
37
+ expect(rb.getRightMost(n => n, rb.root)).toBe(undefined);
38
+
39
+ rb.set(10, 10);
40
+ rb.delete(10);
41
+ expect(rb.size).toBe(0);
42
+ expect(rb.getLeftMost(n => n, rb.root)).toBe(undefined);
43
+ expect(rb.getRightMost(n => n, rb.root)).toBe(undefined);
44
+ });
45
+
46
+ it('should keep min/max correct across decreasing inserts and boundary deletes', () => {
47
+ const rb = new RedBlackTree<number, number>();
48
+
49
+ for (let i = 1000; i >= 1; i--) rb.set(i, i);
50
+
51
+ // delete min repeatedly
52
+ for (let k = 1; k <= 250; k++) {
53
+ rb.delete(k);
54
+ const min = rb.getLeftMost(n => n, rb.root);
55
+ expect(min?.key).toBe(k + 1);
56
+ }
57
+
58
+ // delete max repeatedly
59
+ for (let k = 1000; k >= 751; k--) {
60
+ rb.delete(k);
61
+ const max = rb.getRightMost(n => n, rb.root);
62
+ expect(max?.key).toBe(k - 1);
63
+ }
64
+ });
65
+ });
@@ -0,0 +1,17 @@
1
+ import { RedBlackTree } from '../../../../src';
2
+
3
+ describe('RedBlackTree misc input coverage', () => {
4
+ it('delete(null) returns [] and does not throw', () => {
5
+ const t = new RedBlackTree<number, number>([], { isMapMode: false });
6
+ t.set(1, 1);
7
+ expect(t.delete(null as any)).toEqual([]);
8
+ expect(t.size).toBe(1);
9
+ });
10
+
11
+ it('delete(undefined) returns [] and does not throw', () => {
12
+ const t = new RedBlackTree<number, number>([], { isMapMode: false });
13
+ t.set(1, 1);
14
+ expect(t.delete(undefined as any)).toEqual([]);
15
+ expect(t.size).toBe(1);
16
+ });
17
+ });
@@ -0,0 +1,121 @@
1
+ import { RedBlackTree, RedBlackTreeNode } from '../../../../src';
2
+
3
+ describe('RedBlackTree remaining reachable branches (coverage)', () => {
4
+ it('mapMode updates existing MAX key with defined value via boundary cMax===0 path inside _setKVNode (covers store.set branch)', () => {
5
+ const t = new RedBlackTree<number, string>([], { isMapMode: true });
6
+ t.set(1, 'a');
7
+ t.set(2, 'b');
8
+
9
+ // Bypass _setKV store.has fast-path by corrupting the store (node exists but store.has(key) is false).
10
+ (t as any)._store.delete(2);
11
+
12
+ // key==max => boundary cMax===0 update in _setKVNode
13
+ t.set(2, 'bb');
14
+ expect(t.get(2)).toBe('bb');
15
+ });
16
+
17
+ it('mapMode updates existing interior key with defined value via normal search update branch inside _setKVNode', () => {
18
+ const t = new RedBlackTree<number, string>([], { isMapMode: true });
19
+ t.set(10, 'x');
20
+ t.set(5, 'a');
21
+ t.set(15, 'z');
22
+
23
+ // Bypass _setKV store.has fast-path for this key.
24
+ (t as any)._store.delete(10);
25
+
26
+ // Update a non-min/non-max key to avoid boundary min/max equality early returns.
27
+ t.set(10, 'xx');
28
+ expect(t.get(10)).toBe('xx');
29
+ });
30
+
31
+ it('normal-path search uses right ?? NIL fallback when a node child pointer is undefined', () => {
32
+ const t = new RedBlackTree<number, number>([], { isMapMode: false });
33
+ t.set(10, 10);
34
+ t.set(5, 5);
35
+
36
+ const n5 = t.getNode(5)!;
37
+
38
+ // Corrupt: right pointer becomes undefined (instead of NIL).
39
+ // This should exercise `current = current.right ?? NIL` fallback.
40
+ (n5 as any).right = undefined;
41
+
42
+ t.set(7, 7);
43
+ expect(t.get(7)).toBe(7);
44
+ });
45
+
46
+ it('setWithHintNode cache maintenance evaluates compare operands in all 4 fast-attach variants', () => {
47
+ // (1) c0 < 0, direct attach to hint.left
48
+ {
49
+ const t = new RedBlackTree<number, number>();
50
+ t.set(10, 10);
51
+ t.set(20, 20);
52
+ // Ensure caches are real nodes (not NIL)
53
+ (t as any)._header._left = t.getNode(10);
54
+ (t as any)._header._right = t.getNode(20);
55
+
56
+ const hint = t.getNode(20)!;
57
+ const n = t.setWithHintNode(15, 15, hint)!;
58
+ expect(n.key).toBe(15);
59
+ }
60
+
61
+ // (2) c0 < 0, attach as right child of predecessor
62
+ {
63
+ const t = new RedBlackTree<number, number>();
64
+ t.set(10, 10);
65
+ t.set(20, 20);
66
+ // Make hint.left real so direct attach is skipped
67
+ t.set(5, 5);
68
+ (t as any)._header._left = t.getNode(5);
69
+ (t as any)._header._right = t.getNode(20);
70
+
71
+ const hint = t.getNode(20)!;
72
+ const n = t.setWithHintNode(15, 15, hint)!;
73
+ expect(n.key).toBe(15);
74
+ }
75
+
76
+ // (3) c0 > 0, direct attach to hint.right
77
+ {
78
+ const t = new RedBlackTree<number, number>();
79
+ t.set(10, 10);
80
+ t.set(20, 20);
81
+ (t as any)._header._left = t.getNode(10);
82
+ (t as any)._header._right = t.getNode(20);
83
+
84
+ const hint = t.getNode(20)!;
85
+ const n = t.setWithHintNode(30, 30, hint)!;
86
+ expect(n.key).toBe(30);
87
+ }
88
+
89
+ // (4) c0 > 0, attach as left child of successor
90
+ {
91
+ const t = new RedBlackTree<number, number>();
92
+ t.set(10, 10);
93
+ t.set(30, 30);
94
+ t.set(20, 20);
95
+ // ensure hint.right is real (30) so direct attach is skipped
96
+ (t as any)._header._left = t.getNode(10);
97
+ (t as any)._header._right = t.getNode(30);
98
+
99
+ const hint = t.getNode(20)!;
100
+ const n = t.setWithHintNode(25, 25, hint)!;
101
+ expect(n.key).toBe(25);
102
+ }
103
+ });
104
+
105
+ it('_leftRotate and _rightRotate early-return when pivot or required child is missing', () => {
106
+ const t = new RedBlackTree<number, number>([], { isMapMode: false });
107
+
108
+ // undefined pivot
109
+ (t as any)._leftRotate(undefined);
110
+ (t as any)._rightRotate(undefined);
111
+
112
+ // pivot exists but missing required child
113
+ const x = new RedBlackTreeNode<number, number>(1);
114
+ (x as any).right = undefined;
115
+ const y = new RedBlackTreeNode<number, number>(2);
116
+ (y as any).left = undefined;
117
+
118
+ (t as any)._leftRotate(x);
119
+ (t as any)._rightRotate(y);
120
+ });
121
+ });
@@ -0,0 +1,55 @@
1
+ import { RedBlackTree } from '../../../../src';
2
+
3
+ describe('RedBlackTree additional reachable branch coverage (batch 3)', () => {
4
+ it('insertion cache: hits parent===hMax and parent===hMin else-if branches', () => {
5
+ const t = new RedBlackTree<number, number>();
6
+
7
+ t.set(2, 2);
8
+ // new max: parent should be current max
9
+ t.set(3, 3);
10
+
11
+ t.clear();
12
+
13
+ t.set(2, 2);
14
+ // new min: parent should be current min
15
+ t.set(1, 1);
16
+
17
+ // Sanity: min/max nodes exist and are ordered.
18
+ expect(t.getLeftMost((n: any) => n)?.key).toBe(1);
19
+ expect(t.getRightMost((n: any) => n)?.key).toBe(2);
20
+ });
21
+
22
+ it('setWithHintNode: executes min/max cache logical-expr second operands across all 4 ultra-fast attach variants', () => {
23
+ const t = new RedBlackTree<number, number>();
24
+
25
+ // Seed non-empty tree so hMin/hMax are real and `hMin===NIL || compare(...)` evaluates RHS.
26
+ t.setMany([
27
+ [10, 10],
28
+ [20, 20],
29
+ [30, 30]
30
+ ]);
31
+
32
+ const n10 = t.getNode(10)!;
33
+ const n20 = t.getNode(20)!;
34
+ const n30 = t.getNode(30)!;
35
+
36
+ // 1) direct attach as left of hint (new global min)
37
+ const n5 = t.setWithHintNode(5, 5, n10);
38
+ expect(n5?.key).toBe(5);
39
+
40
+ // 2) attach as right of predecessor
41
+ const n15 = t.setWithHintNode(15, 15, n20);
42
+ expect(n15?.key).toBe(15);
43
+
44
+ // 3) direct attach as right of hint (new global max)
45
+ const n40 = t.setWithHintNode(40, 40, n30);
46
+ expect(n40?.key).toBe(40);
47
+
48
+ // 4) attach as left of successor
49
+ const n25 = t.setWithHintNode(25, 25, n20);
50
+ expect(n25?.key).toBe(25);
51
+
52
+ expect(t.getLeftMost((n: any) => n)?.key).toBe(5);
53
+ expect(t.getRightMost((n: any) => n)?.key).toBe(40);
54
+ });
55
+ });
@@ -0,0 +1,44 @@
1
+ import { RedBlackTree } from '../../../../src';
2
+
3
+ describe('RedBlackTree additional reachable branch coverage (batch 4)', () => {
4
+ it('setWithHintNode: covers header._left/_right nullish-coalescing RHS (?? NIL) in all 4 ultra-fast attach variants', () => {
5
+ const t = new RedBlackTree<number, number>();
6
+
7
+ t.setMany([
8
+ [10, 10],
9
+ [20, 20],
10
+ [30, 30]
11
+ ]);
12
+
13
+ const n10 = t.getNode(10)!;
14
+ const n20 = t.getNode(20)!;
15
+ const n30 = t.getNode(30)!;
16
+
17
+ const clearHeaderMinMaxToUndefined = () => {
18
+ // Simulate a stale/partial cache state. This is a realistic “repair” scenario:
19
+ // the code uses `?? NIL` to tolerate undefined here.
20
+ (t as any)._header._left = undefined;
21
+ (t as any)._header._right = undefined;
22
+ };
23
+
24
+ // 1) direct attach as left of hint
25
+ clearHeaderMinMaxToUndefined();
26
+ expect(t.setWithHintNode(5, 5, n10)?.key).toBe(5);
27
+
28
+ // 2) attach as right of predecessor
29
+ clearHeaderMinMaxToUndefined();
30
+ expect(t.setWithHintNode(15, 15, n20)?.key).toBe(15);
31
+
32
+ // 3) direct attach as right of hint
33
+ clearHeaderMinMaxToUndefined();
34
+ expect(t.setWithHintNode(40, 40, n30)?.key).toBe(40);
35
+
36
+ // 4) attach as left of successor
37
+ clearHeaderMinMaxToUndefined();
38
+ expect(t.setWithHintNode(25, 25, n20)?.key).toBe(25);
39
+
40
+ // Sanity: tree still orders correctly.
41
+ expect(t.getLeftMost(n => n)?.key).toBe(5);
42
+ expect(t.getRightMost(n => n)?.key).toBe(40);
43
+ });
44
+ });