data-structure-typed 2.2.8 → 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 (137) hide show
  1. package/.github/workflows/ci.yml +9 -0
  2. package/CHANGELOG.md +1 -1
  3. package/README.md +1 -1
  4. package/README_CN.md +1 -1
  5. package/dist/cjs/index.cjs +584 -76
  6. package/dist/cjs/index.cjs.map +1 -1
  7. package/dist/cjs-legacy/index.cjs +588 -79
  8. package/dist/cjs-legacy/index.cjs.map +1 -1
  9. package/dist/esm/index.mjs +584 -76
  10. package/dist/esm/index.mjs.map +1 -1
  11. package/dist/esm-legacy/index.mjs +588 -79
  12. package/dist/esm-legacy/index.mjs.map +1 -1
  13. package/dist/types/data-structures/base/linear-base.d.ts +6 -6
  14. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +3 -4
  15. package/dist/types/data-structures/binary-tree/bst.d.ts +2 -1
  16. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +150 -20
  17. package/dist/types/data-structures/binary-tree/tree-counter.d.ts +3 -3
  18. package/dist/types/interfaces/binary-tree.d.ts +1 -1
  19. package/dist/umd/data-structure-typed.js +588 -79
  20. package/dist/umd/data-structure-typed.js.map +1 -1
  21. package/dist/umd/data-structure-typed.min.js +3 -3
  22. package/dist/umd/data-structure-typed.min.js.map +1 -1
  23. package/package.json +4 -3
  24. package/src/data-structures/base/linear-base.ts +2 -12
  25. package/src/data-structures/binary-tree/binary-tree.ts +5 -6
  26. package/src/data-structures/binary-tree/bst.ts +79 -4
  27. package/src/data-structures/binary-tree/red-black-tree.ts +583 -73
  28. package/src/data-structures/binary-tree/tree-counter.ts +21 -9
  29. package/src/data-structures/queue/deque.ts +10 -0
  30. package/src/interfaces/binary-tree.ts +1 -1
  31. package/test/unit/data-structures/base/iterable-element-base.coverage.test.ts +106 -0
  32. package/test/unit/data-structures/base/iterable-element-base.more-branches.coverage.test.ts +61 -0
  33. package/test/unit/data-structures/base/linear-base.array.coverage.test.ts +168 -0
  34. package/test/unit/data-structures/base/linear-base.concat-else.coverage.test.ts +82 -0
  35. package/test/unit/data-structures/base/linear-base.coverage.test.ts +72 -0
  36. package/test/unit/data-structures/base/linear-base.more-branches.coverage.test.ts +417 -0
  37. package/test/unit/data-structures/binary-tree/avl-tree-counter.more-branches-3.coverage.test.ts +146 -0
  38. package/test/unit/data-structures/binary-tree/avl-tree-counter.more-branches.coverage.test.ts +93 -0
  39. package/test/unit/data-structures/binary-tree/avl-tree-multi-map.coverage.test.ts +108 -0
  40. package/test/unit/data-structures/binary-tree/avl-tree-multi-map.more-branches-2.coverage.test.ts +85 -0
  41. package/test/unit/data-structures/binary-tree/avl-tree-node.familyPosition-root-left.coverage.test.ts +17 -0
  42. package/test/unit/data-structures/binary-tree/avl-tree.more-branches-2.coverage.test.ts +99 -0
  43. package/test/unit/data-structures/binary-tree/binary-indexed-tree.more-branches.coverage.test.ts +18 -0
  44. package/test/unit/data-structures/binary-tree/binary-tree.more-branches.coverage.test.ts +56 -0
  45. package/test/unit/data-structures/binary-tree/binary-tree.remaining-branches.coverage.test.ts +229 -0
  46. package/test/unit/data-structures/binary-tree/bst.bound-by-predicate.coverage.test.ts +33 -0
  47. package/test/unit/data-structures/binary-tree/bst.coverage.test.ts +94 -0
  48. package/test/unit/data-structures/binary-tree/bst.deletebykey.coverage.test.ts +70 -0
  49. package/test/unit/data-structures/binary-tree/bst.deletewhere.coverage.test.ts +37 -0
  50. package/test/unit/data-structures/binary-tree/bst.floor-lower-predicate.coverage.test.ts +29 -0
  51. package/test/unit/data-structures/binary-tree/bst.floor-setmany.coverage.test.ts +72 -0
  52. package/test/unit/data-structures/binary-tree/bst.getnode.range-ensure.coverage.test.ts +22 -0
  53. package/test/unit/data-structures/binary-tree/bst.misc-branches.coverage.test.ts +100 -0
  54. package/test/unit/data-structures/binary-tree/bst.more-branches-2.coverage.test.ts +133 -0
  55. package/test/unit/data-structures/binary-tree/bst.more-branches-3.coverage.test.ts +45 -0
  56. package/test/unit/data-structures/binary-tree/bst.more-branches-4.coverage.test.ts +36 -0
  57. package/test/unit/data-structures/binary-tree/bst.more-branches-5.coverage.test.ts +40 -0
  58. package/test/unit/data-structures/binary-tree/bst.more.coverage.test.ts +39 -0
  59. package/test/unit/data-structures/binary-tree/bst.node-family.coverage.test.ts +29 -0
  60. package/test/unit/data-structures/binary-tree/bst.range-pruning.coverage.test.ts +43 -0
  61. package/test/unit/data-structures/binary-tree/bst.search-fastpath.coverage.test.ts +30 -0
  62. package/test/unit/data-structures/binary-tree/bst.test.ts +25 -55
  63. package/test/unit/data-structures/binary-tree/red-black-tree.boundary-corruption-repair.coverage.test.ts +66 -0
  64. package/test/unit/data-structures/binary-tree/red-black-tree.boundary-max-update.coverage.test.ts +18 -0
  65. package/test/unit/data-structures/binary-tree/red-black-tree.boundary-null.coverage.test.ts +53 -0
  66. package/test/unit/data-structures/binary-tree/red-black-tree.boundary-stale-cache.coverage.test.ts +25 -0
  67. package/test/unit/data-structures/binary-tree/red-black-tree.boundary-update.coverage.test.ts +23 -0
  68. package/test/unit/data-structures/binary-tree/red-black-tree.cache-delete.coverage.test.ts +49 -0
  69. package/test/unit/data-structures/binary-tree/red-black-tree.cache-edge.coverage.test.ts +37 -0
  70. package/test/unit/data-structures/binary-tree/red-black-tree.cache-stale-insert.coverage.test.ts +39 -0
  71. package/test/unit/data-structures/binary-tree/red-black-tree.coverage.test.ts +334 -0
  72. package/test/unit/data-structures/binary-tree/red-black-tree.delete-fixup.coverage.test.ts +68 -0
  73. package/test/unit/data-structures/binary-tree/red-black-tree.delete-successor.coverage.test.ts +75 -0
  74. package/test/unit/data-structures/binary-tree/red-black-tree.factories.coverage.test.ts +26 -0
  75. package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-compare-update.coverage.test.ts +74 -0
  76. package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-no-update.coverage.test.ts +44 -0
  77. package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-nullish.coverage.test.ts +61 -0
  78. package/test/unit/data-structures/binary-tree/red-black-tree.hint-mapmode-defined.coverage.test.ts +35 -0
  79. package/test/unit/data-structures/binary-tree/red-black-tree.hint-mapmode-undefined.coverage.test.ts +43 -0
  80. package/test/unit/data-structures/binary-tree/red-black-tree.hint-more.coverage.test.ts +99 -0
  81. package/test/unit/data-structures/binary-tree/red-black-tree.hint.coverage.test.ts +60 -0
  82. package/test/unit/data-structures/binary-tree/red-black-tree.insert-cache-nullish.coverage.test.ts +29 -0
  83. package/test/unit/data-structures/binary-tree/red-black-tree.insert-header-parent-nullish.coverage.test.ts +17 -0
  84. package/test/unit/data-structures/binary-tree/red-black-tree.internal-walk.coverage.test.ts +57 -0
  85. package/test/unit/data-structures/binary-tree/red-black-tree.minmax-cache.test.ts +65 -0
  86. package/test/unit/data-structures/binary-tree/red-black-tree.misc-inputs.coverage.test.ts +17 -0
  87. package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-2.coverage.test.ts +121 -0
  88. package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-3.coverage.test.ts +55 -0
  89. package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-4.coverage.test.ts +44 -0
  90. package/test/unit/data-structures/binary-tree/red-black-tree.predsucc.coverage.test.ts +40 -0
  91. package/test/unit/data-structures/binary-tree/red-black-tree.remaining-branches.coverage.test.ts +123 -0
  92. package/test/unit/data-structures/binary-tree/red-black-tree.set-inputs.coverage.test.ts +64 -0
  93. package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-parent-cache.coverage.test.ts +79 -0
  94. package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-remaining.coverage.test.ts +44 -0
  95. package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-uncovered.coverage.test.ts +74 -0
  96. package/test/unit/data-structures/binary-tree/red-black-tree.update-branches.coverage.test.ts +30 -0
  97. package/test/unit/data-structures/binary-tree/segment-tree.more-branches.coverage.test.ts +31 -0
  98. package/test/unit/data-structures/binary-tree/tree-counter.coverage.test.ts +115 -0
  99. package/test/unit/data-structures/binary-tree/tree-counter.more-branches.coverage.test.ts +244 -0
  100. package/test/unit/data-structures/binary-tree/tree-counter.test.ts +4 -2
  101. package/test/unit/data-structures/binary-tree/tree-multi-map.coverage.test.ts +104 -0
  102. package/test/unit/data-structures/binary-tree/tree-multi-map.more-branches-2.coverage.test.ts +59 -0
  103. package/test/unit/data-structures/graph/abstract-graph.more-branches-2.coverage.test.ts +40 -0
  104. package/test/unit/data-structures/graph/abstract-graph.more-branches-3.coverage.test.ts +65 -0
  105. package/test/unit/data-structures/graph/abstract-graph.more-branches-4.coverage.test.ts +98 -0
  106. package/test/unit/data-structures/graph/abstract-graph.more-branches-5.coverage.test.ts +51 -0
  107. package/test/unit/data-structures/graph/abstract-graph.more-branches.coverage.test.ts +62 -0
  108. package/test/unit/data-structures/graph/directed-graph.more-branches-2.coverage.test.ts +38 -0
  109. package/test/unit/data-structures/graph/directed-graph.more-branches-3.coverage.test.ts +25 -0
  110. package/test/unit/data-structures/graph/directed-graph.more-branches.coverage.test.ts +82 -0
  111. package/test/unit/data-structures/graph/map-graph.more-branches.coverage.test.ts +22 -0
  112. package/test/unit/data-structures/graph/undirected-graph.more-branches-2.coverage.test.ts +35 -0
  113. package/test/unit/data-structures/graph/undirected-graph.more-branches.coverage.test.ts +87 -0
  114. package/test/unit/data-structures/hash/hash-map.more-branches.coverage.test.ts +64 -0
  115. package/test/unit/data-structures/hash/hash-map.toEntryFn-branch.coverage.test.ts +9 -0
  116. package/test/unit/data-structures/heap/heap.misc-branches.coverage.test.ts +110 -0
  117. package/test/unit/data-structures/heap/heap.remaining-branches.coverage.test.ts +22 -0
  118. package/test/unit/data-structures/heap/max-heap.coverage.test.ts +29 -0
  119. package/test/unit/data-structures/linked-list/doubly-linked-list.more-branches.coverage.test.ts +72 -0
  120. package/test/unit/data-structures/linked-list/linked-list.unshiftMany-else.coverage.test.ts +15 -0
  121. package/test/unit/data-structures/linked-list/singly-linked-list.coverage.test.ts +221 -0
  122. package/test/unit/data-structures/linked-list/singly-linked-list.more-branches.coverage.test.ts +86 -0
  123. package/test/unit/data-structures/linked-list/skip-linked-list.more-branches.coverage.test.ts +31 -0
  124. package/test/unit/data-structures/matrix/matrix.more-branches.coverage.test.ts +81 -0
  125. package/test/unit/data-structures/matrix/matrix.pivotElement-nullish.coverage.test.ts +28 -0
  126. package/test/unit/data-structures/priority-queue/max-priority-queue.more-branches.coverage.test.ts +10 -0
  127. package/test/unit/data-structures/priority-queue/priority-queue.coverage.test.ts +21 -0
  128. package/test/unit/data-structures/queue/deque.coverage.test.ts +173 -0
  129. package/test/unit/data-structures/queue/deque.more-branches-2.coverage.test.ts +39 -0
  130. package/test/unit/data-structures/queue/deque.more-branches-3.coverage.test.ts +9 -0
  131. package/test/unit/data-structures/queue/deque.more-branches.coverage.test.ts +95 -0
  132. package/test/unit/data-structures/queue/queue.coverage.test.ts +138 -0
  133. package/test/unit/data-structures/queue/queue.more-branches-2.coverage.test.ts +27 -0
  134. package/test/unit/data-structures/stack/stack.coverage.test.ts +112 -0
  135. package/test/unit/data-structures/tree/tree.more-branches.coverage.test.ts +9 -0
  136. package/test/unit/data-structures/trie/trie.more-branches-2.coverage.test.ts +51 -0
  137. package/test/utils/patch.ts +33 -0
