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,72 @@
1
+ import { DoublyLinkedList } from '../../../../src';
2
+
3
+ /**
4
+ * Coverage-focused tests for LinearBase helpers (via DoublyLinkedList).
5
+ * Keep existing @example tests intact.
6
+ */
7
+ describe('LinearBase coverage (via DoublyLinkedList)', () => {
8
+ it('indexOf/lastIndexOf handle fromIndex bounds and negatives', () => {
9
+ const list = new DoublyLinkedList<number | undefined>();
10
+ list.pushMany([1, 2, 3, 2, 1]);
11
+
12
+ expect(list.indexOf(2)).toBe(1);
13
+ expect(list.indexOf(2, 2)).toBe(3);
14
+
15
+ // negative fromIndex clamps to 0
16
+ expect(list.indexOf(1, -999)).toBe(0);
17
+
18
+ expect(list.lastIndexOf(2)).toBe(3);
19
+ // fromIndex >= length clamps to length-1
20
+ expect(list.lastIndexOf(1, 999)).toBe(4);
21
+ // negative fromIndex path (current implementation returns -1 for -1 specifically)
22
+ // (We mainly want to exercise the branch; behavior is asserted as-is.)
23
+ expect(list.lastIndexOf(2, -1)).toBe(-1);
24
+ });
25
+
26
+ it('findIndex skips undefined elements', () => {
27
+ const list = new DoublyLinkedList<number | undefined>();
28
+ list.pushMany([undefined, 1, undefined, 2]);
29
+
30
+ const spy = jest.fn((x: number) => x === 2);
31
+ expect(list.findIndex(spy as any)).toBe(3);
32
+
33
+ // predicate should only be called for defined elements
34
+ expect(spy).toHaveBeenCalledTimes(2);
35
+ });
36
+
37
+ it('slice/splice cover defaults and head-insert path', () => {
38
+ const list = new DoublyLinkedList<number>();
39
+ list.pushMany([1, 2, 3, 4]);
40
+
41
+ // slice defaults
42
+ expect(list.slice().toArray()).toEqual([1, 2, 3, 4]);
43
+ expect(list.slice(1, -1).toArray()).toEqual([2, 3]);
44
+
45
+ // splice: insert at head (previousNode undefined)
46
+ const removed0 = list.splice(0, 0, 9, 8);
47
+ expect(removed0.toArray()).toEqual([]);
48
+ expect(list.toArray()).toEqual([9, 8, 1, 2, 3, 4]);
49
+
50
+ // splice: delete + insert in middle
51
+ const removed = list.splice(2, 2, 7);
52
+ expect(removed.toArray()).toEqual([1, 2]);
53
+ expect(list.toArray()).toEqual([9, 8, 7, 3, 4]);
54
+
55
+ // splice: negative start
56
+ const removed2 = list.splice(-1, 1);
57
+ expect(removed2.toArray()).toEqual([4]);
58
+ expect(list.toArray()).toEqual([9, 8, 7, 3]);
59
+ });
60
+
61
+ it('reduceRight covers initialValue defaulting', () => {
62
+ const list = new DoublyLinkedList<number>();
63
+ list.pushMany([1, 2, 3]);
64
+
65
+ // no initialValue => accumulator defaults (0 as U)
66
+ const sum = list.reduceRight((acc: number, x: number) => acc + x);
67
+ expect(sum).toBe(6);
68
+
69
+ const sum2 = list.reduceRight((acc: number, x: number) => acc + x, 10);
70
+ expect(sum2).toBe(16);
71
+ });
72
+ });
@@ -0,0 +1,417 @@
1
+ import { LinearBase, LinearLinkedBase, LinkedListNode, } from '../../../../src/data-structures/base/linear-base';
2
+ import {
3
+ DoublyLinkedListNode,
4
+ DoublyLinkedListOptions,
5
+ ElementCallback,
6
+ IterableElementBase,
7
+ IterableElementBaseOptions
8
+ } from '../../../../src';
9
+
10
+ class ArrayLinear extends LinearBase<number, any> {
11
+ private _arr: number[] = [];
12
+
13
+ get length(): number {
14
+ return this._arr.length;
15
+ }
16
+
17
+ override clone(): this {
18
+ const out = this._createInstance();
19
+ for (const v of this._arr) out.push(v);
20
+ return out;
21
+ }
22
+
23
+ reverse(): this {
24
+ this._arr.reverse();
25
+ return this;
26
+ }
27
+
28
+ push(elementOrNode: number | LinkedListNode<number>): boolean {
29
+ const v = elementOrNode instanceof LinkedListNode ? elementOrNode.value : elementOrNode;
30
+ this._arr.push(v);
31
+ return true;
32
+ }
33
+
34
+ pushMany(elements: Iterable<number> | Iterable<any> | Iterable<LinkedListNode<number>>): boolean[] {
35
+ const ans: boolean[] = [];
36
+ for (const el of elements as any) ans.push(this.push(el));
37
+ return ans;
38
+ }
39
+
40
+ delete(elementOrNode: number | LinkedListNode<number> | undefined): boolean {
41
+ if (elementOrNode === undefined) return false;
42
+ const v = elementOrNode instanceof LinkedListNode ? elementOrNode.value : elementOrNode;
43
+ const i = this._arr.indexOf(v);
44
+ if (i < 0) return false;
45
+ this._arr.splice(i, 1);
46
+ return true;
47
+ }
48
+
49
+ at(index: number): number | undefined {
50
+ return this._arr[index];
51
+ }
52
+
53
+ deleteAt(pos: number): number | undefined {
54
+ if (pos < 0 || pos >= this._arr.length) return undefined;
55
+ return this._arr.splice(pos, 1)[0];
56
+ }
57
+
58
+ addAt(index: number, newElementOrNode: number | LinkedListNode<number>): boolean {
59
+ const v = newElementOrNode instanceof LinkedListNode ? newElementOrNode.value : newElementOrNode;
60
+ this._arr.splice(index, 0, v);
61
+ return true;
62
+ }
63
+
64
+ setAt(index: number, value: number): boolean {
65
+ if (index < 0 || index >= this._arr.length) return false;
66
+ this._arr[index] = value;
67
+ return true;
68
+ }
69
+
70
+ clear(): void {
71
+ this._arr = [];
72
+ }
73
+
74
+ protected _createInstance(): this {
75
+ return new (this.constructor as any)();
76
+ }
77
+
78
+ protected *_getIterator(): IterableIterator<number> {
79
+ yield* this._arr;
80
+ }
81
+
82
+ protected *_getReverseIterator(): IterableIterator<number> {
83
+ for (let i = this._arr.length - 1; i >= 0; i--) yield this._arr[i];
84
+ }
85
+
86
+ isEmpty(): boolean {
87
+ return false;
88
+ }
89
+
90
+ filter(predicate: ElementCallback<number, any, boolean>, thisArg?: any): this {
91
+ const out = this._createInstance();
92
+
93
+ return out;
94
+ }
95
+
96
+ // @ts-ignore
97
+ map(callback: ElementCallback<number, any, number>, options: IterableElementBaseOptions<number, any> | undefined, thisArg: unknown | undefined): ArrayLinear {
98
+ const out = this._createLike([], { ...(options ?? {}) });
99
+ return out;
100
+ }
101
+
102
+ mapSame(callback: ElementCallback<number, any, number>, thisArg: unknown | undefined): this {
103
+ const out = this._createInstance();
104
+
105
+ return out;
106
+ }
107
+
108
+ protected _createLike(
109
+ elements: Iterable<number> | Iterable<any> = [],
110
+ options?: IterableElementBaseOptions<number, any>
111
+ ): ArrayLinear {
112
+ const Ctor = this.constructor as new (
113
+ elements?: Iterable<number> | Iterable<any> ,
114
+ options?: IterableElementBaseOptions<number, any>
115
+ ) => ArrayLinear;
116
+ return new Ctor(elements, options);
117
+ }
118
+ }
119
+
120
+ class NodeLinear extends LinearLinkedBase<number, any, LinkedListNode<number>> {
121
+ private _head: LinkedListNode<number> | undefined;
122
+ private _tail: LinkedListNode<number> | undefined;
123
+ private _len = 0;
124
+
125
+ get length(): number {
126
+ return this._len;
127
+ }
128
+
129
+ override clone(): this {
130
+ const out = this._createInstance();
131
+ for (const v of this) out.push(v);
132
+ return out;
133
+ }
134
+
135
+ reverse(): this {
136
+ // simple rebuild
137
+ const arr = [...this].reverse();
138
+ this.clear();
139
+ for (const v of arr) this.push(v);
140
+ return this;
141
+ }
142
+
143
+ push(elementOrNode: number | LinkedListNode<number>): boolean {
144
+ const n = elementOrNode instanceof LinkedListNode ? elementOrNode : new LinkedListNode(elementOrNode);
145
+ n.next = undefined;
146
+ if (!this._head) {
147
+ this._head = this._tail = n;
148
+ } else {
149
+ (this._tail as any).next = n;
150
+ this._tail = n;
151
+ }
152
+ this._len++;
153
+ return true;
154
+ }
155
+
156
+ pushMany(elements: Iterable<number> | Iterable<any> | Iterable<LinkedListNode<number>>): boolean[] {
157
+ const ans: boolean[] = [];
158
+ for (const el of elements as any) ans.push(this.push(el));
159
+ return ans;
160
+ }
161
+
162
+ delete(elementOrNode: number | LinkedListNode<number> | undefined): boolean {
163
+ if (elementOrNode === undefined) return false;
164
+ const target = elementOrNode instanceof LinkedListNode ? elementOrNode : undefined;
165
+ const value = elementOrNode instanceof LinkedListNode ? elementOrNode.value : elementOrNode;
166
+
167
+ let prev: LinkedListNode<number> | undefined;
168
+ let cur = this._head;
169
+ while (cur) {
170
+ const match = target ? cur === target : cur.value === value;
171
+ if (match) {
172
+ if (!prev) {
173
+ this._head = cur.next;
174
+ if (this._tail === cur) this._tail = this._head;
175
+ } else {
176
+ prev.next = cur.next;
177
+ if (this._tail === cur) this._tail = prev;
178
+ }
179
+ this._len--;
180
+ return true;
181
+ }
182
+ prev = cur;
183
+ cur = cur.next;
184
+ }
185
+ return false;
186
+ }
187
+
188
+ at(index: number): number | undefined {
189
+ return this.getNodeAt(index)?.value;
190
+ }
191
+
192
+ deleteAt(pos: number): number | undefined {
193
+ const n = this.getNodeAt(pos);
194
+ if (!n) return undefined;
195
+ const v = n.value;
196
+ this.delete(n);
197
+ return v;
198
+ }
199
+
200
+ addAt(index: number, newElementOrNode: number | LinkedListNode<number>): boolean {
201
+ const node = newElementOrNode instanceof LinkedListNode ? newElementOrNode : new LinkedListNode(newElementOrNode);
202
+ if (index <= 0 || !this._head) {
203
+ node.next = this._head;
204
+ this._head = node;
205
+ if (!this._tail) this._tail = node;
206
+ this._len++;
207
+ return true;
208
+ }
209
+ const prev = this.getNodeAt(index - 1);
210
+ if (!prev) return false;
211
+ node.next = prev.next;
212
+ prev.next = node;
213
+ if (this._tail === prev) this._tail = node;
214
+ this._len++;
215
+ return true;
216
+ }
217
+
218
+ setAt(index: number, value: number): boolean {
219
+ const n = this.getNodeAt(index);
220
+ if (!n) return false;
221
+ n.value = value;
222
+ return true;
223
+ }
224
+ protected _ensurePredicate(
225
+ elementNodeOrPredicate: number | LinkedListNode<number> | ((node: LinkedListNode<number>) => boolean)
226
+ ): (node: LinkedListNode<number>) => boolean {
227
+ if (elementNodeOrPredicate instanceof LinkedListNode) {
228
+ const target = elementNodeOrPredicate;
229
+ return (node: LinkedListNode<number>) => node === target;
230
+ }
231
+ if (typeof elementNodeOrPredicate === 'function') {
232
+ return elementNodeOrPredicate as (node: LinkedListNode<number>) => boolean;
233
+ }
234
+ const value = elementNodeOrPredicate as number;
235
+ return (node: LinkedListNode<number>) => node.value === value;
236
+ }
237
+
238
+ getNode(
239
+ elementNodeOrPredicate: number | LinkedListNode<number> | ((node: LinkedListNode<number>) => boolean) | undefined
240
+ ): LinkedListNode<number> | undefined {
241
+ if (elementNodeOrPredicate === undefined) return;
242
+
243
+ if ( elementNodeOrPredicate instanceof LinkedListNode) {
244
+ const target = elementNodeOrPredicate;
245
+
246
+ let cur = this._head;
247
+ while (cur) {
248
+ if (cur === target) return target;
249
+ cur = cur.next;
250
+ }
251
+
252
+ const isMatch = (node: LinkedListNode<number>) => node.value === target.value;
253
+ cur = this._head;
254
+ while (cur) {
255
+ if (isMatch(cur)) return cur;
256
+ cur = cur.next;
257
+ }
258
+ return undefined;
259
+ }
260
+
261
+ const predicate = this._ensurePredicate(elementNodeOrPredicate);
262
+ let current = this._head;
263
+ while (current) {
264
+ if (predicate(current)) return current;
265
+ current = current.next;
266
+ }
267
+ return undefined;
268
+ }
269
+
270
+ addBefore(existing: number | LinkedListNode<number>, neu: number | LinkedListNode<number>): boolean {
271
+ const node = this.getNode(existing);
272
+ if (!node) return false;
273
+ const prev = this._getPrevNode(node);
274
+ const nn = neu instanceof LinkedListNode ? neu : new LinkedListNode(neu);
275
+ if (!prev) {
276
+ nn.next = this._head;
277
+ this._head = nn;
278
+ if (!this._tail) this._tail = nn;
279
+ } else {
280
+ prev.next = nn;
281
+ nn.next = node;
282
+ }
283
+ this._len++;
284
+ return true;
285
+ }
286
+
287
+ addAfter(existing: number | LinkedListNode<number>, neu: number | LinkedListNode<number>): boolean {
288
+ const node = this.getNode(existing);
289
+ if (!node) return false;
290
+ const nn = neu instanceof LinkedListNode ? neu : new LinkedListNode(neu);
291
+ nn.next = node.next;
292
+ node.next = nn;
293
+ if (this._tail === node) this._tail = nn;
294
+ this._len++;
295
+ return true;
296
+ }
297
+
298
+ getNodeAt(index: number): LinkedListNode<number> | undefined {
299
+ if (index < 0 || index >= this._len) return undefined;
300
+ let cur = this._head;
301
+ let i = 0;
302
+ while (cur && i < index) {
303
+ cur = cur.next;
304
+ i++;
305
+ }
306
+ return cur;
307
+ }
308
+
309
+ clear(): void {
310
+ this._head = this._tail = undefined;
311
+ this._len = 0;
312
+ }
313
+
314
+ protected _createInstance(): this {
315
+ return new (this.constructor as any)();
316
+ }
317
+
318
+ protected *_getIterator(): IterableIterator<number> {
319
+ let cur = this._head;
320
+ while (cur) {
321
+ yield cur.value;
322
+ cur = cur.next;
323
+ }
324
+ }
325
+
326
+ protected *_getReverseIterator(): IterableIterator<number> {
327
+ const arr = [...this].reverse();
328
+ for (const v of arr) yield v;
329
+ }
330
+
331
+ protected *_getNodeIterator(): IterableIterator<LinkedListNode<number>> {
332
+ let cur = this._head;
333
+ while (cur) {
334
+ yield cur;
335
+ cur = cur.next;
336
+ }
337
+ }
338
+
339
+ protected _getPrevNode(node: LinkedListNode<number>): LinkedListNode<number> | undefined {
340
+ if (!this._head || this._head === node) return undefined;
341
+ let cur = this._head;
342
+ while (cur.next && cur.next !== node) cur = cur.next;
343
+ return cur.next === node ? cur : undefined;
344
+ }
345
+
346
+ isEmpty(): boolean {
347
+ return false;
348
+ }
349
+
350
+
351
+
352
+ filter(predicate: ElementCallback<number, any, boolean>, thisArg?: any): this {
353
+ const out = this._createInstance();
354
+
355
+ return out;
356
+ }
357
+
358
+ // @ts-ignore
359
+ map(callback: ElementCallback<number, any, number>, options: IterableElementBaseOptions<number, any> | undefined, thisArg: unknown | undefined): ArrayLinear {
360
+ const out = this._createLike([], { ...(options ?? {}) });
361
+ return out;
362
+ }
363
+
364
+ mapSame(callback: ElementCallback<number, any, number>, thisArg: unknown | undefined): this {
365
+ const out = this._createInstance();
366
+
367
+ return out;
368
+ }
369
+
370
+ protected _createLike(
371
+ elements: Iterable<number> | Iterable<any> = [],
372
+ options?: IterableElementBaseOptions<number, any>
373
+ ): ArrayLinear {
374
+ const Ctor = this.constructor as new (
375
+ elements?: Iterable<number> | Iterable<any> ,
376
+ options?: IterableElementBaseOptions<number, any>
377
+ ) => ArrayLinear;
378
+ return new Ctor(elements, options);
379
+ }
380
+ }
381
+
382
+ describe('LinearBase additional branch coverage', () => {
383
+ it('splice() covers default deleteCount and start<0 false arm; reduceRight covers initialValue ?? fallback', () => {
384
+ const l = new ArrayLinear();
385
+ l.pushMany([1, 2, 3]);
386
+
387
+ // default deleteCount=0 + start>=0 (false arm of start<0 ? ...)
388
+ const removed = l.splice(1);
389
+ expect([...removed]).toEqual([]);
390
+
391
+ // reduceRight: initialValue undefined => uses 0; and defined path
392
+ const sum0 = (l as any).reduceRight((acc: number, v: number) => acc + v, undefined);
393
+ expect(sum0).toBe(6);
394
+ const sum10 = l.reduceRight((acc, v) => acc + v, 10);
395
+ expect(sum10).toBe(16);
396
+ });
397
+
398
+ it('slice() covers default args start=0,end=length; concat covers non-LinearBase else arm', () => {
399
+ const l = new ArrayLinear();
400
+ l.pushMany([1, 2, 3]);
401
+
402
+ expect([...l.slice()]).toEqual([1, 2, 3]);
403
+
404
+ const c = l.concat(4 as any);
405
+ expect([...c]).toEqual([1, 2, 3, 4]);
406
+ });
407
+
408
+ it('LinearLinkedBase slice uses negative start arm; splice uses default deleteCount', () => {
409
+ const l = new NodeLinear();
410
+ l.pushMany([1, 2, 3, 4]);
411
+
412
+ expect([...l.slice(-2)]).toEqual([3, 4]);
413
+
414
+ const removed = l.splice(2);
415
+ expect([...removed]).toEqual([]);
416
+ });
417
+ });
@@ -0,0 +1,146 @@
1
+ import { AVLTreeCounter } from '../../../../src';
2
+
3
+ describe('AVLTreeCounter remaining reachable branch coverage (batch 3)', () => {
4
+ it('perfectlyBalance returns false for empty tree (n===0 branch)', () => {
5
+ const t = new AVLTreeCounter<number, number>();
6
+ expect(t.perfectlyBalance()).toBe(false);
7
+ });
8
+
9
+ it('clone covers non-mapMode branch (bfs sets values)', () => {
10
+ const t = new AVLTreeCounter<number, string>([], { isMapMode: false });
11
+ t.set(1, 'a', 3);
12
+
13
+ const c = t.clone();
14
+ expect(c.get(1)).toBe('a');
15
+ expect((c as any).getNode(1).count).toBe(3);
16
+ });
17
+
18
+ it('_createLike hits default iter=[] parameter', () => {
19
+ const t = new AVLTreeCounter<number, number>();
20
+ const like = (t as any)._createLike();
21
+ expect(like).toBeInstanceOf(AVLTreeCounter);
22
+ expect(like.size).toBe(0);
23
+ });
24
+
25
+ it('_keyValueNodeOrEntryToNodeAndValue entry with undefined key returns [undefined, undefined]', () => {
26
+ const t = new AVLTreeCounter<number, number>();
27
+ const out = (t as any)._keyValueNodeOrEntryToNodeAndValue([undefined, 123]);
28
+ expect(out).toEqual([undefined, undefined]);
29
+ });
30
+
31
+ it('_swapProperties covers mapMode branches where value assignments are skipped', () => {
32
+ const t = new AVLTreeCounter<number, string>([], { isMapMode: true });
33
+
34
+ const n1 = t.createNode(1, 's', 1) as any;
35
+ const n2 = t.createNode(2, 'd', 2) as any;
36
+
37
+ // Ensure values are present so we can assert they were NOT reassigned.
38
+ n1.value = 's';
39
+ n2.value = 'd';
40
+ n1.height = 10;
41
+ n2.height = 20;
42
+
43
+ const swapped = (t as any)._swapProperties(n1, n2);
44
+ expect(swapped).toBe(n2);
45
+
46
+ // keys/counts/heights swap...
47
+ expect(n2.key).toBe(1);
48
+ expect(n2.count).toBe(1);
49
+ expect(n2.height).toBe(10);
50
+
51
+ expect(n1.key).toBe(2);
52
+ expect(n1.count).toBe(2);
53
+ expect(n1.height).toBe(20);
54
+
55
+ // ...but values should be untouched in map mode.
56
+ expect(n1.value).toBe('s');
57
+ expect(n2.value).toBe('d');
58
+ });
59
+
60
+ it('_swapProperties covers non-mapMode branches where value assignments occur', () => {
61
+ const t = new AVLTreeCounter<number, string>([], { isMapMode: false });
62
+
63
+ const n1 = t.createNode(1, 's', 1) as any;
64
+ const n2 = t.createNode(2, 'd', 2) as any;
65
+ n1.height = 10;
66
+ n2.height = 20;
67
+
68
+ const swapped = (t as any)._swapProperties(n1, n2);
69
+ expect(swapped).toBe(n2);
70
+
71
+ expect(n2.key).toBe(1);
72
+ expect(n2.value).toBe('s');
73
+ expect(n2.count).toBe(1);
74
+
75
+ expect(n1.key).toBe(2);
76
+ expect(n1.value).toBe('d');
77
+ expect(n1.count).toBe(2);
78
+ });
79
+
80
+ it('delete() hits `curr.left ? getRightMost(...) : undefined` false-arm via left getter side-effect', () => {
81
+ const t = new AVLTreeCounter<number, number>();
82
+ t.setMany([
83
+ [2, 2],
84
+ [1, 1],
85
+ [3, 3]
86
+ ]);
87
+
88
+ const node2 = (t as any).getNode(2);
89
+ const realLeft = node2.left;
90
+
91
+ let reads = 0;
92
+ Object.defineProperty(node2, 'left', {
93
+ configurable: true,
94
+ get() {
95
+ reads++;
96
+ // First read (in `if (!curr.left)`) must be truthy to reach the else-branch.
97
+ if (reads === 1) return realLeft;
98
+ // Second read (in ternary) returns undefined to hit the false-arm.
99
+ return undefined;
100
+ }
101
+ });
102
+
103
+ try {
104
+ expect(() => t.delete(2)).not.toThrow();
105
+ } finally {
106
+ // Restore a normal data property to avoid polluting later tests.
107
+ Object.defineProperty(node2, 'left', {
108
+ configurable: true,
109
+ writable: true,
110
+ value: realLeft
111
+ });
112
+ }
113
+ });
114
+
115
+ it('perfectlyBalance hits `nd ? nd.count : 0` false-arm via proxy iterator yielding undefined', () => {
116
+ const t = new AVLTreeCounter<number, number>();
117
+ t.setMany([
118
+ [2, 2],
119
+ [1, 1],
120
+ [3, 3]
121
+ ]);
122
+
123
+ const origDfs = (t as any).dfs;
124
+ (t as any).dfs = (...args: any[]) => {
125
+ const nodes: any[] = origDfs.apply(t, args);
126
+ // Proxy: keep indexing intact, but iteration yields an initial undefined.
127
+ return new Proxy(nodes, {
128
+ get(target, prop, receiver) {
129
+ if (prop === Symbol.iterator) {
130
+ return function* () {
131
+ yield undefined;
132
+ yield* target;
133
+ };
134
+ }
135
+ return Reflect.get(target, prop, receiver);
136
+ }
137
+ });
138
+ };
139
+
140
+ try {
141
+ expect(t.perfectlyBalance()).toBe(true);
142
+ } finally {
143
+ (t as any).dfs = origDfs;
144
+ }
145
+ });
146
+ });