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,28 @@
1
+ import { Matrix } from '../../../../src';
2
+
3
+ describe('Matrix inverse pivotElement ?? 1 remaining branch coverage', () => {
4
+ it('inverse() uses pivotElement fallback 1 when get(i,i) is nullish', () => {
5
+ const origGet = Matrix.prototype.get;
6
+ try {
7
+ Matrix.prototype.get = function (row: number, col: number): any {
8
+ if (row === 0 && col === 0) return undefined;
9
+ return origGet.call(this, row, col);
10
+ };
11
+
12
+ const m = new Matrix([
13
+ [1, 0],
14
+ [0, 1]
15
+ ]);
16
+
17
+ const inv = m.inverse();
18
+
19
+ // Restore before asserting so inv.get is not affected.
20
+ Matrix.prototype.get = origGet;
21
+
22
+ expect(inv?.get(0, 0)).toBe(1);
23
+ expect(inv?.get(1, 1)).toBe(1);
24
+ } finally {
25
+ Matrix.prototype.get = origGet;
26
+ }
27
+ });
28
+ });
@@ -0,0 +1,10 @@
1
+ import { MaxPriorityQueue } from '../../../../src';
2
+
3
+ describe('MaxPriorityQueue remaining branch coverage', () => {
4
+ it('default comparator throws when comparing object elements', () => {
5
+ const pq = new MaxPriorityQueue<any>();
6
+ // call comparator directly to deterministically hit the throw branch
7
+ const cmp = (pq as any).comparator as (a: any, b: any) => number;
8
+ expect(() => cmp({ a: 1 }, { b: 2 })).toThrow(TypeError);
9
+ });
10
+ });
@@ -0,0 +1,21 @@
1
+ import { PriorityQueue } from '../../../../src';
2
+
3
+ /**
4
+ * Coverage-focused test for PriorityQueue thin wrapper.
5
+ * Keep existing @example tests intact.
6
+ */
7
+ describe('PriorityQueue coverage', () => {
8
+ it('constructs and supports basic add/poll via Heap API', () => {
9
+ const pq = new PriorityQueue<number>();
10
+ pq.add(3);
11
+ pq.add(1);
12
+ pq.add(2);
13
+
14
+ // Default PriorityQueue here behaves as a min-heap.
15
+ expect(pq.peek()).toBe(1);
16
+ expect(pq.poll()).toBe(1);
17
+ expect(pq.poll()).toBe(2);
18
+ expect(pq.poll()).toBe(3);
19
+ expect(pq.poll()).toBe(undefined);
20
+ });
21
+ });
@@ -0,0 +1,173 @@
1
+ import { Deque } from '../../../../src';
2
+
3
+ describe('Deque coverage', () => {
4
+ it('constructor handles iterable-like length()/size() branches and bucketSize option', () => {
5
+ const arr = [1, 2, 3, 4, 5];
6
+
7
+ const withLengthFn = {
8
+ length: () => arr.length,
9
+ [Symbol.iterator]: function* () {
10
+ yield* arr;
11
+ }
12
+ } as any;
13
+
14
+ const d1 = new Deque<number>(withLengthFn, { bucketSize: 4 });
15
+ expect(d1.bucketSize).toBe(4);
16
+ expect([...d1]).toEqual(arr);
17
+
18
+ const withSizeFn = {
19
+ size: () => arr.length,
20
+ [Symbol.iterator]: function* () {
21
+ yield* arr;
22
+ }
23
+ } as any;
24
+
25
+ const d2 = new Deque<number>(withSizeFn, { bucketSize: 4 });
26
+ expect([...d2]).toEqual(arr);
27
+ });
28
+
29
+ it('push/unshift respect maxLen (trigger shift/pop) and cover wrap-around + reallocate', () => {
30
+ // small bucket to make wrap/reallocate reachable with few ops
31
+ const d = new Deque<number>([], { bucketSize: 4, maxLen: 5 });
32
+
33
+ // Fill and force internal pointers to wrap a couple times
34
+ for (let i = 0; i < 20; i++) d.push(i);
35
+ expect(d.length).toBe(5);
36
+ expect([...d]).toEqual([15, 16, 17, 18, 19]);
37
+
38
+ for (let i = 100; i < 110; i++) d.unshift(i);
39
+ expect(d.length).toBe(5);
40
+ // unshift beyond maxLen pops from end
41
+ expect([...d]).toEqual([109, 108, 107, 106, 105]);
42
+ });
43
+
44
+ it('pop/shift on empty and singleton cases', () => {
45
+ const empty = new Deque<number>([], { bucketSize: 4 });
46
+ expect(empty.pop()).toBeUndefined();
47
+ expect(empty.shift()).toBeUndefined();
48
+ expect(empty.first).toBeUndefined();
49
+ expect(empty.last).toBeUndefined();
50
+
51
+ const one = new Deque<number>([1], { bucketSize: 4 });
52
+ expect(one.first).toBe(1);
53
+ expect(one.last).toBe(1);
54
+ expect(one.pop()).toBe(1);
55
+ expect(one.length).toBe(0);
56
+
57
+ one.push(2);
58
+ expect(one.shift()).toBe(2);
59
+ expect(one.length).toBe(0);
60
+ });
61
+
62
+ it('at/setAt/addAt/deleteAt/splice rangeCheck throwing + success paths', () => {
63
+ const d = new Deque<number>([1, 2, 3], { bucketSize: 4 });
64
+
65
+ expect(d.at(-1)).toBeUndefined();
66
+ expect(d.at(999)).toBeUndefined();
67
+
68
+ expect(() => d.setAt(-1 as any, 0)).toThrow();
69
+ expect(() => d.setAt(999 as any, 0)).toThrow();
70
+ expect(d.setAt(1, 20)).toBe(true);
71
+ expect([...d]).toEqual([1, 20, 3]);
72
+
73
+ expect(() => d.addAt(-1 as any, 0)).toThrow();
74
+ expect(() => d.deleteAt(-1 as any)).toThrow();
75
+ expect(() => d.splice(999 as any, 0)).toThrow();
76
+
77
+ // addAt: pos=0 and pos=length branches
78
+ d.addAt(0, 9, 2);
79
+ d.addAt(d.length, 7, 1);
80
+ expect(d.first).toBe(9);
81
+ expect(d.last).toBe(7);
82
+
83
+ // deleteAt: middle shift loop branch
84
+ const mid = d.deleteAt(2);
85
+ expect(mid).toBeDefined();
86
+ });
87
+
88
+ it('cut/cutRest cover in-place and copy branches', () => {
89
+ const d = new Deque<number>([1, 2, 3, 4, 5], { bucketSize: 4 });
90
+
91
+ const prefix = d.cut(2, false);
92
+ expect([...prefix]).toEqual([1, 2, 3]);
93
+
94
+ const suffix = d.cutRest(3, false);
95
+ expect([...suffix]).toEqual([4, 5]);
96
+
97
+ // in-place cut with pos<0 clears
98
+ d.cut(-1, true);
99
+ expect(d.length).toBe(0);
100
+
101
+ const d2 = new Deque<number>([1, 2, 3, 4, 5], { bucketSize: 4 });
102
+ d2.cutRest(-1, true);
103
+ expect([...d2]).toEqual([1, 2, 3, 4, 5]);
104
+ });
105
+
106
+ it('delete/deleteWhere/setEquality/unique/reverse/shrinkToFit cover branches', () => {
107
+ type Obj = { id: number };
108
+ const a: Obj = { id: 1 };
109
+ const b: Obj = { id: 1 };
110
+ const c: Obj = { id: 2 };
111
+
112
+ const d = new Deque<Obj>([a, c], { bucketSize: 4 });
113
+
114
+ // default Object.is: b not found
115
+ expect(d.delete(b)).toBe(true); // returns true even when not found? it compacts all != element
116
+ expect(d.length).toBe(2);
117
+
118
+ d.setEquality((x, y) => x.id === y.id);
119
+ expect(d.delete(b)).toBe(true);
120
+ expect([...d].map(x => x.id)).toEqual([2]);
121
+
122
+ d.push({ id: 2 });
123
+ d.push({ id: 3 });
124
+
125
+ expect(d.deleteWhere(v => v.id === 2)).toBe(true);
126
+ expect(d.deleteWhere(v => v.id === 999)).toBe(false);
127
+
128
+ // unique
129
+ const nums = new Deque<number>([1, 1, 2, 2, 2, 3], { bucketSize: 4 });
130
+ nums.unique();
131
+ expect([...nums]).toEqual([1, 2, 3]);
132
+
133
+ // unique early return
134
+ expect(new Deque<number>([1], { bucketSize: 4 }).unique().length).toBe(1);
135
+
136
+ // reverse
137
+ nums.reverse();
138
+ expect([...nums]).toEqual([3, 2, 1]);
139
+
140
+ // shrinkToFit branches
141
+ const s0 = new Deque<number>([], { bucketSize: 4 });
142
+ s0.shrinkToFit();
143
+
144
+ const s1 = new Deque<number>([1, 2, 3, 4, 5, 6, 7, 8], { bucketSize: 2 });
145
+ s1.shift();
146
+ s1.shift();
147
+ s1.pop();
148
+ s1.pop();
149
+ // now likely spans multiple buckets; just ensure no throw
150
+ s1.shrinkToFit();
151
+ expect(s1.length).toBeGreaterThan(0);
152
+ });
153
+
154
+ it('filter/mapSame/map cover thisArg and toElementFn branches', () => {
155
+ const d = new Deque<number, { v: number }>([{ v: 1 }, { v: 2 }, { v: 3 }] as any, {
156
+ bucketSize: 4,
157
+ toElementFn: r => r.v
158
+ });
159
+
160
+ const filtered = d.filter(v => v % 2 === 1);
161
+ expect([...filtered]).toEqual([1, 3]);
162
+
163
+ const ctx = { mul: 3 };
164
+ const mappedSame = d.mapSame(function (v) {
165
+ // @ts-ignore
166
+ return v * this.mul;
167
+ }, ctx);
168
+ expect([...mappedSame]).toEqual([3, 6, 9]);
169
+
170
+ const mapped = d.map(v => String(v));
171
+ expect([...mapped]).toEqual(['1', '2', '3']);
172
+ });
173
+ });
@@ -0,0 +1,39 @@
1
+ import { Deque } from '../../../../src';
2
+
3
+ describe('Deque remaining branch coverage (batch 2)', () => {
4
+ it('unshiftMany covers toElementFn branch (and is executed at all)', () => {
5
+ const d = new Deque<number, { v: number }>([], {
6
+ toElementFn: (r: { v: number }) => r.v
7
+ });
8
+
9
+ expect(d.unshiftMany([{ v: 1 }, { v: 2 }])).toEqual([true, true]);
10
+ expect(d.toArray()).toEqual([2, 1]);
11
+ });
12
+
13
+ it('splice(start) uses default deleteCount = length - start', () => {
14
+ const d = new Deque<number>();
15
+ d.pushMany([1, 2, 3, 4]);
16
+
17
+ // omit deleteCount to hit the default-arg branch
18
+ const removed = d.splice(1);
19
+
20
+ expect(removed.toArray()).toEqual([2, 3, 4]);
21
+ expect(d.toArray()).toEqual([1]);
22
+ });
23
+
24
+ it('shrinkToFit covers wrap-around bucketFirst > bucketLast branch', () => {
25
+ const d = new Deque<number>();
26
+
27
+ // Force an internal wrap-around layout (reachable-only: test-side corruption).
28
+ (d as any)._length = 1;
29
+ (d as any)._bucketFirst = 2;
30
+ (d as any)._bucketLast = 1;
31
+ (d as any)._bucketCount = 4;
32
+ (d as any)._buckets = [[0], [1], [2], [3]];
33
+
34
+ expect(() => d.shrinkToFit()).not.toThrow();
35
+ expect((d as any)._bucketFirst).toBe(0);
36
+ expect((d as any)._bucketLast).toBe(3);
37
+ expect((d as any)._buckets.length).toBe(4);
38
+ });
39
+ });
@@ -0,0 +1,9 @@
1
+ import { Deque } from '../../../../src';
2
+
3
+ describe('Deque remaining branch coverage (batch 3)', () => {
4
+ it('unshiftMany covers else-branch when toElementFn is not provided', () => {
5
+ const d = new Deque<number>();
6
+ expect(d.unshiftMany([1, 2])).toEqual([true, true]);
7
+ expect(d.toArray()).toEqual([2, 1]);
8
+ });
9
+ });
@@ -0,0 +1,95 @@
1
+ import { Deque } from '../../../../src';
2
+
3
+ describe('Deque additional branch coverage', () => {
4
+ it('unshiftMany() default-arg empty iterable returns []', () => {
5
+ const d = new Deque<number>();
6
+ expect(d.unshiftMany()).toEqual([]);
7
+ });
8
+
9
+ it('splice clamps deleteCount when negative / too large (covers both clamp branches)', () => {
10
+ const d = new Deque<number>();
11
+ d.pushMany([1, 2, 3, 4]);
12
+
13
+ // deleteCount < 0 => clamp to 0
14
+ const r0 = d.splice(1, -1, 99);
15
+ expect(r0.toArray()).toEqual([]);
16
+
17
+ // deleteCount too large => clamp to length-start
18
+ const r1 = d.splice(1, 999);
19
+ expect(r1.toArray()).toEqual([99, 2, 3, 4]);
20
+ expect(d.toArray()).toEqual([1]);
21
+ });
22
+
23
+ it('shrinkToFit returns early when bucketFirst===bucketLast (covers that return branch)', () => {
24
+ const d = new Deque<number>();
25
+ d.push(1);
26
+ // Force bucketFirst===bucketLast and length>0
27
+ (d as any)._bucketFirst = 0;
28
+ (d as any)._bucketLast = 0;
29
+ d.shrinkToFit();
30
+ expect(d.length).toBe(1);
31
+ });
32
+
33
+ it('mapSame uses the thisArg===undefined branch', () => {
34
+ const d = new Deque<number>();
35
+ d.pushMany([1, 2, 3]);
36
+ const out = d.mapSame(v => v * 2);
37
+ expect(out.toArray()).toEqual([2, 4, 6]);
38
+ });
39
+
40
+ it('map() uses thisArg branch and also covers options??{} merge path', () => {
41
+ const d = new Deque<number>();
42
+ d.pushMany([1, 2]);
43
+ const ctx = { add: 10 };
44
+
45
+ const out = d.map(
46
+ function (this: any, v: number) {
47
+ return v + this.add;
48
+ },
49
+ undefined,
50
+ ctx
51
+ );
52
+
53
+ expect(out.toArray()).toEqual([11, 12]);
54
+ });
55
+
56
+ it('_setBucketSize does not reinit buckets when length>0 (covers length===0 false branch)', () => {
57
+ const d = new Deque<number>();
58
+ d.pushMany([1, 2, 3]);
59
+ const before = (d as any)._buckets;
60
+ (d as any)._setBucketSize((d as any)._bucketSize);
61
+ expect((d as any)._buckets).toBe(before);
62
+ });
63
+
64
+ it('_getIterator yields only defined values (covers v!==undefined true branch)', () => {
65
+ const d = new Deque<number>();
66
+ d.pushMany([1, 2, 3]);
67
+ // Corrupt one slot to undefined; _getIterator should skip it.
68
+ const loc = (d as any)._getBucketAndPosition(1);
69
+ (d as any)._buckets[loc.bucketIndex][loc.indexInBucket] = undefined;
70
+
71
+ const got: number[] = [];
72
+ for (const v of d) got.push(v);
73
+ expect(got).toEqual([1, 3]);
74
+ });
75
+
76
+ it('_createLike default-arg path can be called with no args', () => {
77
+ const d = new Deque<number>();
78
+ const like = (d as any)._createLike();
79
+ expect(like.length).toBe(0);
80
+ });
81
+
82
+ it('_getReverseIterator handles v===undefined by not yielding it', () => {
83
+ const d = new Deque<number>();
84
+ d.pushMany([1, 2, 3]);
85
+
86
+ // Make last element undefined
87
+ const loc = (d as any)._getBucketAndPosition(2);
88
+ (d as any)._buckets[loc.bucketIndex][loc.indexInBucket] = undefined;
89
+
90
+ const it = (d as any)._getReverseIterator();
91
+ const got: number[] = [];
92
+ for (const v of it) got.push(v);
93
+ expect(got).toEqual([2, 1]);
94
+ });
95
+ });
@@ -0,0 +1,138 @@
1
+ import { Queue } from '../../../../src';
2
+
3
+ describe('Queue coverage', () => {
4
+ it('constructor options set autoCompactRatio and push respects maxLen via shift', () => {
5
+ const q = new Queue<number>([], { maxLen: 2, autoCompactRatio: 1 });
6
+ expect(q.autoCompactRatio).toBe(1);
7
+
8
+ q.push(1);
9
+ q.push(2);
10
+ q.push(3); // maxLen overflow triggers shift()
11
+
12
+ expect([...q]).toEqual([2, 3]);
13
+ expect(q.length).toBe(2);
14
+ expect(q.first).toBe(2);
15
+ expect(q.last).toBe(3);
16
+ });
17
+
18
+ it('pushMany uses toElementFn branch', () => {
19
+ const q = new Queue<number, { v: number }>([], { toElementFn: r => r.v });
20
+ expect(q.pushMany([{ v: 1 }, { v: 2 }])).toEqual([true, true]);
21
+ expect([...q]).toEqual([1, 2]);
22
+ });
23
+
24
+ it('shift covers empty branch and compaction trigger', () => {
25
+ const q = new Queue<number>();
26
+ expect(q.shift()).toBeUndefined();
27
+
28
+ // Force compaction quickly.
29
+ q.autoCompactRatio = 0.25;
30
+ q.pushMany([1, 2, 3, 4]);
31
+
32
+ expect(q.shift()).toBe(1);
33
+ // offset=1, elements.length=4 => 0.25, not strictly greater
34
+ expect(q.offset).toBe(1);
35
+
36
+ expect(q.shift()).toBe(2);
37
+ // offset=2, elements.length=4 => 0.5 > 0.25 => compact()
38
+ expect(q.offset).toBe(0);
39
+ expect(q.elements).toEqual([3, 4]);
40
+ });
41
+
42
+ it('delete/deleteAt/addAt/setAt cover bounds and success', () => {
43
+ const q = new Queue<number>([1, 2, 3, 4]);
44
+ // consume one to introduce offset
45
+ expect(q.shift()).toBe(1);
46
+
47
+ expect(q.delete(999)).toBe(false);
48
+ expect(q.delete(3)).toBe(true);
49
+ expect([...q]).toEqual([2, 4]);
50
+
51
+ expect(q.at(-1)).toBeUndefined();
52
+ expect(q.at(999)).toBeUndefined();
53
+ expect(q.at(0)).toBe(2);
54
+
55
+ expect(q.deleteAt(-1)).toBeUndefined();
56
+ expect(q.deleteAt(999)).toBeUndefined();
57
+ expect(q.deleteAt(0)).toBe(2);
58
+ expect([...q]).toEqual([4]);
59
+
60
+ expect(q.addAt(-1, 0)).toBe(false);
61
+ expect(q.addAt(999, 0)).toBe(false);
62
+ expect(q.addAt(0, 3)).toBe(true);
63
+ expect([...q]).toEqual([3, 4]);
64
+
65
+ expect(q.setAt(-1, 0)).toBe(false);
66
+ expect(q.setAt(999, 0)).toBe(false);
67
+ expect(q.setAt(1, 40)).toBe(true);
68
+ expect([...q]).toEqual([3, 40]);
69
+ });
70
+
71
+ it('reverse/clear/compact basic behaviors', () => {
72
+ const q = new Queue<number>([1, 2, 3]);
73
+ q.shift();
74
+ expect(q.offset).toBe(1);
75
+
76
+ q.reverse();
77
+ expect(q.offset).toBe(0);
78
+ expect([...q]).toEqual([3, 2]);
79
+
80
+ q.clear();
81
+ expect(q.length).toBe(0);
82
+ expect(q.offset).toBe(0);
83
+
84
+ q.pushMany([1, 2]);
85
+ q.shift();
86
+ expect(q.compact()).toBe(true);
87
+ expect(q.offset).toBe(0);
88
+ });
89
+
90
+ it('splice triggers optional compaction and returns removed queue with copied ratio', () => {
91
+ const q = new Queue<number>([1, 2, 3, 4, 5], { autoCompactRatio: 0.2 });
92
+ q.shift();
93
+ q.shift(); // offset=2, len=5 => 0.4 > 0.2 would compact on next splice
94
+
95
+ const removed = q.splice(1, 2, 9, 8);
96
+ expect([...removed]).toEqual([4, 5]);
97
+ expect(removed.autoCompactRatio).toBe(q.autoCompactRatio);
98
+
99
+ expect([...q]).toEqual([3, 9, 8]);
100
+ expect(q.offset).toBe(0);
101
+ });
102
+
103
+ it('map/mapSame cover thisArg and default branches, and _createLike default elements branch', () => {
104
+ const q = new Queue<number>([1, 2, 3], { autoCompactRatio: 0.9 });
105
+
106
+ const mapped1 = q.map(v => v + 1);
107
+ expect([...mapped1]).toEqual([2, 3, 4]);
108
+
109
+ const ctx = { mul: 2 };
110
+ const mapped2 = q.map(function (v) {
111
+ // @ts-ignore
112
+ return v * this.mul;
113
+ }, undefined, ctx);
114
+ expect([...mapped2]).toEqual([2, 4, 6]);
115
+
116
+ const same1 = q.mapSame(v => v * 10);
117
+ expect([...same1]).toEqual([10, 20, 30]);
118
+
119
+ const same2 = q.mapSame(function (v) {
120
+ // @ts-ignore
121
+ return v + this.inc;
122
+ }, { inc: 5 });
123
+ expect([...same2]).toEqual([6, 7, 8]);
124
+
125
+ const like = (q as any)._createLike();
126
+ expect(like.length).toBe(0);
127
+ });
128
+
129
+ it('_getReverseIterator skips undefined items', () => {
130
+ const q = new Queue<number | undefined>([1, undefined, 2]);
131
+ expect([...q.toReversedArray()]).toEqual([2, undefined, 1]);
132
+
133
+ const rev: (number | undefined)[] = [];
134
+ for (const v of (q as any)._getReverseIterator()) rev.push(v);
135
+ // undefined is skipped by implementation
136
+ expect(rev).toEqual([2, 1]);
137
+ });
138
+ });
@@ -0,0 +1,27 @@
1
+ import { Queue } from '../../../../src';
2
+
3
+ describe('Queue remaining branch coverage (batch 2)', () => {
4
+ it('splice(start) hits default deleteCount=0 and can trigger auto-compaction branch', () => {
5
+ const q = new Queue<number>();
6
+ q.pushMany([1, 2, 3]);
7
+
8
+ // Prevent auto-compaction during the shifts; we want a non-zero offset.
9
+ q.autoCompactRatio = 1;
10
+
11
+ // Create offset > 0 while keeping underlying elements array non-empty.
12
+ expect(q.shift()).toBe(1);
13
+ expect(q.shift()).toBe(2);
14
+ expect(q.offset).toBe(2);
15
+
16
+ // Now ensure the condition `offset/elements.length > autoCompactRatio` is true at splice-time.
17
+ q.autoCompactRatio = 0;
18
+
19
+ // Omit deleteCount to hit the default-arg branch.
20
+ const removed = q.splice(0, undefined as any, 9);
21
+
22
+ // Should have compacted (offset reset) and inserted item.
23
+ expect(q.offset).toBe(0);
24
+ expect(q.toArray()).toEqual([9, 3]);
25
+ expect(removed.toArray()).toEqual([]);
26
+ });
27
+ });
@@ -0,0 +1,112 @@
1
+ import { Stack } from '../../../../src';
2
+
3
+ describe('Stack coverage', () => {
4
+ it('fromArray + basic ops cover isEmpty/peek/pop on empty', () => {
5
+ // constructor default params branch
6
+ const empty = new Stack<number>();
7
+ expect(empty.size).toBe(0);
8
+
9
+ const s = Stack.fromArray([1, 2, 3]);
10
+ expect([...s]).toEqual([1, 2, 3]);
11
+
12
+ expect(s.peek()).toBe(3);
13
+ expect(s.pop()).toBe(3);
14
+ expect(s.pop()).toBe(2);
15
+ expect(s.pop()).toBe(1);
16
+
17
+ expect(s.isEmpty()).toBe(true);
18
+ expect(s.peek()).toBeUndefined();
19
+ expect(s.pop()).toBeUndefined();
20
+ });
21
+
22
+ it('pushMany uses toElementFn conversion branch', () => {
23
+ const s = new Stack<number, { v: number }>([], { toElementFn: r => r.v });
24
+ const res = s.pushMany([{ v: 1 }, { v: 2 }]);
25
+ expect(res).toEqual([true, true]);
26
+ expect([...s]).toEqual([1, 2]);
27
+ });
28
+
29
+ it('delete/deleteAt cover not-found and bounds', () => {
30
+ const s = new Stack<number>([1, 2, 3, 2]);
31
+
32
+ // not found => _indexOfByEquals returns -1 => deleteAt(-1) false
33
+ expect(s.delete(999)).toBe(false);
34
+
35
+ // bounds
36
+ expect(s.deleteAt(-1)).toBe(false);
37
+ expect(s.deleteAt(999)).toBe(false);
38
+
39
+ // delete first matching occurrence (bottom-up)
40
+ expect(s.delete(2)).toBe(true);
41
+ expect([...s]).toEqual([1, 3, 2]);
42
+
43
+ // deleteAt valid
44
+ expect(s.deleteAt(1)).toBe(true);
45
+ expect([...s]).toEqual([1, 2]);
46
+ });
47
+
48
+ it('deleteWhere covers both match and no-match branches', () => {
49
+ const s = new Stack<number>([1, 2, 3]);
50
+ expect(s.deleteWhere(v => v === 2)).toBe(true);
51
+ expect([...s]).toEqual([1, 3]);
52
+
53
+ expect(s.deleteWhere(v => v === 999)).toBe(false);
54
+ expect([...s]).toEqual([1, 3]);
55
+ });
56
+
57
+ it('clear/clone/filter/mapSame/map cover instance factories and thisArg call path', () => {
58
+ const raw = [{ v: 1 }, { v: 2 }, { v: 3 }];
59
+ const s = new Stack<number, { v: number }>(raw, { toElementFn: r => r.v });
60
+
61
+ const cloned = s.clone();
62
+ expect([...cloned]).toEqual([1, 2, 3]);
63
+
64
+ const filtered = s.filter(v => v % 2 === 1);
65
+ expect([...filtered]).toEqual([1, 3]);
66
+
67
+ const mappedSame = s.mapSame(v => v * 2);
68
+ expect([...mappedSame]).toEqual([2, 4, 6]);
69
+
70
+ // mapSame with thisArg branch
71
+ const ctx2 = { mul: 3 };
72
+ const mappedSame2 = s.mapSame(function (v) {
73
+ // @ts-ignore
74
+ return v * this.mul;
75
+ }, ctx2);
76
+ expect([...mappedSame2]).toEqual([3, 6, 9]);
77
+
78
+
79
+ // map with thisArg branch
80
+ const ctx = { inc: 10 };
81
+ const mapped = s.map(function (v) {
82
+ // @ts-ignore
83
+ return v + this.inc;
84
+ }, undefined, ctx);
85
+ expect([...mapped]).toEqual([11, 12, 13]);
86
+
87
+ // map with undefined thisArg branch
88
+ const mapped2 = s.map(v => v + 1);
89
+ expect([...mapped2]).toEqual([2, 3, 4]);
90
+
91
+ // _createLike default elements branch (protected)
92
+ const like = (s as any)._createLike();
93
+ expect(like.size).toBe(0);
94
+
95
+ s.clear();
96
+ expect(s.size).toBe(0);
97
+ });
98
+
99
+ it('setEquality affects delete/search semantics', () => {
100
+ type Obj = { id: number };
101
+ const a = { id: 1 };
102
+ const b = { id: 2 };
103
+ const s = new Stack<Obj>([a, b]);
104
+
105
+ // default Object.is: new object not found
106
+ expect(s.delete({ id: 1 } as any)).toBe(false);
107
+
108
+ s.setEquality((x, y) => x.id === y.id);
109
+ expect(s.delete({ id: 1 } as any)).toBe(true);
110
+ expect([...s].map(x => x.id)).toEqual([2]);
111
+ });
112
+ });
@@ -0,0 +1,9 @@
1
+ import { TreeNode } from '../../../../src';
2
+
3
+ describe('TreeNode remaining branch coverage', () => {
4
+ it('constructor assigns children when provided (covers if(children) branch)', () => {
5
+ const child = new TreeNode('c');
6
+ const root = new TreeNode('r', undefined, [child]);
7
+ expect(root.children).toEqual([child]);
8
+ });
9
+ });