@@ -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
+ });
@@ -0,0 +1,93 @@
1
+ import { AVLTreeCounter, AVLTreeCounterNode } from '../../../../src';
2
+
3
+ describe('AVLTreeCounter additional branch coverage', () => {
4
+ it('AVLTreeCounterNode constructor uses default count=1', () => {
5
+ const n = new AVLTreeCounterNode(1, 'v');
6
+ expect(n.count).toBe(1);
7
+ });
8
+
9
+ it('AVLTreeCounterNode familyPosition covers ISOLATED/ROOT/LEFT/ROOT_LEFT/RIGHT/ROOT_RIGHT/MAL_NODE', () => {
10
+ const a = new AVLTreeCounterNode(1);
11
+ expect(a.familyPosition).toBe('ISOLATED');
12
+
13
+ // root-like: no parent, but has child
14
+ const root = new AVLTreeCounterNode(10);
15
+ root.left = new AVLTreeCounterNode(5);
16
+ expect(root.familyPosition).toBe('ROOT');
17
+
18
+ const p = new AVLTreeCounterNode(0);
19
+ const left = new AVLTreeCounterNode(-1);
20
+ const right = new AVLTreeCounterNode(1);
21
+ p.left = left;
22
+ p.right = right;
23
+
24
+ expect(left.familyPosition).toBe('LEFT');
25
+ expect(right.familyPosition).toBe('RIGHT');
26
+
27
+ // root-left/right variants: node has its own child
28
+ left.left = new AVLTreeCounterNode(-2);
29
+ right.right = new AVLTreeCounterNode(2);
30
+ expect(left.familyPosition).toBe('ROOT_LEFT');
31
+ expect(right.familyPosition).toBe('ROOT_RIGHT');
32
+
33
+ // MAL_NODE: has parent but parent does not reference it
34
+ const mal = new AVLTreeCounterNode(99);
35
+ mal.parent = p;
36
+ expect(mal.familyPosition).toBe('MAL_NODE');
37
+ });
38
+
39
+ it('set() returns false when keyNodeOrEntry is null/undefined (covers newNode===undefined early return)', () => {
40
+ const t = new AVLTreeCounter<number, number>([], { isMapMode: false });
41
+ expect(t.set(undefined as any)).toBe(false);
42
+ expect(t.set(null as any)).toBe(false);
43
+ });
44
+
45
+ it('set() with count=0 exercises orgNodeCount==0 branch without changing aggregate count', () => {
46
+ const t = new AVLTreeCounter<number, number>([], { isMapMode: false });
47
+ expect(t.count).toBe(0);
48
+
49
+ t.set(1, 1, 0);
50
+ expect(t.count).toBe(0);
51
+
52
+ // normal insert should increase count
53
+ t.set(2, 2);
54
+ expect(t.count).toBe(1);
55
+ });
56
+
57
+ it('delete() returns [] when tree is empty or key missing', () => {
58
+ const t = new AVLTreeCounter<number, number>([], { isMapMode: false });
59
+ expect(t.delete(1)).toEqual([]);
60
+
61
+ t.set(1, 1);
62
+ expect(t.delete(999)).toEqual([]);
63
+ });
64
+
65
+ it('delete() decrements count when node.count>1 and ignoreCount=false', () => {
66
+ const t = new AVLTreeCounter<number, number>([], { isMapMode: false });
67
+ t.set(1, 1);
68
+ t.set(1, 1); // duplicate increments count in _replaceNode
69
+
70
+ const n = t.getNode(1)!;
71
+ expect(n.count).toBe(2);
72
+ expect(t.count).toBe(2);
73
+
74
+ const res = t.delete(1, false);
75
+ expect(res.length).toBe(1);
76
+ expect(t.getNode(1)!.count).toBe(1);
77
+ expect(t.count).toBe(1);
78
+ });
79
+
80
+ it('delete() removes root when it has no left child and no parent (covers parent-null root replacement)', () => {
81
+ const t = new AVLTreeCounter<number, number>([], { isMapMode: false });
82
+ t.set(1, 1);
83
+ t.set(2, 2);
84
+
85
+ // force root to have no left (common in AVL after balancing for two nodes)
86
+ const root = t.root!;
87
+ root.left = undefined;
88
+
89
+ const res = t.delete(root.key, true);
90
+ expect(res.length).toBe(1);
91
+ expect(t.root).toBeDefined();
92
+ });
93
+ });