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,110 @@
1
+ import { Heap, FibonacciHeap } from '../../../../src';
2
+
3
+ describe('Heap / FibonacciHeap misc branch coverage', () => {
4
+ it('Heap.deleteBy covers not-found, idx=0 poll, idx=last pop, idx=middle splice paths', () => {
5
+ const h = new Heap<number>();
6
+ h.add(3);
7
+ h.add(1);
8
+ h.add(2);
9
+
10
+ expect(h.deleteBy(() => false)).toBe(false); // idx stays -1
11
+
12
+ // idx === 0
13
+ expect(h.deleteBy(x => x === h.peek())).toBe(true);
14
+
15
+ // ensure at least 2 elems again
16
+ h.add(4);
17
+ h.add(5);
18
+
19
+ // idx === last
20
+ const last = (h as any).elements[(h as any).elements.length - 1];
21
+ expect(h.deleteBy(x => x === last)).toBe(true);
22
+
23
+ // idx in middle
24
+ const mid = (h as any).elements[1];
25
+ expect(h.deleteBy(x => x === mid)).toBe(true);
26
+ });
27
+
28
+ it('Heap.filter covers thisArg branch and else(i++) branch', () => {
29
+ const h = new Heap<number>();
30
+ h.add(1);
31
+ h.add(2);
32
+ h.add(3);
33
+
34
+ const ctx = { ok: true };
35
+ const out = h.filter(function (this: any, x: number) {
36
+ // keep only one element so the else branch runs too
37
+ return this.ok && x === 2;
38
+ }, ctx);
39
+
40
+ expect(out.toArray()).toEqual([2]);
41
+ });
42
+
43
+ it('Heap.map throws when comparator missing, and uses thisArg branch when provided', () => {
44
+ const h = new Heap<number>();
45
+ h.add(1);
46
+ h.add(2);
47
+
48
+ expect(() => h.map(x => ({ x }), {} as any)).toThrow(/requires options\.comparator/i);
49
+
50
+ const ctx = { mul: 10 };
51
+ const mapped = h.map(
52
+ function (this: any, x: number) {
53
+ return x * this.mul;
54
+ },
55
+ { comparator: (a: number, b: number) => a - b },
56
+ ctx
57
+ );
58
+
59
+ expect(mapped.peek()).toBe(10);
60
+ });
61
+
62
+ it('Heap.mapSame covers thisArg branch', () => {
63
+ const h = new Heap<number>();
64
+ h.add(1);
65
+ h.add(3);
66
+
67
+ const ctx = { add: 7 };
68
+ const out = h.mapSame(function (this: any, x: number) {
69
+ return x + this.add;
70
+ }, ctx);
71
+
72
+ expect(out.peek()).toBe(8);
73
+ });
74
+
75
+ it('Heap._createLike default-arg path can be called via (heap as any)._createLike()', () => {
76
+ const h = new Heap<number>();
77
+ const like = (h as any)._createLike();
78
+ expect(like.size).toBe(0);
79
+ });
80
+
81
+ it('FibonacciHeap constructor throws when comparator is not a function', () => {
82
+ expect(() => new FibonacciHeap<number>(123 as any)).toThrow(/comparator must be a function/i);
83
+ });
84
+
85
+ it('FibonacciHeap.consumeLinkedList(undefined) returns [] (covers !head guard)', () => {
86
+ const fh = new FibonacciHeap<number>();
87
+ expect(fh.consumeLinkedList(undefined)).toEqual([]);
88
+ });
89
+
90
+ it('FibonacciHeap.merge covers empty-merge early return, empty-this adopt-root, and non-empty root-merge', () => {
91
+ const a = new FibonacciHeap<number>();
92
+ const b = new FibonacciHeap<number>();
93
+
94
+ // empty merge early return
95
+ a.merge(b);
96
+ expect(a.size).toBe(0);
97
+
98
+ // empty-this adopt-root
99
+ b.add(5);
100
+ a.merge(b);
101
+ expect(a.size).toBe(1);
102
+
103
+ // non-empty root-merge + min update paths
104
+ const c = new FibonacciHeap<number>();
105
+ c.add(1);
106
+ c.add(10);
107
+ a.merge(c);
108
+ expect(a.peek()).toBe(1);
109
+ });
110
+ });
@@ -0,0 +1,22 @@
1
+ import { Heap } from '../../../../src';
2
+
3
+ describe('Heap remaining branch coverage', () => {
4
+ it('Heap.map with options undefined hits (options ?? {}) path and throws for missing comparator', () => {
5
+ const h = new Heap<number>();
6
+ h.add(1);
7
+ expect(() => (h as any).map((x: number) => x, undefined)).toThrow(/requires options\.comparator/i);
8
+ });
9
+
10
+ it('Heap.mapSame without thisArg hits thisArg===undefined branch', () => {
11
+ const h = new Heap<number>();
12
+ h.add(1);
13
+ h.add(2);
14
+ const out = h.mapSame(x => x * 2);
15
+ expect(out.toArray().sort((a, b) => a - b)).toEqual([2, 4]);
16
+ });
17
+
18
+ it('Heap default comparator throws when comparing object types', () => {
19
+ const h = new Heap<any>();
20
+ expect(() => (h as any)._DEFAULT_COMPARATOR({}, 1)).toThrow(TypeError);
21
+ });
22
+ });
@@ -0,0 +1,29 @@
1
+ import { MaxHeap } from '../../../../src';
2
+
3
+ /**
4
+ * Coverage-focused test for MaxHeap comparator branches.
5
+ * Keep existing @example tests intact.
6
+ */
7
+ describe('MaxHeap coverage', () => {
8
+ it('orders numbers as a max-heap (a<b / a>b / equal branches)', () => {
9
+ const h = new MaxHeap<number>();
10
+
11
+ h.add(2);
12
+ h.add(1);
13
+ h.add(3);
14
+ h.add(3); // equal branch exercised during comparisons
15
+
16
+ expect(h.peek()).toBe(3);
17
+ expect(h.poll()).toBe(3);
18
+ expect(h.poll()).toBe(3);
19
+ expect(h.poll()).toBe(2);
20
+ expect(h.poll()).toBe(1);
21
+ expect(h.poll()).toBe(undefined);
22
+ });
23
+
24
+ it('throws when comparing object types without custom comparator', () => {
25
+ const h = new MaxHeap<any>();
26
+ h.add({ k: 1 });
27
+ expect(() => h.add({ k: 2 })).toThrow(TypeError);
28
+ });
29
+ });
@@ -0,0 +1,72 @@
1
+ import { DoublyLinkedList, DoublyLinkedListNode } from '../../../../src';
2
+
3
+ describe('DoublyLinkedList additional branch coverage', () => {
4
+ it('unshiftMany uses toElementFn branch when provided', () => {
5
+ const l = new DoublyLinkedList<number, { v: number }>([], {
6
+ toElementFn: r => r.v
7
+ });
8
+ expect(l.unshiftMany([{ v: 1 }, { v: 2 }])).toEqual([true, true]);
9
+ expect(l.toArray()).toEqual([2, 1]);
10
+ });
11
+
12
+ it('getNode(undefined) returns undefined (covers early return)', () => {
13
+ const l = new DoublyLinkedList<number>();
14
+ l.pushMany([1, 2]);
15
+ expect(l.getNode(undefined)).toBeUndefined();
16
+ });
17
+
18
+ it('setAt returns false when node does not exist', () => {
19
+ const l = new DoublyLinkedList<number>();
20
+ expect(l.setAt(0, 1)).toBe(false);
21
+ });
22
+
23
+ it('search returns value when predicate matches (covers predicate(current) true branch)', () => {
24
+ const l = new DoublyLinkedList<number>();
25
+ l.pushMany([1, 2, 3]);
26
+ expect(l.search(n => n.value === 2)).toBe(2);
27
+ });
28
+
29
+ it('mapSame covers both thisArg branches', () => {
30
+ const l = new DoublyLinkedList<number>();
31
+ l.pushMany([1, 2]);
32
+
33
+ // thisArg === undefined arm
34
+ expect(l.mapSame(v => v + 1).toArray()).toEqual([2, 3]);
35
+
36
+ // thisArg provided arm
37
+ const ctx = { add: 10 };
38
+ expect(
39
+ l
40
+ .mapSame(function (this: any, v: number) {
41
+ return v + this.add;
42
+ }, ctx)
43
+ .toArray()
44
+ ).toEqual([11, 12]);
45
+ });
46
+
47
+ it('_ensureNode returns the same node when input is a node (covers isNode true branch)', () => {
48
+ const l = new DoublyLinkedList<number>();
49
+ l.pushMany([1, 3]);
50
+
51
+ const existing = l.getNodeAt(0)!;
52
+ const newNode = new DoublyLinkedListNode(2);
53
+
54
+ // addAfter calls _ensureNode(newElementOrNode)
55
+ expect(l.addAfter(existing, newNode)).toBe(true);
56
+ expect(l.toArray()).toEqual([1, 2, 3]);
57
+ });
58
+
59
+ it('_ensurePredicate covers isNode(target) branch via search(node)', () => {
60
+ const l = new DoublyLinkedList<number>();
61
+ l.pushMany([1, 2, 3]);
62
+
63
+ const target = l.getNodeAt(1)!;
64
+ expect(l.search(target)).toBe(2);
65
+ });
66
+
67
+ it('_createLike default-arg path can be called with no args', () => {
68
+ const l = new DoublyLinkedList<number>();
69
+ const like = (l as any)._createLike();
70
+ expect(like.length).toBe(0);
71
+ });
72
+ });
@@ -0,0 +1,15 @@
1
+ import { DoublyLinkedList, SinglyLinkedList } from '../../../../src';
2
+
3
+ describe('LinkedList unshiftMany else-branch coverage', () => {
4
+ it('DoublyLinkedList.unshiftMany uses else-branch when toElementFn is not provided', () => {
5
+ const l = new DoublyLinkedList<number>();
6
+ expect(l.unshiftMany([1, 2])).toEqual([true, true]);
7
+ expect(l.toArray()).toEqual([2, 1]);
8
+ });
9
+
10
+ it('SinglyLinkedList.unshiftMany uses else-branch when toElementFn is not provided', () => {
11
+ const l = new SinglyLinkedList<number>();
12
+ expect(l.unshiftMany([1, 2])).toEqual([true, true]);
13
+ expect(l.toArray()).toEqual([2, 1]);
14
+ });
15
+ });
@@ -0,0 +1,221 @@
1
+ import { SinglyLinkedList, SinglyLinkedListNode } from '../../../../src';
2
+
3
+ describe('SinglyLinkedList coverage', () => {
4
+ it('push respects maxLen by shifting when over capacity', () => {
5
+ const list = new SinglyLinkedList<number>([], { maxLen: 2 });
6
+ list.push(1);
7
+ list.push(2);
8
+ list.push(3); // should shift 1
9
+ expect([...list]).toEqual([2, 3]);
10
+ expect(list.length).toBe(2);
11
+ expect(list.first).toBe(2);
12
+ expect(list.last).toBe(3);
13
+ });
14
+
15
+ it('pop covers empty, single-node, and multi-node cases', () => {
16
+ const empty = new SinglyLinkedList<number>();
17
+ expect(empty.pop()).toBeUndefined();
18
+
19
+ const single = new SinglyLinkedList<number>([1]);
20
+ expect(single.pop()).toBe(1);
21
+ expect(single.length).toBe(0);
22
+ expect(single.head).toBeUndefined();
23
+ expect(single.tail).toBeUndefined();
24
+
25
+ const multi = new SinglyLinkedList<number>([1, 2, 3]);
26
+ expect(multi.pop()).toBe(3);
27
+ expect([...multi]).toEqual([1, 2]);
28
+ expect(multi.tail?.value).toBe(2);
29
+ });
30
+
31
+ it('shift/unshift handle empty and update tail when last removed', () => {
32
+ const list = new SinglyLinkedList<number>();
33
+ expect(list.shift()).toBeUndefined();
34
+
35
+ list.unshift(1);
36
+ expect(list.shift()).toBe(1);
37
+ expect(list.head).toBeUndefined();
38
+ expect(list.tail).toBeUndefined();
39
+ expect(list.length).toBe(0);
40
+ });
41
+
42
+ it('pushMany/unshiftMany exercise toElementFn conversion branch', () => {
43
+ const list = new SinglyLinkedList<number, { v: number }>([], { toElementFn: r => r.v });
44
+
45
+ expect(list.pushMany([{ v: 1 }, { v: 2 }])).toEqual([true, true]);
46
+ expect([...list]).toEqual([1, 2]);
47
+
48
+ expect(list.unshiftMany([{ v: 3 }, { v: 4 }])).toEqual([true, true]);
49
+ expect([...list]).toEqual([4, 3, 1, 2]);
50
+ });
51
+
52
+ it('at/getNodeAt/setAt cover bounds and success cases', () => {
53
+ const list = new SinglyLinkedList<number>([1, 2, 3]);
54
+
55
+ expect(list.at(-1)).toBeUndefined();
56
+ expect(list.at(999)).toBeUndefined();
57
+ expect(list.at(1)).toBe(2);
58
+
59
+ expect(list.getNodeAt(-1)).toBeUndefined();
60
+ expect(list.getNodeAt(999)).toBeUndefined();
61
+
62
+ expect(list.setAt(999, 0)).toBe(false);
63
+ expect(list.setAt(1, 20)).toBe(true);
64
+ expect([...list]).toEqual([1, 20, 3]);
65
+ });
66
+
67
+ it('deleteAt covers head delete, tail delete, and middle delete', () => {
68
+ const list = new SinglyLinkedList<number>([1, 2, 3]);
69
+
70
+ expect(list.deleteAt(-1)).toBeUndefined();
71
+ expect(list.deleteAt(999)).toBeUndefined();
72
+
73
+ // head
74
+ expect(list.deleteAt(0)).toBe(1);
75
+ expect([...list]).toEqual([2, 3]);
76
+
77
+ // tail
78
+ expect(list.deleteAt(1)).toBe(3);
79
+ expect([...list]).toEqual([2]);
80
+ expect(list.tail?.value).toBe(2);
81
+
82
+ // middle (rebuild)
83
+ list.pushMany([3, 4]); // [2,3,4]
84
+ expect(list.deleteAt(1)).toBe(3);
85
+ expect([...list]).toEqual([2, 4]);
86
+ });
87
+
88
+ it('delete covers undefined input, missing node, and deleting head/tail', () => {
89
+ const list = new SinglyLinkedList<number>([1, 2, 3]);
90
+
91
+ expect(list.delete(undefined)).toBe(false);
92
+ expect(list.delete(999)).toBe(false);
93
+
94
+ // delete head
95
+ expect(list.delete(1)).toBe(true);
96
+ expect([...list]).toEqual([2, 3]);
97
+
98
+ // delete tail
99
+ expect(list.delete(3)).toBe(true);
100
+ expect([...list]).toEqual([2]);
101
+ expect(list.tail?.value).toBe(2);
102
+ });
103
+
104
+ it('reverse early-return and full reverse path', () => {
105
+ const empty = new SinglyLinkedList<number>();
106
+ expect(empty.reverse()).toBe(empty);
107
+
108
+ const single = new SinglyLinkedList<number>([1]);
109
+ expect([...single.reverse()]).toEqual([1]);
110
+
111
+ const list = new SinglyLinkedList<number>([1, 2, 3]);
112
+ list.reverse();
113
+ expect([...list]).toEqual([3, 2, 1]);
114
+ expect(list.first).toBe(3);
115
+ expect(list.last).toBe(1);
116
+ });
117
+
118
+ it('getNode/search handle undefined, node pass-through, and predicate branches', () => {
119
+ const list = new SinglyLinkedList<number>([1, 2, 3]);
120
+ expect(list.getNode(undefined)).toBeUndefined();
121
+
122
+ const n2 = list.getNodeAt(1)!;
123
+ expect(list.getNode(n2)).toBe(n2);
124
+
125
+ expect(list.getNode(node => node.value === 3)?.value).toBe(3);
126
+ expect(list.search(node => node.value === 2)).toBe(2);
127
+ });
128
+
129
+ it('addAt/addBefore/addAfter cover boundary and missing-node cases', () => {
130
+ const list = new SinglyLinkedList<number>([2, 4]);
131
+
132
+ expect(list.addAt(-1, 0)).toBe(false);
133
+ expect(list.addAt(999, 0)).toBe(false);
134
+
135
+ // addAt head/tail/middle
136
+ expect(list.addAt(0, 1)).toBe(true);
137
+ expect(list.addAt(list.length, 5)).toBe(true);
138
+ expect(list.addAt(2, 3)).toBe(true);
139
+ expect([...list]).toEqual([1, 2, 3, 4, 5]);
140
+
141
+ // addBefore/After missing
142
+ expect(list.addBefore(999, 0)).toBe(false);
143
+ expect(list.addAfter(999, 0)).toBe(false);
144
+
145
+ // addBefore head
146
+ expect(list.addBefore(1, 0)).toBe(true);
147
+ // addAfter tail
148
+ expect(list.addAfter(5, 6)).toBe(true);
149
+ expect([...list]).toEqual([0, 1, 2, 3, 4, 5, 6]);
150
+ });
151
+
152
+ it('splice covers remove-only, insert-only, remove+insert, and empty-result reset', () => {
153
+ const list = new SinglyLinkedList<number>([1, 2, 3, 4]);
154
+
155
+ // remove middle
156
+ const removed = list.splice(1, 2);
157
+ expect([...removed]).toEqual([2, 3]);
158
+ expect([...list]).toEqual([1, 4]);
159
+
160
+ // insert at head without deletion
161
+ const removed2 = list.splice(0, 0, 9, 8);
162
+ expect([...removed2]).toEqual([]);
163
+ expect([...list]).toEqual([9, 8, 1, 4]);
164
+
165
+ // remove tail and insert
166
+ const removed3 = list.splice(3, 10, 7);
167
+ expect([...removed3]).toEqual([4]);
168
+ expect([...list]).toEqual([9, 8, 1, 7]);
169
+
170
+ // remove everything, expect head/tail reset
171
+ const removedAll = list.splice(0, 999);
172
+ expect([...removedAll]).toEqual([9, 8, 1, 7]);
173
+ expect(list.length).toBe(0);
174
+ expect(list.head).toBeUndefined();
175
+ expect(list.tail).toBeUndefined();
176
+ });
177
+
178
+ it('countOccurrences covers element/node/predicate branches and setEquality', () => {
179
+ type Obj = { id: number };
180
+ const a: Obj = { id: 1 };
181
+ const b: Obj = { id: 1 };
182
+ const c: Obj = { id: 2 };
183
+
184
+ const list = new SinglyLinkedList<Obj>([a, c]);
185
+
186
+ // default Object.is: b is not the same ref as a
187
+ expect(list.countOccurrences(b)).toBe(0);
188
+
189
+ list.setEquality((x, y) => x.id === y.id);
190
+ expect(list.countOccurrences(b)).toBe(1);
191
+
192
+ const nodeA = list.getNodeAt(0)!;
193
+ expect(list.countOccurrences(nodeA)).toBe(1);
194
+
195
+ expect(list.countOccurrences(node => node.value.id === 2)).toBe(1);
196
+ });
197
+
198
+ it('deleteWhere covers deleting head and tail branches + no-match', () => {
199
+ const list = new SinglyLinkedList<number>([1, 2, 3]);
200
+
201
+ // delete head branch
202
+ expect(list.deleteWhere(v => v === 1)).toBe(true);
203
+ expect([...list]).toEqual([2, 3]);
204
+
205
+ // delete tail branch
206
+ expect(list.deleteWhere(v => v === 3)).toBe(true);
207
+ expect([...list]).toEqual([2]);
208
+ expect(list.tail?.value).toBe(2);
209
+
210
+ // no match
211
+ expect(list.deleteWhere(v => v === 999)).toBe(false);
212
+ });
213
+
214
+ it('_getPrevNode not-found branch via foreign node', () => {
215
+ const list = new SinglyLinkedList<number>([1, 2, 3]);
216
+ const foreign = new SinglyLinkedListNode(2);
217
+
218
+ // Access protected for branch coverage.
219
+ expect((list as any)._getPrevNode(foreign)).toBeUndefined();
220
+ });
221
+ });
@@ -0,0 +1,86 @@
1
+ import { SinglyLinkedList, SinglyLinkedListNode } from '../../../../src';
2
+
3
+ describe('SinglyLinkedList additional branch coverage', () => {
4
+ it('unshiftMany uses toElementFn branch when provided', () => {
5
+ const l = new SinglyLinkedList<number, { v: number }>([], {
6
+ toElementFn: r => r.v
7
+ });
8
+ expect(l.unshiftMany([{ v: 1 }, { v: 2 }])).toEqual([true, true]);
9
+ expect(l.toArray()).toEqual([2, 1]);
10
+ });
11
+
12
+ it('addBefore sets tail when prevNode is undefined and internal tail is missing (covers if(!this._tail))', () => {
13
+ const l = new SinglyLinkedList<number>();
14
+ l.push(1);
15
+
16
+ // Corrupt internal tail so the recovery branch runs.
17
+ (l as any)._tail = undefined;
18
+
19
+ expect(l.addBefore(1, 0)).toBe(true);
20
+ expect(l.toArray()).toEqual([0, 1]);
21
+ // and tail should be restored (best-effort invariant)
22
+ expect((l as any)._tail).toBeDefined();
23
+ });
24
+
25
+ it('splice uses default deleteCount=0 when omitted', () => {
26
+ const l = new SinglyLinkedList<number>();
27
+ l.pushMany([1, 2, 3]);
28
+
29
+ const removed = l.splice(1); // deleteCount omitted
30
+ expect(removed.toArray()).toEqual([]);
31
+ expect(l.toArray()).toEqual([1, 2, 3]);
32
+ });
33
+
34
+ it('deleteWhere sets tail to undefined when removing the only element (covers current===_tail branch)', () => {
35
+ const l = new SinglyLinkedList<number>();
36
+ l.push(1);
37
+
38
+ expect(l.deleteWhere(v => v === 1)).toBe(true);
39
+ expect(l.length).toBe(0);
40
+ expect((l as any)._tail).toBeUndefined();
41
+ });
42
+
43
+ it('mapSame covers both ternary arms (thisArg undefined vs defined)', () => {
44
+ const l = new SinglyLinkedList<number>();
45
+ l.pushMany([1, 2]);
46
+
47
+ // thisArg === undefined branch
48
+ expect(l.mapSame(v => v + 1).toArray()).toEqual([2, 3]);
49
+
50
+ // thisArg provided branch
51
+ const ctx = { add: 10 };
52
+ expect(
53
+ l
54
+ .mapSame(function (this: any, v: number) {
55
+ return v + this.add;
56
+ }, ctx)
57
+ .toArray()
58
+ ).toEqual([11, 12]);
59
+ });
60
+
61
+ it('_ensureNode returns the same node when input is a node (covers isNode true branch)', () => {
62
+ const l = new SinglyLinkedList<number>();
63
+ l.pushMany([1, 3]);
64
+
65
+ const existing = l.getNodeAt(0)!;
66
+ const newNode = new SinglyLinkedListNode(2);
67
+
68
+ // addAfter calls _ensureNode(newElementOrNode)
69
+ expect(l.addAfter(existing, newNode)).toBe(true);
70
+ expect(l.toArray()).toEqual([1, 2, 3]);
71
+ });
72
+
73
+ it('_ensurePredicate covers isNode(target) branch via search(node)', () => {
74
+ const l = new SinglyLinkedList<number>();
75
+ l.pushMany([1, 2, 3]);
76
+
77
+ const target = l.getNodeAt(1)!;
78
+ expect(l.search(target)).toBe(2);
79
+ });
80
+
81
+ it('_createLike default-arg path can be called with no args', () => {
82
+ const l = new SinglyLinkedList<number>();
83
+ const like = (l as any)._createLike();
84
+ expect(like.length).toBe(0);
85
+ });
86
+ });
@@ -0,0 +1,31 @@
1
+ import { SkipList } from '../../../../src';
2
+
3
+ describe('SkipList additional branch coverage', () => {
4
+ it('constructor applies options branches (maxLevel/probability) and first() returns undefined when empty', () => {
5
+ const s = new SkipList<number, number>([], { maxLevel: 8, probability: 0.25 });
6
+ expect(s.maxLevel).toBe(8);
7
+ expect(s.probability).toBe(0.25);
8
+
9
+ // covers `firstNode ? ... : undefined` false arm
10
+ expect(s.first).toBeUndefined();
11
+ });
12
+
13
+ it('delete() covers the break branch when deleted node has smaller level than list level', () => {
14
+ const s = new SkipList<number, string>();
15
+
16
+ // Force deterministic node levels: first node makes list level high, second is low-level.
17
+ const origRandomLevel = (s as any)._randomLevel;
18
+ const levels = [4, 1];
19
+ (s as any)._randomLevel = () => levels.shift() ?? 1;
20
+ try {
21
+ s.add(1, 'hi'); // level 4, end -> raises list level
22
+ s.add(2, 'lo'); // level 1, end, list level stays 4
23
+
24
+ expect(s.level).toBeGreaterThan(1);
25
+ expect(s.delete(2)).toBe(true);
26
+ expect(s.get(2)).toBeUndefined();
27
+ } finally {
28
+ (s as any)._randomLevel = origRandomLevel;
29
+ }
30
+ });
31
+ });
@@ -0,0 +1,81 @@
1
+ import { Matrix } from '../../../../src';
2
+
3
+ describe('Matrix additional branch coverage', () => {
4
+ it('inverse throws when matrix is singular (pivotRow reaches rows)', () => {
5
+ const m = new Matrix([[0]], { rows: 1, cols: 1 });
6
+ expect(() => m.inverse()).toThrow(/singular/i);
7
+ });
8
+
9
+ it('inverse hits division-by-zero guard (pivotElement===0) via get() monkeypatch', () => {
10
+ const m = new Matrix(
11
+ [
12
+ [1, 0],
13
+ [0, 1]
14
+ ],
15
+ { rows: 2, cols: 2 }
16
+ );
17
+
18
+ const origGet = (Matrix as any).prototype.get;
19
+ try {
20
+ (Matrix as any).prototype.get = function (row: number, col: number) {
21
+ // Make pivot search succeed (non-zero) but pivot element read as 0.
22
+ if (row === col) return 0;
23
+ return 1;
24
+ };
25
+ expect(() => m.inverse()).toThrow(/division by zero/i);
26
+ } finally {
27
+ (Matrix as any).prototype.get = origGet;
28
+ }
29
+ });
30
+
31
+ it('inverse treats undefined elimination factor as 0 (factor===undefined branch)', () => {
32
+ const m = new Matrix(
33
+ [
34
+ [1, 0],
35
+ [0, 1]
36
+ ],
37
+ { rows: 2, cols: 2 }
38
+ );
39
+
40
+ const origGet = (Matrix as any).prototype.get;
41
+ try {
42
+ (Matrix as any).prototype.get = function (row: number, col: number) {
43
+ // Provide real diagonal for pivoting
44
+ if (row === col) return 1;
45
+ // For elimination factor reads (j,i) when j!=i, return undefined
46
+ return undefined;
47
+ };
48
+
49
+ // Should still return something (we only care about branch execution)
50
+ const inv = m.inverse();
51
+ expect(inv?.rows).toBe(2);
52
+ expect(inv?.cols).toBe(2);
53
+ } finally {
54
+ (Matrix as any).prototype.get = origGet;
55
+ }
56
+ });
57
+
58
+ it('_scaleRow and _addScaledRow coerce undefined multiply/add results to 0', () => {
59
+ const m = new Matrix(
60
+ [
61
+ [1, 2],
62
+ [3, 4]
63
+ ],
64
+ {
65
+ rows: 2,
66
+ cols: 2,
67
+ multiplyFn: () => undefined as any,
68
+ addFn: () => undefined as any
69
+ }
70
+ );
71
+
72
+ // call protected helpers via any
73
+ (m as any)._scaleRow(0, 2);
74
+ expect(m.data[0][0]).toBe(0);
75
+ expect(m.data[0][1]).toBe(0);
76
+
77
+ (m as any)._addScaledRow(1, 0, 3);
78
+ expect(m.data[1][0]).toBe(0);
79
+ expect(m.data[1][1]).toBe(0);
80
+ });
81
+ });