data-structure-typed 2.5.0 → 2.5.2

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 (246) hide show
  1. package/.vitepress/cache/deps_temp_51f5f1b0/chunk-7OIKW5WK.js +12984 -0
  2. package/.vitepress/cache/deps_temp_51f5f1b0/package.json +3 -0
  3. package/.vitepress/cache/deps_temp_51f5f1b0/vitepress___@vue_devtools-api.js +4505 -0
  4. package/.vitepress/cache/deps_temp_51f5f1b0/vitepress___@vueuse_core.js +9731 -0
  5. package/.vitepress/cache/deps_temp_51f5f1b0/vue.js +347 -0
  6. package/CHANGELOG.md +5 -1
  7. package/README.md +124 -29
  8. package/dist/cjs/binary-tree.cjs +26282 -0
  9. package/dist/cjs/graph.cjs +5422 -0
  10. package/dist/cjs/hash.cjs +1310 -0
  11. package/dist/cjs/heap.cjs +1602 -0
  12. package/dist/cjs/index.cjs +31257 -14673
  13. package/dist/cjs/linked-list.cjs +4576 -0
  14. package/dist/cjs/matrix.cjs +1080 -0
  15. package/dist/cjs/priority-queue.cjs +1376 -0
  16. package/dist/cjs/queue.cjs +4264 -0
  17. package/dist/cjs/stack.cjs +907 -0
  18. package/dist/cjs/trie.cjs +1223 -0
  19. package/dist/cjs-legacy/binary-tree.cjs +26319 -0
  20. package/dist/cjs-legacy/graph.cjs +5420 -0
  21. package/dist/cjs-legacy/hash.cjs +1310 -0
  22. package/dist/cjs-legacy/heap.cjs +1599 -0
  23. package/dist/cjs-legacy/index.cjs +31268 -14679
  24. package/dist/cjs-legacy/linked-list.cjs +4582 -0
  25. package/dist/cjs-legacy/matrix.cjs +1083 -0
  26. package/dist/cjs-legacy/priority-queue.cjs +1374 -0
  27. package/dist/cjs-legacy/queue.cjs +4262 -0
  28. package/dist/cjs-legacy/stack.cjs +907 -0
  29. package/dist/cjs-legacy/trie.cjs +1222 -0
  30. package/dist/esm/binary-tree.mjs +26267 -0
  31. package/dist/esm/graph.mjs +5409 -0
  32. package/dist/esm/hash.mjs +1307 -0
  33. package/dist/esm/heap.mjs +1596 -0
  34. package/dist/esm/index.mjs +31254 -14674
  35. package/dist/esm/linked-list.mjs +4569 -0
  36. package/dist/esm/matrix.mjs +1076 -0
  37. package/dist/esm/priority-queue.mjs +1372 -0
  38. package/dist/esm/queue.mjs +4260 -0
  39. package/dist/esm/stack.mjs +905 -0
  40. package/dist/esm/trie.mjs +1220 -0
  41. package/dist/esm-legacy/binary-tree.mjs +26304 -0
  42. package/dist/esm-legacy/graph.mjs +5407 -0
  43. package/dist/esm-legacy/hash.mjs +1307 -0
  44. package/dist/esm-legacy/heap.mjs +1593 -0
  45. package/dist/esm-legacy/index.mjs +31265 -14680
  46. package/dist/esm-legacy/linked-list.mjs +4575 -0
  47. package/dist/esm-legacy/matrix.mjs +1079 -0
  48. package/dist/esm-legacy/priority-queue.mjs +1370 -0
  49. package/dist/esm-legacy/queue.mjs +4258 -0
  50. package/dist/esm-legacy/stack.mjs +905 -0
  51. package/dist/esm-legacy/trie.mjs +1219 -0
  52. package/dist/types/common/error.d.ts +9 -0
  53. package/dist/types/common/index.d.ts +1 -1
  54. package/dist/types/data-structures/base/index.d.ts +1 -0
  55. package/dist/types/data-structures/base/iterable-entry-base.d.ts +8 -8
  56. package/dist/types/data-structures/base/linear-base.d.ts +3 -3
  57. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +288 -0
  58. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +336 -0
  59. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +618 -18
  60. package/dist/types/data-structures/binary-tree/bst.d.ts +676 -1
  61. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +456 -0
  62. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +144 -1
  63. package/dist/types/data-structures/binary-tree/tree-map.d.ts +3307 -399
  64. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +3285 -360
  65. package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +2674 -325
  66. package/dist/types/data-structures/binary-tree/tree-set.d.ts +3072 -287
  67. package/dist/types/data-structures/graph/abstract-graph.d.ts +4 -4
  68. package/dist/types/data-structures/graph/directed-graph.d.ts +240 -0
  69. package/dist/types/data-structures/graph/undirected-graph.d.ts +216 -0
  70. package/dist/types/data-structures/hash/hash-map.d.ts +274 -10
  71. package/dist/types/data-structures/heap/heap.d.ts +336 -0
  72. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +411 -3
  73. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +363 -3
  74. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +434 -2
  75. package/dist/types/data-structures/matrix/matrix.d.ts +192 -0
  76. package/dist/types/data-structures/queue/deque.d.ts +364 -4
  77. package/dist/types/data-structures/queue/queue.d.ts +288 -0
  78. package/dist/types/data-structures/stack/stack.d.ts +240 -0
  79. package/dist/types/data-structures/trie/trie.d.ts +292 -4
  80. package/dist/types/interfaces/graph.d.ts +1 -1
  81. package/dist/types/types/common.d.ts +2 -2
  82. package/dist/types/types/data-structures/binary-tree/bst.d.ts +1 -0
  83. package/dist/types/types/data-structures/binary-tree/tree-map.d.ts +5 -0
  84. package/dist/types/types/data-structures/binary-tree/tree-multi-set.d.ts +4 -0
  85. package/dist/types/types/data-structures/binary-tree/tree-set.d.ts +4 -0
  86. package/dist/types/types/data-structures/heap/heap.d.ts +1 -0
  87. package/dist/types/types/data-structures/priority-queue/priority-queue.d.ts +1 -0
  88. package/dist/types/types/utils/validate-type.d.ts +4 -4
  89. package/dist/umd/data-structure-typed.js +31196 -14608
  90. package/dist/umd/data-structure-typed.min.js +11 -5
  91. package/docs-site-docusaurus/README.md +41 -0
  92. package/docs-site-docusaurus/docs/api/README.md +52 -0
  93. package/docs-site-docusaurus/docs/api/classes/AVLTree.md +6644 -0
  94. package/docs-site-docusaurus/docs/api/classes/AVLTreeNode.md +282 -0
  95. package/docs-site-docusaurus/docs/api/classes/AbstractGraph.md +2266 -0
  96. package/docs-site-docusaurus/docs/api/classes/BST.md +6293 -0
  97. package/docs-site-docusaurus/docs/api/classes/BSTNode.md +333 -0
  98. package/docs-site-docusaurus/docs/api/classes/BinaryIndexedTree.md +455 -0
  99. package/docs-site-docusaurus/docs/api/classes/BinaryTree.md +4647 -0
  100. package/docs-site-docusaurus/docs/api/classes/BinaryTreeNode.md +331 -0
  101. package/docs-site-docusaurus/docs/api/classes/Deque.md +2767 -0
  102. package/docs-site-docusaurus/docs/api/classes/DirectedGraph.md +2999 -0
  103. package/docs-site-docusaurus/docs/api/classes/DoublyLinkedList.md +2685 -0
  104. package/docs-site-docusaurus/docs/api/classes/DoublyLinkedListNode.md +221 -0
  105. package/docs-site-docusaurus/docs/api/classes/FibonacciHeap.md +253 -0
  106. package/docs-site-docusaurus/docs/api/classes/FibonacciHeapNode.md +21 -0
  107. package/docs-site-docusaurus/docs/api/classes/HashMap.md +1333 -0
  108. package/docs-site-docusaurus/docs/api/classes/Heap.md +1881 -0
  109. package/docs-site-docusaurus/docs/api/classes/IterableElementBase.md +800 -0
  110. package/docs-site-docusaurus/docs/api/classes/IterableEntryBase.md +644 -0
  111. package/docs-site-docusaurus/docs/api/classes/LinearBase.md +1632 -0
  112. package/docs-site-docusaurus/docs/api/classes/LinearLinkedBase.md +1853 -0
  113. package/docs-site-docusaurus/docs/api/classes/LinkedHashMap.md +1108 -0
  114. package/docs-site-docusaurus/docs/api/classes/LinkedListNode.md +156 -0
  115. package/docs-site-docusaurus/docs/api/classes/LinkedListQueue.md +2824 -0
  116. package/docs-site-docusaurus/docs/api/classes/MapGraph.md +2929 -0
  117. package/docs-site-docusaurus/docs/api/classes/Matrix.md +1026 -0
  118. package/docs-site-docusaurus/docs/api/classes/MaxHeap.md +1866 -0
  119. package/docs-site-docusaurus/docs/api/classes/MaxPriorityQueue.md +1883 -0
  120. package/docs-site-docusaurus/docs/api/classes/MinHeap.md +1879 -0
  121. package/docs-site-docusaurus/docs/api/classes/MinPriorityQueue.md +1882 -0
  122. package/docs-site-docusaurus/docs/api/classes/Navigator.md +109 -0
  123. package/docs-site-docusaurus/docs/api/classes/PriorityQueue.md +1839 -0
  124. package/docs-site-docusaurus/docs/api/classes/Queue.md +2244 -0
  125. package/docs-site-docusaurus/docs/api/classes/RedBlackTree.md +6888 -0
  126. package/docs-site-docusaurus/docs/api/classes/SegmentTree.md +372 -0
  127. package/docs-site-docusaurus/docs/api/classes/SinglyLinkedList.md +2897 -0
  128. package/docs-site-docusaurus/docs/api/classes/SinglyLinkedListNode.md +169 -0
  129. package/docs-site-docusaurus/docs/api/classes/SkipList.md +1229 -0
  130. package/docs-site-docusaurus/docs/api/classes/Stack.md +1573 -0
  131. package/docs-site-docusaurus/docs/api/classes/TreeMap.md +1389 -0
  132. package/docs-site-docusaurus/docs/api/classes/TreeMultiMap.md +1591 -0
  133. package/docs-site-docusaurus/docs/api/classes/TreeSet.md +1246 -0
  134. package/docs-site-docusaurus/docs/api/classes/Trie.md +1708 -0
  135. package/docs-site-docusaurus/docs/api/classes/TrieNode.md +199 -0
  136. package/docs-site-docusaurus/docs/api/classes/UndirectedGraph.md +2979 -0
  137. package/docs-site-docusaurus/docs/guide/_category_.json +6 -0
  138. package/docs-site-docusaurus/docs/guide/architecture.md +615 -0
  139. package/docs-site-docusaurus/docs/guide/concepts.md +451 -0
  140. package/docs-site-docusaurus/docs/guide/faq.md +180 -0
  141. package/docs-site-docusaurus/docs/guide/guides.md +597 -0
  142. package/docs-site-docusaurus/docs/guide/installation.md +62 -0
  143. package/docs-site-docusaurus/docs/guide/integrations.md +825 -0
  144. package/docs-site-docusaurus/docs/guide/overview.md +645 -0
  145. package/docs-site-docusaurus/docs/guide/performance.md +835 -0
  146. package/docs-site-docusaurus/docs/guide/quick-start.md +104 -0
  147. package/docs-site-docusaurus/docs/guide/use-cases/_category_.json +6 -0
  148. package/docs-site-docusaurus/docs/guide/use-cases/array-sort-alternative.md +158 -0
  149. package/docs-site-docusaurus/docs/guide/use-cases/heap-vs-sorting.md +92 -0
  150. package/docs-site-docusaurus/docs/guide/use-cases/map-vs-treemap.md +151 -0
  151. package/docs-site-docusaurus/docs/guide/use-cases/priority-queue-typescript.md +113 -0
  152. package/docs-site-docusaurus/docs/guide/use-cases/treemap-javascript.md +151 -0
  153. package/docs-site-docusaurus/docusaurus.config.ts +159 -0
  154. package/docs-site-docusaurus/fix-mdx-generics.mjs +75 -0
  155. package/docs-site-docusaurus/package-lock.json +18667 -0
  156. package/docs-site-docusaurus/package.json +50 -0
  157. package/docs-site-docusaurus/prefix-class-to-methods.mjs +48 -0
  158. package/docs-site-docusaurus/sidebars.ts +23 -0
  159. package/docs-site-docusaurus/sort-protected.mjs +87 -0
  160. package/docs-site-docusaurus/src/css/custom.css +96 -0
  161. package/docs-site-docusaurus/src/pages/index.module.css +13 -0
  162. package/docs-site-docusaurus/src/pages/index.tsx +120 -0
  163. package/docs-site-docusaurus/src/pages/markdown-page.md +7 -0
  164. package/docs-site-docusaurus/src/theme/TOCItems/index.tsx +34 -0
  165. package/docs-site-docusaurus/static/.nojekyll +0 -0
  166. package/docs-site-docusaurus/static/img/docusaurus-social-card.jpg +0 -0
  167. package/docs-site-docusaurus/static/img/docusaurus.png +0 -0
  168. package/docs-site-docusaurus/static/img/favicon.ico +0 -0
  169. package/docs-site-docusaurus/static/img/favicon.png +0 -0
  170. package/docs-site-docusaurus/static/img/logo-180.png +0 -0
  171. package/docs-site-docusaurus/static/img/logo.jpg +0 -0
  172. package/docs-site-docusaurus/static/img/logo.png +0 -0
  173. package/docs-site-docusaurus/static/img/logo.svg +1 -0
  174. package/docs-site-docusaurus/static/img/og-image.png +0 -0
  175. package/docs-site-docusaurus/static/img/undraw_docusaurus_mountain.svg +171 -0
  176. package/docs-site-docusaurus/static/img/undraw_docusaurus_react.svg +170 -0
  177. package/docs-site-docusaurus/static/img/undraw_docusaurus_tree.svg +40 -0
  178. package/docs-site-docusaurus/static/llms.txt +37 -0
  179. package/docs-site-docusaurus/static/robots.txt +4 -0
  180. package/docs-site-docusaurus/typedoc.json +23 -0
  181. package/llms.txt +37 -0
  182. package/package.json +159 -55
  183. package/src/common/error.ts +19 -1
  184. package/src/common/index.ts +1 -1
  185. package/src/data-structures/base/index.ts +1 -0
  186. package/src/data-structures/base/iterable-element-base.ts +3 -2
  187. package/src/data-structures/base/iterable-entry-base.ts +8 -8
  188. package/src/data-structures/base/linear-base.ts +3 -3
  189. package/src/data-structures/binary-tree/avl-tree.ts +287 -0
  190. package/src/data-structures/binary-tree/binary-indexed-tree.ts +327 -5
  191. package/src/data-structures/binary-tree/binary-tree.ts +581 -6
  192. package/src/data-structures/binary-tree/bst.ts +922 -7
  193. package/src/data-structures/binary-tree/red-black-tree.ts +453 -0
  194. package/src/data-structures/binary-tree/segment-tree.ts +139 -2
  195. package/src/data-structures/binary-tree/tree-map.ts +3300 -495
  196. package/src/data-structures/binary-tree/tree-multi-map.ts +3384 -563
  197. package/src/data-structures/binary-tree/tree-multi-set.ts +2757 -493
  198. package/src/data-structures/binary-tree/tree-set.ts +3122 -440
  199. package/src/data-structures/graph/abstract-graph.ts +6 -6
  200. package/src/data-structures/graph/directed-graph.ts +230 -0
  201. package/src/data-structures/graph/undirected-graph.ts +207 -0
  202. package/src/data-structures/hash/hash-map.ts +270 -19
  203. package/src/data-structures/heap/heap.ts +326 -4
  204. package/src/data-structures/heap/max-heap.ts +2 -2
  205. package/src/data-structures/linked-list/doubly-linked-list.ts +394 -3
  206. package/src/data-structures/linked-list/singly-linked-list.ts +348 -3
  207. package/src/data-structures/linked-list/skip-linked-list.ts +421 -7
  208. package/src/data-structures/matrix/matrix.ts +194 -10
  209. package/src/data-structures/priority-queue/max-priority-queue.ts +2 -2
  210. package/src/data-structures/queue/deque.ts +350 -5
  211. package/src/data-structures/queue/queue.ts +276 -0
  212. package/src/data-structures/stack/stack.ts +230 -0
  213. package/src/data-structures/trie/trie.ts +283 -7
  214. package/src/interfaces/graph.ts +1 -1
  215. package/src/types/common.ts +2 -2
  216. package/src/types/data-structures/binary-tree/bst.ts +1 -0
  217. package/src/types/data-structures/binary-tree/tree-map.ts +6 -0
  218. package/src/types/data-structures/binary-tree/tree-multi-set.ts +5 -0
  219. package/src/types/data-structures/binary-tree/tree-set.ts +5 -0
  220. package/src/types/data-structures/heap/heap.ts +1 -0
  221. package/src/types/data-structures/priority-queue/priority-queue.ts +1 -0
  222. package/src/types/utils/validate-type.ts +4 -4
  223. package/vercel.json +6 -0
  224. package/dist/leetcode/avl-tree-counter.mjs +0 -2957
  225. package/dist/leetcode/avl-tree-multi-map.mjs +0 -2889
  226. package/dist/leetcode/avl-tree.mjs +0 -2720
  227. package/dist/leetcode/binary-tree.mjs +0 -1594
  228. package/dist/leetcode/bst.mjs +0 -2398
  229. package/dist/leetcode/deque.mjs +0 -683
  230. package/dist/leetcode/directed-graph.mjs +0 -1733
  231. package/dist/leetcode/doubly-linked-list.mjs +0 -709
  232. package/dist/leetcode/hash-map.mjs +0 -493
  233. package/dist/leetcode/heap.mjs +0 -542
  234. package/dist/leetcode/max-heap.mjs +0 -375
  235. package/dist/leetcode/max-priority-queue.mjs +0 -383
  236. package/dist/leetcode/min-heap.mjs +0 -363
  237. package/dist/leetcode/min-priority-queue.mjs +0 -371
  238. package/dist/leetcode/priority-queue.mjs +0 -363
  239. package/dist/leetcode/queue.mjs +0 -943
  240. package/dist/leetcode/red-black-tree.mjs +0 -2765
  241. package/dist/leetcode/singly-linked-list.mjs +0 -754
  242. package/dist/leetcode/stack.mjs +0 -217
  243. package/dist/leetcode/tree-counter.mjs +0 -3039
  244. package/dist/leetcode/tree-multi-map.mjs +0 -2913
  245. package/dist/leetcode/trie.mjs +0 -413
  246. package/dist/leetcode/undirected-graph.mjs +0 -1650
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  import type { Comparator, TreeMultiMapOptions } from '../../types';
10
- import { ERR, Range } from '../../common';
10
+ import { ERR, raise, Range } from '../../common';
11
11
  import { RedBlackTree, RedBlackTreeNode } from './red-black-tree';
12
12
  import { TreeSet } from './tree-set';
13
13
 
@@ -49,7 +49,7 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
49
49
  const comparator = options.comparator ?? TreeSet.createDefaultComparator<K>();
50
50
  this.#isDefaultComparator = options.comparator === undefined;
51
51
  const toEntryFn = options.toEntryFn;
52
- this.#core = new RedBlackTree<K, V[], R>([], { ...options, comparator, isMapMode: options.isMapMode });
52
+ this.#core = new RedBlackTree<K, V[], R>([], { ...options, comparator, isMapMode: options.isMapMode, enableOrderStatistic: options.enableOrderStatistic });
53
53
 
54
54
  for (const x of keysNodesEntriesOrRaws) {
55
55
  if (x === null || x === undefined) continue;
@@ -91,15 +91,15 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
91
91
  // reuse TreeSet strict validation (same policy)
92
92
  // NOTE: TreeSet._validateKey is private, so we replicate the checks.
93
93
  if (typeof key === 'number') {
94
- if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN('TreeMultiMap'));
94
+ if (Number.isNaN(key)) raise(TypeError, ERR.invalidNaN('TreeMultiMap'));
95
95
  return;
96
96
  }
97
97
  if (typeof key === 'string') return;
98
98
  if (key instanceof Date) {
99
- if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate('TreeMultiMap'));
99
+ if (Number.isNaN(key.getTime())) raise(TypeError, ERR.invalidDate('TreeMultiMap'));
100
100
  return;
101
101
  }
102
- throw new TypeError(ERR.comparatorRequired('TreeMultiMap'));
102
+ raise(TypeError, ERR.comparatorRequired('TreeMultiMap'));
103
103
  }
104
104
 
105
105
  /**
@@ -156,17 +156,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
156
156
 
157
157
 
158
158
 
159
- * @example
160
- * // Check if empty
161
- * console.log(new TreeMultiMap().isEmpty()); // true;
162
- */
163
- isEmpty(): boolean {
164
- return this.size === 0;
165
- }
166
-
167
- /**
168
- * Removes all entries from the map.
169
- * @remarks Time O(1), Space O(1)
170
159
 
171
160
 
172
161
 
@@ -210,58 +199,20 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
210
199
 
211
200
 
212
201
 
213
- * @example
214
- * // Remove all entries
215
- * const mm = new TreeMultiMap<number, string>();
216
- * mm.add(1, 'a');
217
- * mm.clear();
218
- * console.log(mm.isEmpty()); // true;
219
- */
220
- clear(): void {
221
- this.#core.clear();
222
- }
223
-
224
- /**
225
- * Bucket length for a key (missing => 0).
226
- * @remarks Time O(log n), Space O(1)
227
202
 
228
203
 
229
204
 
230
- * @example
231
- * // Count values for key
232
- * const mm = new TreeMultiMap<number, string>();
233
- * mm.add(1, 'a');
234
- * mm.add(1, 'b');
235
- * console.log(mm.count(1)); // 2;
236
- */
237
- count(key: K): number {
238
- const b = this.get(key);
239
- return Array.isArray(b) ? b.length : 0;
240
- }
241
-
242
- /**
243
- * Total number of values across all buckets (Σ bucket.length).
244
- * @remarks Time O(n), Space O(1)
245
205
 
246
206
 
247
207
 
248
- * @example
249
- * // Total number of values
250
- * const mm = new TreeMultiMap<number, string>();
251
- * mm.add(1, 'a');
252
- * mm.add(1, 'b');
253
- * mm.add(2, 'c');
254
- * console.log(mm.totalSize); // 3;
255
- */
256
- get totalSize(): number {
257
- let sum = 0;
258
- for (const [, bucket] of this) sum += bucket.length;
259
- return sum;
260
- }
261
-
262
- /**
263
- * Whether the map contains the given key.
264
- * @remarks Time O(log n), Space O(1)
208
+
209
+
210
+
211
+
212
+
213
+
214
+
215
+
265
216
 
266
217
 
267
218
 
@@ -321,20 +272,23 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
321
272
 
322
273
 
323
274
  * @example
324
- * // Check key existence
325
- * const mm = new TreeMultiMap<number, string>();
326
- * mm.add(1, 'a');
327
- * console.log(mm.has(1)); // true;
328
- * console.log(mm.has(2)); // false;
275
+ * // Check if empty
276
+ * console.log(new TreeMultiMap().isEmpty()); // true;
329
277
  */
330
- has(key: K): boolean {
331
- this._validateKey(key);
332
- return this.#core.has(key);
278
+ isEmpty(): boolean {
279
+ return this.size === 0;
333
280
  }
334
281
 
335
282
  /**
336
- * Live bucket reference (do not auto-delete key if bucket becomes empty via mutation).
337
- * @remarks Time O(log n), Space O(1)
283
+ * Removes all entries from the map.
284
+ * @remarks Time O(1), Space O(1)
285
+
286
+
287
+
288
+
289
+
290
+
291
+
338
292
 
339
293
 
340
294
 
@@ -393,21 +347,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
393
347
 
394
348
 
395
349
 
396
- * @example
397
- * // Get values for key
398
- * const mm = new TreeMultiMap<number, string>();
399
- * mm.add(1, 'a');
400
- * mm.add(1, 'b');
401
- * console.log(mm.get(1)); // ['a', 'b'];
402
- */
403
- get(key: K): V[] | undefined {
404
- this._validateKey(key);
405
- return this.#core.get(key);
406
- }
407
-
408
- /**
409
- * Append a single value.
410
- * @remarks Time O(log n), Space O(1)
411
350
 
412
351
 
413
352
 
@@ -445,27 +384,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
445
384
 
446
385
 
447
386
 
448
- * @example
449
- * // Add key-value pair
450
- * const mm = new TreeMultiMap<number, string>();
451
- * mm.add(1, 'a');
452
- * mm.add(1, 'b');
453
- * mm.add(2, 'c');
454
- * console.log(mm.get(1)); // ['a', 'b'];
455
- */
456
- add(key: K, value: V): boolean {
457
- this._validateKey(key);
458
- const bucket = this.#core.get(key);
459
- if (bucket) {
460
- bucket.push(value);
461
- return true;
462
- }
463
- return this.#core.set(key, [value]);
464
- }
465
-
466
- /**
467
- * Alias for compatibility with existing TreeMultiMap semantics.
468
- * @remarks Time O(log n), Space O(1) for single value; O(log n + m) for bucket append
469
387
 
470
388
 
471
389
 
@@ -523,39 +441,18 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
523
441
 
524
442
 
525
443
  * @example
526
- * // Set values for key
444
+ * // Remove all entries
527
445
  * const mm = new TreeMultiMap<number, string>();
528
- * mm.set(1, 'a');
529
- * mm.set(1, 'b');
530
- * console.log(mm.get(1)); // ['a', 'b'];
446
+ * mm.add(1, 'a');
447
+ * mm.clear();
448
+ * console.log(mm.isEmpty()); // true;
531
449
  */
532
- set(entry: [K | null | undefined, V[] | undefined] | K | null | undefined, value?: V): boolean;
533
- set(key: K, value: V): boolean;
534
- set(entry: [K | null | undefined, V[] | undefined] | K | null | undefined, value?: V): boolean {
535
- if (entry === null || entry === undefined) return false;
536
- if (Array.isArray(entry)) {
537
- const [k, bucket] = entry;
538
- if (k === null || k === undefined) return false;
539
- if (value !== undefined) return this.add(k as K, value);
540
- if (bucket === undefined) {
541
- // ensure key exists
542
- return this.#core.set(k as K, [] as V[]);
543
- }
544
- // append bucket
545
- const existing = this.#core.get(k as K);
546
- if (existing) {
547
- existing.push(...bucket);
548
- return true;
549
- }
550
- return this.#core.set(k as K, [...bucket] as V[]);
551
- }
552
- // key-only or key+value
553
- if (value !== undefined) return this.add(entry as K, value);
554
- return this.#core.set(entry as K, [] as V[]);
450
+ clear(): void {
451
+ this.#core.clear();
555
452
  }
556
453
 
557
454
  /**
558
- * Deletes a key and its entire bucket.
455
+ * Bucket length for a key (missing => 0).
559
456
  * @remarks Time O(log n), Space O(1)
560
457
 
561
458
 
@@ -583,12 +480,21 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
583
480
 
584
481
 
585
482
 
586
-
587
-
588
-
589
-
590
-
591
-
483
+ * @example
484
+ * // Count values for key
485
+ * const mm = new TreeMultiMap<number, string>();
486
+ * mm.add(1, 'a');
487
+ * mm.add(1, 'b');
488
+ * console.log(mm.count(1)); // 2;
489
+ */
490
+ count(key: K): number {
491
+ const b = this.get(key);
492
+ return Array.isArray(b) ? b.length : 0;
493
+ }
494
+
495
+ /**
496
+ * Total number of values across all buckets (Σ bucket.length).
497
+ * @remarks Time O(n), Space O(1)
592
498
 
593
499
 
594
500
 
@@ -616,106 +522,3174 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
616
522
 
617
523
 
618
524
  * @example
619
- * // Remove key
525
+ * // Total number of values
620
526
  * const mm = new TreeMultiMap<number, string>();
621
527
  * mm.add(1, 'a');
622
- * mm.add(2, 'b');
623
- * mm.delete(1);
624
- * console.log(mm.has(1)); // false;
528
+ * mm.add(1, 'b');
529
+ * mm.add(2, 'c');
530
+ * console.log(mm.totalSize); // 3;
625
531
  */
626
- delete(key: K): boolean {
627
- this._validateKey(key);
628
- return this.#core.delete(key).length > 0;
532
+ get totalSize(): number {
533
+ let sum = 0;
534
+ for (const [, bucket] of this) sum += bucket.length;
535
+ return sum;
629
536
  }
630
537
 
631
538
  /**
632
- * Check if a specific value exists in a key's bucket.
633
- * @remarks Time O(log n + m), Space O(1) where m is bucket size
539
+ * Whether the map contains the given key.
540
+ * @remarks Time O(log n), Space O(1)
634
541
 
635
542
 
636
543
 
637
- * @example
638
- * // Check specific key-value
639
- * const mm = new TreeMultiMap<number, string>();
640
- * mm.add(1, 'a');
641
- * console.log(mm.hasEntry(1, 'a')); // true;
642
- * console.log(mm.hasEntry(1, 'z')); // false;
643
- */
644
- hasEntry(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): boolean {
645
- const bucket = this.get(key);
646
- if (!Array.isArray(bucket)) return false;
647
- return bucket.some(v => eq(v, value));
648
- }
649
-
650
- /**
651
- * Delete a single occurrence of a value from a key's bucket.
652
- * @remarks Time O(log n + m), Space O(1) where m is bucket size
653
544
 
654
545
 
655
546
 
656
- * @example
657
- * // Delete specific value
658
- * const mm = new TreeMultiMap<number, string>();
659
- * mm.add(1, 'a');
660
- * mm.add(1, 'b');
661
- * mm.deleteValue(1, 'a');
662
- * console.log(mm.get(1)); // ['b'];
663
- */
664
- deleteValue(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): boolean {
665
- const bucket = this.get(key);
666
- if (!Array.isArray(bucket)) return false;
667
- const idx = bucket.findIndex(v => eq(v, value));
668
- if (idx === -1) return false;
669
- bucket.splice(idx, 1);
670
- if (bucket.length === 0) this.delete(key);
671
- return true;
672
- }
673
-
674
- /**
675
- * Delete all occurrences of a value from a key's bucket.
676
- * @remarks Time O(log n + m), Space O(1) where m is bucket size
677
547
 
678
548
 
679
549
 
680
- * @example
681
- * // Delete all matching values
682
- * const mm = new TreeMultiMap<number, string>();
683
- * mm.add(1, 'a');
684
- * mm.add(1, 'a');
685
- * mm.add(1, 'b');
686
- * const count = mm.deleteValues(1, 'a');
687
- * console.log(count); // 2;
688
- */
689
- deleteValues(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): number {
690
- const bucket = this.get(key);
691
- if (!Array.isArray(bucket) || bucket.length === 0) return 0;
692
- let removed = 0;
693
- for (let i = bucket.length - 1; i >= 0; i--) {
694
- if (eq(bucket[i] as V, value)) {
695
- bucket.splice(i, 1);
696
- removed++;
697
- }
698
- }
699
- if (bucket.length === 0 && removed > 0) this.delete(key);
550
+
551
+
552
+
553
+
554
+
555
+
556
+
557
+
558
+
559
+
560
+
561
+
562
+
563
+
564
+
565
+
566
+
567
+
568
+
569
+
570
+
571
+
572
+
573
+
574
+
575
+
576
+
577
+
578
+
579
+
580
+
581
+
582
+
583
+
584
+
585
+
586
+
587
+
588
+
589
+
590
+
591
+
592
+
593
+
594
+
595
+
596
+
597
+
598
+
599
+
600
+
601
+
602
+
603
+
604
+
605
+
606
+
607
+
608
+
609
+
610
+
611
+
612
+
613
+
614
+
615
+
616
+
617
+
618
+
619
+
620
+
621
+
622
+
623
+
624
+
625
+
626
+
627
+
628
+
629
+
630
+
631
+
632
+
633
+
634
+
635
+
636
+
637
+
638
+
639
+
640
+
641
+
642
+
643
+
644
+
645
+
646
+
647
+
648
+
649
+
650
+
651
+
652
+
653
+
654
+
655
+
656
+
657
+
658
+
659
+
660
+
661
+
662
+
663
+
664
+
665
+
666
+
667
+
668
+
669
+
670
+
671
+
672
+
673
+
674
+
675
+
676
+
677
+
678
+
679
+
680
+
681
+
682
+
683
+
684
+
685
+
686
+
687
+
688
+
689
+
690
+
691
+
692
+
693
+
694
+
695
+
696
+
697
+
698
+
699
+
700
+
701
+
702
+
703
+
704
+
705
+
706
+
707
+
708
+
709
+
710
+
711
+
712
+
713
+
714
+
715
+
716
+
717
+
718
+
719
+
720
+
721
+
722
+
723
+
724
+
725
+
726
+
727
+
728
+
729
+
730
+
731
+
732
+
733
+
734
+
735
+
736
+
737
+ * @example
738
+ * // Check key existence
739
+ * const mm = new TreeMultiMap<number, string>();
740
+ * mm.add(1, 'a');
741
+ * console.log(mm.has(1)); // true;
742
+ * console.log(mm.has(2)); // false;
743
+ */
744
+ has(key: K): boolean {
745
+ this._validateKey(key);
746
+ return this.#core.has(key);
747
+ }
748
+
749
+ /**
750
+ * Live bucket reference (do not auto-delete key if bucket becomes empty via mutation).
751
+ * @remarks Time O(log n), Space O(1)
752
+
753
+
754
+
755
+
756
+
757
+
758
+
759
+
760
+
761
+
762
+
763
+
764
+
765
+
766
+
767
+
768
+
769
+
770
+
771
+
772
+
773
+
774
+
775
+
776
+
777
+
778
+
779
+
780
+
781
+
782
+
783
+
784
+
785
+
786
+
787
+
788
+
789
+
790
+
791
+
792
+
793
+
794
+
795
+
796
+
797
+
798
+
799
+
800
+
801
+
802
+
803
+
804
+
805
+
806
+
807
+
808
+
809
+
810
+
811
+
812
+
813
+
814
+
815
+
816
+
817
+
818
+
819
+
820
+
821
+
822
+
823
+
824
+
825
+
826
+
827
+
828
+
829
+
830
+
831
+
832
+
833
+
834
+
835
+
836
+
837
+
838
+
839
+
840
+
841
+
842
+
843
+
844
+
845
+
846
+
847
+
848
+
849
+
850
+
851
+
852
+
853
+
854
+
855
+
856
+
857
+
858
+
859
+
860
+
861
+
862
+
863
+
864
+
865
+
866
+
867
+
868
+
869
+
870
+
871
+
872
+
873
+
874
+
875
+
876
+
877
+
878
+
879
+
880
+
881
+
882
+
883
+
884
+
885
+
886
+
887
+
888
+
889
+
890
+
891
+
892
+
893
+
894
+
895
+
896
+
897
+
898
+
899
+
900
+
901
+
902
+
903
+
904
+
905
+
906
+
907
+
908
+
909
+
910
+
911
+
912
+
913
+
914
+
915
+
916
+
917
+
918
+
919
+
920
+
921
+
922
+
923
+
924
+
925
+
926
+
927
+
928
+
929
+
930
+
931
+
932
+
933
+
934
+
935
+
936
+
937
+
938
+
939
+
940
+
941
+
942
+
943
+
944
+
945
+
946
+
947
+
948
+ * @example
949
+ * // Get values for key
950
+ * const mm = new TreeMultiMap<number, string>();
951
+ * mm.add(1, 'a');
952
+ * mm.add(1, 'b');
953
+ * console.log(mm.get(1)); // ['a', 'b'];
954
+ */
955
+ get(key: K): V[] | undefined {
956
+ this._validateKey(key);
957
+ return this.#core.get(key);
958
+ }
959
+
960
+ /**
961
+ * Append a single value.
962
+ * @remarks Time O(log n), Space O(1)
963
+
964
+
965
+
966
+
967
+
968
+
969
+
970
+
971
+
972
+
973
+
974
+
975
+
976
+
977
+
978
+
979
+
980
+
981
+
982
+
983
+
984
+
985
+
986
+
987
+
988
+
989
+
990
+
991
+
992
+
993
+
994
+
995
+
996
+
997
+
998
+
999
+
1000
+
1001
+
1002
+
1003
+
1004
+
1005
+
1006
+
1007
+
1008
+
1009
+
1010
+
1011
+
1012
+
1013
+
1014
+
1015
+
1016
+
1017
+
1018
+
1019
+
1020
+
1021
+
1022
+
1023
+
1024
+
1025
+
1026
+
1027
+
1028
+
1029
+
1030
+
1031
+
1032
+
1033
+
1034
+
1035
+
1036
+
1037
+
1038
+
1039
+
1040
+
1041
+
1042
+
1043
+
1044
+
1045
+
1046
+
1047
+
1048
+
1049
+
1050
+
1051
+
1052
+
1053
+
1054
+
1055
+
1056
+
1057
+
1058
+
1059
+
1060
+
1061
+
1062
+
1063
+
1064
+
1065
+
1066
+
1067
+
1068
+
1069
+
1070
+
1071
+
1072
+
1073
+
1074
+
1075
+
1076
+
1077
+
1078
+
1079
+
1080
+
1081
+
1082
+
1083
+
1084
+
1085
+
1086
+
1087
+
1088
+
1089
+
1090
+
1091
+
1092
+
1093
+
1094
+
1095
+
1096
+
1097
+
1098
+
1099
+
1100
+
1101
+
1102
+
1103
+
1104
+
1105
+
1106
+
1107
+
1108
+
1109
+
1110
+
1111
+
1112
+
1113
+
1114
+
1115
+ * @example
1116
+ * // Add key-value pair
1117
+ * const mm = new TreeMultiMap<number, string>();
1118
+ * mm.add(1, 'a');
1119
+ * mm.add(1, 'b');
1120
+ * mm.add(2, 'c');
1121
+ * console.log(mm.get(1)); // ['a', 'b'];
1122
+ */
1123
+ add(key: K, value: V): boolean {
1124
+ this._validateKey(key);
1125
+ const bucket = this.#core.get(key);
1126
+ if (bucket) {
1127
+ bucket.push(value);
1128
+ return true;
1129
+ }
1130
+ return this.#core.set(key, [value]);
1131
+ }
1132
+
1133
+ /**
1134
+ * Alias for compatibility with existing TreeMultiMap semantics.
1135
+ * @remarks Time O(log n), Space O(1) for single value; O(log n + m) for bucket append
1136
+
1137
+
1138
+
1139
+
1140
+
1141
+
1142
+
1143
+
1144
+
1145
+
1146
+
1147
+
1148
+
1149
+
1150
+
1151
+
1152
+
1153
+
1154
+
1155
+
1156
+
1157
+
1158
+
1159
+
1160
+
1161
+
1162
+
1163
+
1164
+
1165
+
1166
+
1167
+
1168
+
1169
+
1170
+
1171
+
1172
+
1173
+
1174
+
1175
+
1176
+
1177
+
1178
+
1179
+
1180
+
1181
+
1182
+
1183
+
1184
+
1185
+
1186
+
1187
+
1188
+
1189
+
1190
+
1191
+
1192
+
1193
+
1194
+
1195
+
1196
+
1197
+
1198
+
1199
+
1200
+
1201
+
1202
+
1203
+
1204
+
1205
+
1206
+
1207
+
1208
+
1209
+
1210
+
1211
+
1212
+
1213
+
1214
+
1215
+
1216
+
1217
+
1218
+
1219
+
1220
+
1221
+
1222
+
1223
+
1224
+
1225
+
1226
+
1227
+
1228
+
1229
+
1230
+
1231
+
1232
+
1233
+
1234
+
1235
+
1236
+
1237
+
1238
+
1239
+
1240
+
1241
+
1242
+
1243
+
1244
+
1245
+
1246
+
1247
+
1248
+
1249
+
1250
+
1251
+
1252
+
1253
+
1254
+
1255
+
1256
+
1257
+
1258
+
1259
+
1260
+
1261
+
1262
+
1263
+
1264
+
1265
+
1266
+
1267
+
1268
+
1269
+
1270
+
1271
+
1272
+
1273
+
1274
+
1275
+
1276
+
1277
+
1278
+
1279
+
1280
+
1281
+
1282
+
1283
+
1284
+
1285
+
1286
+
1287
+
1288
+
1289
+
1290
+
1291
+
1292
+
1293
+
1294
+
1295
+
1296
+
1297
+
1298
+
1299
+
1300
+
1301
+
1302
+
1303
+
1304
+
1305
+
1306
+
1307
+
1308
+
1309
+
1310
+
1311
+
1312
+
1313
+
1314
+
1315
+
1316
+
1317
+
1318
+
1319
+
1320
+
1321
+
1322
+
1323
+
1324
+
1325
+
1326
+
1327
+
1328
+
1329
+
1330
+ * @example
1331
+ * // Set values for key
1332
+ * const mm = new TreeMultiMap<number, string>();
1333
+ * mm.set(1, 'a');
1334
+ * mm.set(1, 'b');
1335
+ * console.log(mm.get(1)); // ['a', 'b'];
1336
+ */
1337
+ set(entry: [K | null | undefined, V[] | undefined] | K | null | undefined, value?: V): boolean;
1338
+ set(key: K, value: V): boolean;
1339
+ set(entry: [K | null | undefined, V[] | undefined] | K | null | undefined, value?: V): boolean {
1340
+ if (entry === null || entry === undefined) return false;
1341
+ if (Array.isArray(entry)) {
1342
+ const [k, bucket] = entry;
1343
+ if (k === null || k === undefined) return false;
1344
+ if (value !== undefined) return this.add(k as K, value);
1345
+ if (bucket === undefined) {
1346
+ // ensure key exists
1347
+ return this.#core.set(k as K, [] as V[]);
1348
+ }
1349
+ // append bucket
1350
+ const existing = this.#core.get(k as K);
1351
+ if (existing) {
1352
+ existing.push(...bucket);
1353
+ return true;
1354
+ }
1355
+ return this.#core.set(k as K, [...bucket] as V[]);
1356
+ }
1357
+ // key-only or key+value
1358
+ if (value !== undefined) return this.add(entry as K, value);
1359
+ return this.#core.set(entry as K, [] as V[]);
1360
+ }
1361
+
1362
+ /**
1363
+ * Deletes a key and its entire bucket.
1364
+ * @remarks Time O(log n), Space O(1)
1365
+
1366
+
1367
+
1368
+
1369
+
1370
+
1371
+
1372
+
1373
+
1374
+
1375
+
1376
+
1377
+
1378
+
1379
+
1380
+
1381
+
1382
+
1383
+
1384
+
1385
+
1386
+
1387
+
1388
+
1389
+
1390
+
1391
+
1392
+
1393
+
1394
+
1395
+
1396
+
1397
+
1398
+
1399
+
1400
+
1401
+
1402
+
1403
+
1404
+
1405
+
1406
+
1407
+
1408
+
1409
+
1410
+
1411
+
1412
+
1413
+
1414
+
1415
+
1416
+
1417
+
1418
+
1419
+
1420
+
1421
+
1422
+
1423
+
1424
+
1425
+
1426
+
1427
+
1428
+
1429
+
1430
+
1431
+
1432
+
1433
+
1434
+
1435
+
1436
+
1437
+
1438
+
1439
+
1440
+
1441
+
1442
+
1443
+
1444
+
1445
+
1446
+
1447
+
1448
+
1449
+
1450
+
1451
+
1452
+
1453
+
1454
+
1455
+
1456
+
1457
+
1458
+
1459
+
1460
+
1461
+
1462
+
1463
+
1464
+
1465
+
1466
+
1467
+
1468
+
1469
+
1470
+
1471
+
1472
+
1473
+
1474
+
1475
+
1476
+
1477
+
1478
+
1479
+
1480
+
1481
+
1482
+
1483
+
1484
+
1485
+
1486
+
1487
+
1488
+
1489
+
1490
+
1491
+
1492
+
1493
+
1494
+
1495
+
1496
+
1497
+
1498
+
1499
+
1500
+
1501
+
1502
+
1503
+
1504
+
1505
+
1506
+
1507
+
1508
+
1509
+
1510
+
1511
+
1512
+
1513
+
1514
+
1515
+
1516
+
1517
+
1518
+
1519
+
1520
+
1521
+
1522
+
1523
+
1524
+
1525
+
1526
+
1527
+
1528
+
1529
+
1530
+
1531
+
1532
+
1533
+
1534
+
1535
+
1536
+
1537
+
1538
+
1539
+
1540
+
1541
+
1542
+
1543
+
1544
+
1545
+
1546
+
1547
+
1548
+
1549
+
1550
+
1551
+
1552
+
1553
+
1554
+
1555
+
1556
+
1557
+
1558
+
1559
+
1560
+
1561
+ * @example
1562
+ * // Remove key
1563
+ * const mm = new TreeMultiMap<number, string>();
1564
+ * mm.add(1, 'a');
1565
+ * mm.add(2, 'b');
1566
+ * mm.delete(1);
1567
+ * console.log(mm.has(1)); // false;
1568
+ */
1569
+ delete(key: K): boolean {
1570
+ this._validateKey(key);
1571
+ return this.#core.delete(key).length > 0;
1572
+ }
1573
+
1574
+ /**
1575
+ * Check if a specific value exists in a key's bucket.
1576
+ * @remarks Time O(log n + m), Space O(1) where m is bucket size
1577
+
1578
+
1579
+
1580
+
1581
+
1582
+
1583
+
1584
+
1585
+
1586
+
1587
+
1588
+
1589
+
1590
+
1591
+
1592
+
1593
+
1594
+
1595
+
1596
+
1597
+
1598
+
1599
+
1600
+
1601
+
1602
+
1603
+ * @example
1604
+ * // Check specific key-value
1605
+ * const mm = new TreeMultiMap<number, string>();
1606
+ * mm.add(1, 'a');
1607
+ * console.log(mm.hasEntry(1, 'a')); // true;
1608
+ * console.log(mm.hasEntry(1, 'z')); // false;
1609
+ */
1610
+ hasEntry(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): boolean {
1611
+ const bucket = this.get(key);
1612
+ if (!Array.isArray(bucket)) return false;
1613
+ return bucket.some(v => eq(v, value));
1614
+ }
1615
+
1616
+ /**
1617
+ * Delete a single occurrence of a value from a key's bucket.
1618
+ * @remarks Time O(log n + m), Space O(1) where m is bucket size
1619
+
1620
+
1621
+
1622
+
1623
+
1624
+
1625
+
1626
+
1627
+
1628
+
1629
+
1630
+
1631
+
1632
+
1633
+
1634
+
1635
+
1636
+
1637
+
1638
+
1639
+
1640
+
1641
+
1642
+
1643
+
1644
+
1645
+ * @example
1646
+ * // Delete specific value
1647
+ * const mm = new TreeMultiMap<number, string>();
1648
+ * mm.add(1, 'a');
1649
+ * mm.add(1, 'b');
1650
+ * mm.deleteValue(1, 'a');
1651
+ * console.log(mm.get(1)); // ['b'];
1652
+ */
1653
+ deleteValue(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): boolean {
1654
+ const bucket = this.get(key);
1655
+ if (!Array.isArray(bucket)) return false;
1656
+ const idx = bucket.findIndex(v => eq(v, value));
1657
+ if (idx === -1) return false;
1658
+ bucket.splice(idx, 1);
1659
+ if (bucket.length === 0) this.delete(key);
1660
+ return true;
1661
+ }
1662
+
1663
+ /**
1664
+ * Delete all occurrences of a value from a key's bucket.
1665
+ * @remarks Time O(log n + m), Space O(1) where m is bucket size
1666
+
1667
+
1668
+
1669
+
1670
+
1671
+
1672
+
1673
+
1674
+
1675
+
1676
+
1677
+
1678
+
1679
+
1680
+
1681
+
1682
+
1683
+
1684
+
1685
+
1686
+
1687
+
1688
+
1689
+
1690
+
1691
+
1692
+ * @example
1693
+ * // Delete all matching values
1694
+ * const mm = new TreeMultiMap<number, string>();
1695
+ * mm.add(1, 'a');
1696
+ * mm.add(1, 'a');
1697
+ * mm.add(1, 'b');
1698
+ * const count = mm.deleteValues(1, 'a');
1699
+ * console.log(count); // 2;
1700
+ */
1701
+ deleteValues(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): number {
1702
+ const bucket = this.get(key);
1703
+ if (!Array.isArray(bucket) || bucket.length === 0) return 0;
1704
+ let removed = 0;
1705
+ for (let i = bucket.length - 1; i >= 0; i--) {
1706
+ if (eq(bucket[i] as V, value)) {
1707
+ bucket.splice(i, 1);
1708
+ removed++;
1709
+ }
1710
+ }
1711
+ if (bucket.length === 0 && removed > 0) this.delete(key);
700
1712
  return removed;
701
1713
  }
702
1714
 
703
- // ---- iteration (bucket view) ----
704
-
1715
+ // ---- iteration (bucket view) ----
1716
+
1717
+ /**
1718
+ * Iterates over all entries as [key, bucket] pairs.
1719
+ * @remarks Time O(n), Space O(1)
1720
+ */
1721
+ *[Symbol.iterator](): Iterator<[K, V[]]> {
1722
+ for (const [k, v] of this.#core) {
1723
+ // core always stores buckets, but guard anyway
1724
+ yield [k, v ?? /* istanbul ignore next */ ([] as V[])];
1725
+ }
1726
+ }
1727
+
1728
+ /**
1729
+ * Iterates over all keys.
1730
+ * @remarks Time O(n), Space O(1)
1731
+
1732
+
1733
+
1734
+
1735
+
1736
+
1737
+
1738
+
1739
+
1740
+
1741
+
1742
+
1743
+
1744
+
1745
+
1746
+
1747
+
1748
+
1749
+
1750
+
1751
+
1752
+
1753
+
1754
+
1755
+
1756
+
1757
+
1758
+
1759
+
1760
+
1761
+
1762
+
1763
+
1764
+
1765
+
1766
+
1767
+
1768
+
1769
+
1770
+
1771
+
1772
+
1773
+
1774
+
1775
+
1776
+
1777
+
1778
+
1779
+
1780
+
1781
+
1782
+
1783
+
1784
+
1785
+
1786
+
1787
+
1788
+
1789
+
1790
+
1791
+
1792
+
1793
+
1794
+
1795
+
1796
+
1797
+
1798
+
1799
+
1800
+
1801
+
1802
+
1803
+
1804
+
1805
+
1806
+
1807
+
1808
+
1809
+
1810
+
1811
+
1812
+
1813
+
1814
+
1815
+
1816
+
1817
+
1818
+
1819
+
1820
+
1821
+
1822
+
1823
+
1824
+
1825
+
1826
+
1827
+
1828
+
1829
+
1830
+
1831
+
1832
+
1833
+
1834
+
1835
+
1836
+
1837
+
1838
+
1839
+
1840
+
1841
+
1842
+
1843
+
1844
+
1845
+
1846
+
1847
+
1848
+
1849
+
1850
+
1851
+
1852
+
1853
+
1854
+
1855
+
1856
+
1857
+
1858
+
1859
+
1860
+
1861
+
1862
+
1863
+
1864
+
1865
+
1866
+
1867
+
1868
+
1869
+
1870
+
1871
+
1872
+
1873
+
1874
+
1875
+
1876
+
1877
+
1878
+
1879
+
1880
+
1881
+
1882
+
1883
+
1884
+
1885
+
1886
+
1887
+
1888
+
1889
+ * @example
1890
+ * // Iterate keys
1891
+ * const mm = new TreeMultiMap<number, string>();
1892
+ * mm.add(3, 'c');
1893
+ * mm.add(1, 'a');
1894
+ * console.log([...mm.keys()]); // [1, 3];
1895
+ */
1896
+ *keys(): IterableIterator<K> {
1897
+ yield* this.#core.keys();
1898
+ }
1899
+
1900
+ /**
1901
+ * Iterates over all buckets.
1902
+ * @remarks Time O(n), Space O(1)
1903
+
1904
+
1905
+
1906
+
1907
+
1908
+
1909
+
1910
+
1911
+
1912
+
1913
+
1914
+
1915
+
1916
+
1917
+
1918
+
1919
+
1920
+
1921
+
1922
+
1923
+
1924
+
1925
+
1926
+
1927
+
1928
+
1929
+
1930
+
1931
+
1932
+
1933
+
1934
+
1935
+
1936
+
1937
+
1938
+
1939
+
1940
+
1941
+
1942
+
1943
+
1944
+
1945
+
1946
+
1947
+
1948
+
1949
+
1950
+
1951
+
1952
+
1953
+
1954
+
1955
+
1956
+
1957
+
1958
+
1959
+
1960
+
1961
+
1962
+
1963
+
1964
+
1965
+
1966
+
1967
+
1968
+
1969
+
1970
+
1971
+
1972
+
1973
+
1974
+
1975
+
1976
+
1977
+
1978
+
1979
+
1980
+
1981
+
1982
+
1983
+
1984
+
1985
+
1986
+
1987
+
1988
+
1989
+
1990
+
1991
+
1992
+
1993
+
1994
+
1995
+
1996
+
1997
+
1998
+
1999
+
2000
+
2001
+
2002
+
2003
+
2004
+
2005
+
2006
+
2007
+
2008
+
2009
+
2010
+
2011
+
2012
+
2013
+
2014
+
2015
+
2016
+
2017
+
2018
+
2019
+
2020
+
2021
+
2022
+
2023
+
2024
+
2025
+
2026
+
2027
+
2028
+
2029
+
2030
+
2031
+
2032
+
2033
+
2034
+
2035
+
2036
+
2037
+
2038
+
2039
+
2040
+
2041
+
2042
+
2043
+
2044
+
2045
+
2046
+
2047
+
2048
+
2049
+
2050
+
2051
+
2052
+
2053
+
2054
+
2055
+
2056
+
2057
+
2058
+
2059
+
2060
+
2061
+ * @example
2062
+ * // Iterate value arrays
2063
+ * const mm = new TreeMultiMap<number, string>();
2064
+ * mm.add(1, 'a');
2065
+ * mm.add(1, 'b');
2066
+ * console.log([...mm.values()]); // [['a', 'b']];
2067
+ */
2068
+ *values(): IterableIterator<V[]> {
2069
+ for (const [, bucket] of this) yield bucket;
2070
+ }
2071
+
2072
+ // ---- entry-flat views ----
2073
+
2074
+ /**
2075
+ * Iterates over all entries for a specific key.
2076
+ * @remarks Time O(log n + m), Space O(1) where m is bucket size
2077
+
2078
+
2079
+
2080
+
2081
+
2082
+
2083
+
2084
+
2085
+
2086
+
2087
+
2088
+
2089
+
2090
+
2091
+
2092
+
2093
+
2094
+
2095
+
2096
+
2097
+
2098
+
2099
+
2100
+
2101
+
2102
+
2103
+ * @example
2104
+ * // Get entries for key
2105
+ * const mm = new TreeMultiMap<number, string>();
2106
+ * mm.add(1, 'a');
2107
+ * mm.add(1, 'b');
2108
+ * console.log([...mm.entriesOf(1)]); // [[1, 'a'], [1, 'b']];
2109
+ */
2110
+ *entriesOf(key: K): IterableIterator<[K, V]> {
2111
+ const bucket = this.get(key);
2112
+ if (!Array.isArray(bucket)) return;
2113
+ for (const v of bucket) yield [key, v];
2114
+ }
2115
+
2116
+ /**
2117
+ * Iterates over all values for a specific key.
2118
+ * @remarks Time O(log n + m), Space O(1) where m is bucket size
2119
+
2120
+
2121
+
2122
+
2123
+
2124
+
2125
+
2126
+
2127
+
2128
+
2129
+
2130
+
2131
+
2132
+
2133
+
2134
+
2135
+
2136
+
2137
+
2138
+
2139
+
2140
+
2141
+
2142
+
2143
+
2144
+
2145
+ * @example
2146
+ * // Get flat values for key
2147
+ * const mm = new TreeMultiMap<number, string>();
2148
+ * mm.add(1, 'a');
2149
+ * mm.add(1, 'b');
2150
+ * console.log([...mm.valuesOf(1)]); // ['a', 'b'];
2151
+ */
2152
+ *valuesOf(key: K): IterableIterator<V> {
2153
+ const bucket = this.get(key);
2154
+ if (!Array.isArray(bucket)) return;
2155
+ yield* bucket;
2156
+ }
2157
+
2158
+ /**
2159
+ * Iterates over all [key, value] pairs (flattened from buckets).
2160
+ * @remarks Time O(T), Space O(1) where T is totalSize
2161
+
2162
+
2163
+
2164
+
2165
+
2166
+
2167
+
2168
+
2169
+
2170
+
2171
+
2172
+
2173
+
2174
+
2175
+
2176
+
2177
+
2178
+
2179
+
2180
+
2181
+
2182
+
2183
+
2184
+
2185
+
2186
+
2187
+ * @example
2188
+ * // All key-value pairs flattened
2189
+ * const mm = new TreeMultiMap<number, string>();
2190
+ * mm.add(1, 'a');
2191
+ * mm.add(1, 'b');
2192
+ * mm.add(2, 'c');
2193
+ * console.log([...mm.flatEntries()]); // [[1, 'a'], [1, 'b'], [2, 'c']];
2194
+ */
2195
+ *flatEntries(): IterableIterator<[K, V]> {
2196
+ for (const [k, bucket] of this) {
2197
+ for (const v of bucket) yield [k, v];
2198
+ }
2199
+ }
2200
+
2201
+ // ━━━ Navigable methods (return [K, V[]] | undefined) ━━━
2202
+
2203
+ /**
2204
+ * Returns the entry with the smallest key.
2205
+ * @remarks Time O(log n), Space O(1)
2206
+
2207
+
2208
+
2209
+
2210
+
2211
+
2212
+
2213
+
2214
+
2215
+
2216
+
2217
+
2218
+
2219
+
2220
+
2221
+
2222
+
2223
+
2224
+
2225
+
2226
+
2227
+
2228
+
2229
+
2230
+
2231
+
2232
+
2233
+
2234
+
2235
+
2236
+
2237
+
2238
+
2239
+
2240
+
2241
+
2242
+
2243
+
2244
+
2245
+
2246
+
2247
+
2248
+
2249
+
2250
+
2251
+
2252
+
2253
+
2254
+
2255
+
2256
+
2257
+
2258
+
2259
+
2260
+
2261
+
2262
+
2263
+
2264
+
2265
+
2266
+
2267
+
2268
+ * @example
2269
+ * // First entry
2270
+ * const mm = new TreeMultiMap<number, string>();
2271
+ * mm.add(3, 'c');
2272
+ * mm.add(1, 'a');
2273
+ * console.log(mm.first()?.[0]); // 1;
2274
+ */
2275
+ first(): [K, V[]] | undefined {
2276
+ const k = this.#core.getLeftMost();
2277
+ if (k === undefined) return undefined;
2278
+ const b = this.get(k);
2279
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
2280
+ }
2281
+
2282
+ /**
2283
+ * Returns the entry with the largest key.
2284
+ * @remarks Time O(log n), Space O(1)
2285
+
2286
+
2287
+
2288
+
2289
+
2290
+
2291
+
2292
+
2293
+
2294
+
2295
+
2296
+
2297
+
2298
+
2299
+
2300
+
2301
+
2302
+
2303
+
2304
+
2305
+
2306
+
2307
+
2308
+
2309
+
2310
+
2311
+
2312
+
2313
+
2314
+
2315
+
2316
+
2317
+
2318
+
2319
+
2320
+
2321
+
2322
+
2323
+
2324
+
2325
+
2326
+
2327
+
2328
+
2329
+
2330
+
2331
+
2332
+
2333
+
2334
+
2335
+
2336
+
2337
+
2338
+
2339
+
2340
+
2341
+
2342
+
2343
+
2344
+
2345
+
2346
+
2347
+ * @example
2348
+ * // Last entry
2349
+ * const mm = new TreeMultiMap<number, string>();
2350
+ * mm.add(1, 'a');
2351
+ * mm.add(3, 'c');
2352
+ * console.log(mm.last()?.[0]); // 3;
2353
+ */
2354
+ last(): [K, V[]] | undefined {
2355
+ const k = this.#core.getRightMost();
2356
+ if (k === undefined) return undefined;
2357
+ const b = this.get(k);
2358
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
2359
+ }
2360
+
2361
+ /**
2362
+ * Removes and returns the entry with the smallest key.
2363
+ * @remarks Time O(log n), Space O(1)
2364
+
2365
+
2366
+
2367
+
2368
+
2369
+
2370
+
2371
+
2372
+
2373
+
2374
+
2375
+
2376
+
2377
+
2378
+
2379
+
2380
+
2381
+
2382
+
2383
+
2384
+
2385
+
2386
+
2387
+
2388
+
2389
+
2390
+
2391
+ * @example
2392
+ * // Remove and return first
2393
+ * const mm = new TreeMultiMap<number, string>();
2394
+ * mm.add(2, 'b');
2395
+ * mm.add(1, 'a');
2396
+ * const first = mm.pollFirst();
2397
+ * console.log(first?.[0]); // 1;
2398
+ * console.log(mm.has(1)); // false;
2399
+ */
2400
+ pollFirst(): [K, V[]] | undefined {
2401
+ const e = this.first();
2402
+ if (!e) return undefined;
2403
+ this.delete(e[0]);
2404
+ return e;
2405
+ }
2406
+
2407
+ /**
2408
+ * Removes and returns the entry with the largest key.
2409
+ * @remarks Time O(log n), Space O(1)
2410
+
2411
+
2412
+
2413
+
2414
+
2415
+
2416
+
2417
+
2418
+
2419
+
2420
+
2421
+
2422
+
2423
+
2424
+
2425
+
2426
+
2427
+
2428
+
2429
+
2430
+
2431
+
2432
+
2433
+
2434
+
2435
+
2436
+
2437
+ * @example
2438
+ * // Remove and return last
2439
+ * const mm = new TreeMultiMap<number, string>();
2440
+ * mm.add(1, 'a');
2441
+ * mm.add(3, 'c');
2442
+ * const last = mm.pollLast();
2443
+ * console.log(last?.[0]); // 3;
2444
+ */
2445
+ pollLast(): [K, V[]] | undefined {
2446
+ const e = this.last();
2447
+ if (!e) return undefined;
2448
+ this.delete(e[0]);
2449
+ return e;
2450
+ }
2451
+
2452
+ /**
2453
+ * Returns the entry with the smallest key >= given key.
2454
+ * @remarks Time O(log n), Space O(1)
2455
+
2456
+
2457
+
2458
+
2459
+
2460
+
2461
+
2462
+
2463
+
2464
+
2465
+
2466
+
2467
+
2468
+
2469
+
2470
+
2471
+
2472
+
2473
+
2474
+
2475
+
2476
+
2477
+
2478
+
2479
+
2480
+
2481
+
2482
+
2483
+
2484
+
2485
+
2486
+
2487
+
2488
+
2489
+
2490
+
2491
+
2492
+
2493
+
2494
+
2495
+
2496
+
2497
+
2498
+
2499
+
2500
+
2501
+
2502
+
2503
+
2504
+
2505
+
2506
+
2507
+
2508
+
2509
+
2510
+
2511
+
2512
+
2513
+
2514
+
2515
+
2516
+
2517
+
2518
+
2519
+
2520
+
2521
+
2522
+
2523
+
2524
+
2525
+
2526
+
2527
+
2528
+
2529
+
2530
+
2531
+
2532
+
2533
+
2534
+
2535
+
2536
+
2537
+
2538
+
2539
+
2540
+
2541
+
2542
+
2543
+
2544
+
2545
+
2546
+
2547
+
2548
+
2549
+
2550
+
2551
+
2552
+
2553
+
2554
+
2555
+
2556
+
2557
+
2558
+
2559
+
2560
+
2561
+
2562
+
2563
+
2564
+
2565
+
2566
+
2567
+
2568
+
2569
+
2570
+
2571
+
2572
+
2573
+
2574
+
2575
+
2576
+
2577
+
2578
+
2579
+
2580
+
2581
+
2582
+
2583
+
2584
+
2585
+
2586
+
2587
+
2588
+
2589
+
2590
+
2591
+
2592
+
2593
+
2594
+
2595
+
2596
+
2597
+
2598
+
2599
+
2600
+
2601
+
2602
+
2603
+
2604
+
2605
+
2606
+
2607
+
2608
+
2609
+
2610
+
2611
+
2612
+
2613
+
2614
+
2615
+
2616
+ * @example
2617
+ * // Least key ≥ target
2618
+ * const mm = new TreeMultiMap<number, string>();
2619
+ * mm.add(10, 'a');
2620
+ * mm.add(20, 'b');
2621
+ * mm.add(30, 'c');
2622
+ * console.log(mm.ceiling(15)?.[0]); // 20;
2623
+ */
2624
+ ceiling(key: K): [K, V[]] | undefined {
2625
+ this._validateKey(key);
2626
+ const k = this.#core.ceiling(key);
2627
+ if (k === undefined) return undefined;
2628
+ const b = this.get(k);
2629
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
2630
+ }
2631
+
2632
+ /**
2633
+ * Returns the entry with the largest key <= given key.
2634
+ * @remarks Time O(log n), Space O(1)
2635
+
2636
+
2637
+
2638
+
2639
+
2640
+
2641
+
2642
+
2643
+
2644
+
2645
+
2646
+
2647
+
2648
+
2649
+
2650
+
2651
+
2652
+
2653
+
2654
+
2655
+
2656
+
2657
+
2658
+
2659
+
2660
+
2661
+
2662
+
2663
+
2664
+
2665
+
2666
+
2667
+
2668
+
2669
+
2670
+
2671
+
2672
+
2673
+
2674
+
2675
+
2676
+
2677
+
2678
+
2679
+
2680
+
2681
+
2682
+
2683
+
2684
+
2685
+
2686
+
2687
+
2688
+
2689
+
2690
+
2691
+
2692
+
2693
+
2694
+
2695
+
2696
+
2697
+
2698
+
2699
+
2700
+
2701
+
2702
+
2703
+
2704
+
2705
+
2706
+
2707
+
2708
+
2709
+
2710
+
2711
+
2712
+
2713
+
2714
+
2715
+
2716
+
2717
+
2718
+
2719
+
2720
+
2721
+
2722
+
2723
+
2724
+
2725
+
2726
+
2727
+
2728
+
2729
+
2730
+
2731
+
2732
+
2733
+
2734
+
2735
+
2736
+
2737
+
2738
+
2739
+
2740
+
2741
+
2742
+
2743
+
2744
+
2745
+
2746
+
2747
+
2748
+
2749
+
2750
+
2751
+
2752
+
2753
+
2754
+
2755
+
2756
+
2757
+
2758
+
2759
+
2760
+
2761
+
2762
+
2763
+
2764
+
2765
+
2766
+
2767
+
2768
+
2769
+
2770
+
2771
+
2772
+
2773
+
2774
+
2775
+
2776
+
2777
+
2778
+
2779
+
2780
+
2781
+
2782
+
2783
+
2784
+
2785
+
2786
+
2787
+
2788
+
2789
+
2790
+
2791
+
2792
+
2793
+
2794
+
2795
+
2796
+ * @example
2797
+ * // Greatest key ≤ target
2798
+ * const mm = new TreeMultiMap<number, string>();
2799
+ * mm.add(10, 'a');
2800
+ * mm.add(20, 'b');
2801
+ * mm.add(30, 'c');
2802
+ * console.log(mm.floor(25)?.[0]); // 20;
2803
+ */
2804
+ floor(key: K): [K, V[]] | undefined {
2805
+ this._validateKey(key);
2806
+ const k = this.#core.floor(key);
2807
+ if (k === undefined) return undefined;
2808
+ const b = this.get(k);
2809
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
2810
+ }
2811
+
2812
+ /**
2813
+ * Returns the entry with the smallest key > given key.
2814
+ * @remarks Time O(log n), Space O(1)
2815
+
2816
+
2817
+
2818
+
2819
+
2820
+
2821
+
2822
+
2823
+
2824
+
2825
+
2826
+
2827
+
2828
+
2829
+
2830
+
2831
+
2832
+
2833
+
2834
+
2835
+
2836
+
2837
+
2838
+
2839
+
2840
+
2841
+
2842
+
2843
+
2844
+
2845
+
2846
+
2847
+
2848
+
2849
+
2850
+
2851
+
2852
+
2853
+
2854
+
2855
+
2856
+
2857
+
2858
+
2859
+
2860
+
2861
+
2862
+
2863
+
2864
+
2865
+
2866
+
2867
+
2868
+
2869
+
2870
+
2871
+
2872
+
2873
+
2874
+
2875
+
2876
+
2877
+
2878
+
2879
+
2880
+
2881
+
2882
+
2883
+
2884
+
2885
+
2886
+
2887
+
2888
+
2889
+
2890
+
2891
+
2892
+
2893
+
2894
+
2895
+
2896
+
2897
+
2898
+
2899
+
2900
+
2901
+
2902
+
2903
+
2904
+
2905
+
2906
+
2907
+
2908
+
2909
+
2910
+
2911
+
2912
+
2913
+
2914
+
2915
+
2916
+
2917
+
2918
+
2919
+
2920
+
2921
+
2922
+
2923
+
2924
+
2925
+
2926
+
2927
+
2928
+
2929
+
2930
+
2931
+
2932
+
2933
+
2934
+
2935
+
2936
+
2937
+
2938
+
2939
+
2940
+
2941
+ * @example
2942
+ * // Least key > target
2943
+ * const mm = new TreeMultiMap<number, string>();
2944
+ * mm.add(10, 'a');
2945
+ * mm.add(20, 'b');
2946
+ * console.log(mm.higher(10)?.[0]); // 20;
2947
+ */
2948
+ higher(key: K): [K, V[]] | undefined {
2949
+ this._validateKey(key);
2950
+ const k = this.#core.higher(key);
2951
+ if (k === undefined) return undefined;
2952
+ const b = this.get(k);
2953
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
2954
+ }
2955
+
2956
+ /**
2957
+ * Returns the entry with the largest key < given key.
2958
+ * @remarks Time O(log n), Space O(1)
2959
+
2960
+
2961
+
2962
+
2963
+
2964
+
2965
+
2966
+
2967
+
2968
+
2969
+
2970
+
2971
+
2972
+
2973
+
2974
+
2975
+
2976
+
2977
+
2978
+
2979
+
2980
+
2981
+
2982
+
2983
+
2984
+
2985
+
2986
+
2987
+
2988
+
2989
+
2990
+
2991
+
2992
+
2993
+
2994
+
2995
+
2996
+
2997
+
2998
+
2999
+
3000
+
3001
+
3002
+
3003
+
3004
+
3005
+
3006
+
3007
+
3008
+
3009
+
3010
+
3011
+
3012
+
3013
+
3014
+
3015
+
3016
+
3017
+
3018
+
3019
+
3020
+
3021
+
3022
+
3023
+
3024
+
3025
+
3026
+
3027
+
3028
+
3029
+
3030
+
3031
+
3032
+
3033
+
3034
+
3035
+
3036
+
3037
+
3038
+
3039
+
3040
+
3041
+
3042
+
3043
+
3044
+
3045
+
3046
+
3047
+
3048
+
3049
+
3050
+
3051
+
3052
+
3053
+
3054
+
3055
+
3056
+
3057
+
3058
+
3059
+
3060
+
3061
+
3062
+
3063
+
3064
+
3065
+
3066
+
3067
+
3068
+
3069
+
3070
+
3071
+
3072
+
3073
+
3074
+
3075
+
3076
+
3077
+
3078
+
3079
+
3080
+
3081
+
3082
+
3083
+
3084
+
3085
+ * @example
3086
+ * // Greatest key < target
3087
+ * const mm = new TreeMultiMap<number, string>();
3088
+ * mm.add(10, 'a');
3089
+ * mm.add(20, 'b');
3090
+ * console.log(mm.lower(20)?.[0]); // 10;
3091
+ */
3092
+ lower(key: K): [K, V[]] | undefined {
3093
+ this._validateKey(key);
3094
+ const k = this.#core.lower(key);
3095
+ if (k === undefined) return undefined;
3096
+ const b = this.get(k);
3097
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
3098
+ }
3099
+
3100
+ // ━━━ Tree utilities ━━━
3101
+
3102
+ /**
3103
+ * Prints the internal tree structure (for debugging).
3104
+ * @remarks Time O(n), Space O(n)
3105
+
3106
+
3107
+
3108
+
3109
+
3110
+
3111
+
3112
+
3113
+
3114
+
3115
+
3116
+
3117
+
3118
+
3119
+
3120
+
3121
+
3122
+
3123
+
3124
+
3125
+
3126
+
3127
+
3128
+
3129
+
3130
+
3131
+
3132
+
3133
+
3134
+
3135
+
3136
+
3137
+
3138
+
3139
+
3140
+
3141
+
3142
+
3143
+
3144
+
3145
+
3146
+
3147
+
3148
+
3149
+
3150
+
3151
+
3152
+
3153
+
3154
+
3155
+
3156
+
3157
+
3158
+
3159
+
3160
+
3161
+
3162
+
3163
+
3164
+
3165
+
3166
+
3167
+
3168
+
3169
+
3170
+
3171
+
3172
+
3173
+
3174
+
3175
+
3176
+
3177
+
3178
+
3179
+
3180
+
3181
+
3182
+
3183
+
3184
+
3185
+
3186
+
3187
+
3188
+
3189
+
3190
+
3191
+
3192
+
3193
+
3194
+
3195
+
3196
+
3197
+
3198
+
3199
+
3200
+
3201
+
3202
+
3203
+
3204
+
3205
+
3206
+
3207
+
3208
+
3209
+
3210
+
3211
+
3212
+
3213
+
3214
+
3215
+
3216
+
3217
+
3218
+
3219
+
3220
+
3221
+
3222
+
3223
+
3224
+
3225
+
3226
+
3227
+
3228
+
3229
+
3230
+
3231
+
3232
+
3233
+
3234
+
3235
+
3236
+
3237
+
3238
+
3239
+
3240
+
3241
+
3242
+
3243
+
3244
+
3245
+
3246
+
3247
+
3248
+
3249
+
3250
+
3251
+
3252
+
3253
+
3254
+
3255
+
3256
+
3257
+
3258
+
3259
+
3260
+
3261
+
3262
+
3263
+ * @example
3264
+ * // Display tree
3265
+ * const mm = new TreeMultiMap<number, string>();
3266
+ * mm.add(1, 'a');
3267
+ * expect(() => mm.print()).not.toThrow();
3268
+ */
3269
+ print(): void {
3270
+ this.#core.print();
3271
+ }
3272
+
3273
+ /**
3274
+ * Executes a callback for each entry.
3275
+ * @remarks Time O(n), Space O(1)
3276
+
3277
+
3278
+
3279
+
3280
+
3281
+
3282
+
3283
+
3284
+
3285
+
3286
+
3287
+
3288
+
3289
+
3290
+
3291
+
3292
+
3293
+
3294
+
3295
+
3296
+
3297
+
3298
+
3299
+
3300
+
3301
+
3302
+
3303
+
3304
+
3305
+
3306
+
3307
+
3308
+
3309
+
3310
+
3311
+
3312
+
3313
+
3314
+
3315
+
3316
+
3317
+
3318
+
3319
+
3320
+
3321
+
3322
+
3323
+
3324
+
3325
+
3326
+
3327
+
3328
+
3329
+
3330
+
3331
+
3332
+
3333
+
3334
+
3335
+
3336
+
3337
+
3338
+
3339
+
3340
+
3341
+
3342
+
3343
+
3344
+
3345
+
3346
+
3347
+
3348
+
3349
+
3350
+
3351
+
3352
+
3353
+
3354
+
3355
+
3356
+
3357
+
3358
+
3359
+
3360
+
3361
+
3362
+
3363
+
3364
+
3365
+
3366
+
3367
+
3368
+
3369
+
3370
+
3371
+
3372
+
3373
+
3374
+
3375
+
3376
+
3377
+
3378
+
3379
+
3380
+
3381
+
3382
+
3383
+
3384
+
3385
+
3386
+
3387
+
3388
+
3389
+
3390
+
3391
+
3392
+
3393
+
3394
+
3395
+
3396
+
3397
+
3398
+
3399
+
3400
+
3401
+
3402
+
3403
+
3404
+
3405
+
3406
+
3407
+
3408
+
3409
+
3410
+
3411
+
3412
+
3413
+
3414
+
3415
+
3416
+
3417
+
3418
+
3419
+
3420
+
3421
+
3422
+
3423
+
3424
+
3425
+
3426
+
3427
+
3428
+
3429
+
3430
+
3431
+
3432
+
3433
+
3434
+ * @example
3435
+ * // Iterate entries
3436
+ * const mm = new TreeMultiMap<number, string>();
3437
+ * mm.add(1, 'a');
3438
+ * mm.add(2, 'b');
3439
+ * const keys: number[] = [];
3440
+ * mm.forEach((v, k) => keys.push(k));
3441
+ * console.log(keys); // [1, 2];
3442
+ */
3443
+ forEach(callback: (value: V[], key: K, map: this) => void): void {
3444
+ for (const [k, v] of this) {
3445
+ callback(v, k, this);
3446
+ }
3447
+ }
3448
+
705
3449
  /**
706
- * Iterates over all entries as [key, bucket] pairs.
707
- * @remarks Time O(n), Space O(1)
3450
+ * Creates a new map with entries that pass the predicate.
3451
+ * @remarks Time O(n), Space O(n)
3452
+
3453
+
3454
+
3455
+
3456
+
3457
+
3458
+
3459
+
3460
+
3461
+
3462
+
3463
+
3464
+
3465
+
3466
+
3467
+
3468
+
3469
+
3470
+
3471
+
3472
+
3473
+
3474
+
3475
+
3476
+
3477
+
3478
+
3479
+
3480
+
3481
+
3482
+
3483
+
3484
+
3485
+
3486
+
3487
+
3488
+
3489
+
3490
+
3491
+
3492
+
3493
+
3494
+
3495
+
3496
+
3497
+
3498
+
3499
+
3500
+
3501
+
3502
+
3503
+
3504
+
3505
+
3506
+
3507
+
3508
+
3509
+
3510
+
3511
+
3512
+
3513
+
3514
+
3515
+
3516
+
3517
+
3518
+
3519
+
3520
+
3521
+
3522
+
3523
+
3524
+
3525
+
3526
+
3527
+
3528
+
3529
+
3530
+
3531
+
3532
+
3533
+
3534
+
3535
+
3536
+
3537
+
3538
+
3539
+
3540
+
3541
+
3542
+
3543
+
3544
+
3545
+
3546
+
3547
+
3548
+
3549
+
3550
+
3551
+
3552
+
3553
+
3554
+
3555
+
3556
+
3557
+
3558
+
3559
+
3560
+
3561
+
3562
+
3563
+
3564
+
3565
+
3566
+
3567
+
3568
+
3569
+
3570
+
3571
+
3572
+
3573
+
3574
+
3575
+
3576
+
3577
+
3578
+
3579
+
3580
+
3581
+
3582
+
3583
+
3584
+
3585
+
3586
+
3587
+
3588
+
3589
+
3590
+
3591
+
3592
+
3593
+
3594
+
3595
+
3596
+
3597
+
3598
+
3599
+
3600
+
3601
+
3602
+
3603
+
3604
+
3605
+
3606
+
3607
+
3608
+
3609
+
3610
+ * @example
3611
+ * // Filter entries
3612
+ * const mm = new TreeMultiMap<number, string>();
3613
+ * mm.add(1, 'a');
3614
+ * mm.add(2, 'b');
3615
+ * mm.add(3, 'c');
3616
+ * const filtered = mm.filter((v, k) => k > 1);
3617
+ * console.log([...filtered.keys()]); // [2, 3];
708
3618
  */
709
- *[Symbol.iterator](): Iterator<[K, V[]]> {
710
- for (const [k, v] of this.#core) {
711
- // core always stores buckets, but guard anyway
712
- yield [k, v ?? /* istanbul ignore next */ ([] as V[])];
3619
+ filter(predicate: (value: V[], key: K, map: this) => boolean): TreeMultiMap<K, V, R> {
3620
+ const filtered: [K, V[]][] = [];
3621
+ for (const [k, v] of this) {
3622
+ if (predicate(v, k, this)) filtered.push([k, v]);
713
3623
  }
3624
+ return new TreeMultiMap<K, V, R>(filtered, { comparator: this.comparator });
714
3625
  }
715
3626
 
716
3627
  /**
717
- * Iterates over all keys.
718
- * @remarks Time O(n), Space O(1)
3628
+ * Creates a new map by transforming each entry.
3629
+ * @remarks Time O(n log n), Space O(n)
3630
+
3631
+
3632
+
3633
+
3634
+
3635
+
3636
+
3637
+
3638
+
3639
+
3640
+
3641
+
3642
+
3643
+
3644
+
3645
+
3646
+
3647
+
3648
+
3649
+
3650
+
3651
+
3652
+
3653
+
3654
+
3655
+
3656
+
3657
+
3658
+
3659
+
3660
+
3661
+
3662
+
3663
+
3664
+
3665
+
3666
+
3667
+
3668
+
3669
+
3670
+
3671
+
3672
+
3673
+
3674
+
3675
+
3676
+
3677
+
3678
+
3679
+
3680
+
3681
+
3682
+
3683
+
3684
+
3685
+
3686
+
3687
+
3688
+
3689
+
3690
+
3691
+
3692
+
719
3693
 
720
3694
 
721
3695
 
@@ -759,20 +3733,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
759
3733
 
760
3734
 
761
3735
 
762
- * @example
763
- * // Iterate keys
764
- * const mm = new TreeMultiMap<number, string>();
765
- * mm.add(3, 'c');
766
- * mm.add(1, 'a');
767
- * console.log([...mm.keys()]); // [1, 3];
768
- */
769
- *keys(): IterableIterator<K> {
770
- yield* this.#core.keys();
771
- }
772
-
773
- /**
774
- * Iterates over all buckets.
775
- * @remarks Time O(n), Space O(1)
776
3736
 
777
3737
 
778
3738
 
@@ -816,83 +3776,112 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
816
3776
 
817
3777
 
818
3778
 
819
- * @example
820
- * // Iterate value arrays
821
- * const mm = new TreeMultiMap<number, string>();
822
- * mm.add(1, 'a');
823
- * mm.add(1, 'b');
824
- * console.log([...mm.values()]); // [['a', 'b']];
825
- */
826
- *values(): IterableIterator<V[]> {
827
- for (const [, bucket] of this) yield bucket;
828
- }
829
-
830
- // ---- entry-flat views ----
831
-
832
- /**
833
- * Iterates over all entries for a specific key.
834
- * @remarks Time O(log n + m), Space O(1) where m is bucket size
835
3779
 
836
3780
 
837
3781
 
838
- * @example
839
- * // Get entries for key
840
- * const mm = new TreeMultiMap<number, string>();
841
- * mm.add(1, 'a');
842
- * mm.add(1, 'b');
843
- * console.log([...mm.entriesOf(1)]); // [[1, 'a'], [1, 'b']];
844
- */
845
- *entriesOf(key: K): IterableIterator<[K, V]> {
846
- const bucket = this.get(key);
847
- if (!Array.isArray(bucket)) return;
848
- for (const v of bucket) yield [key, v];
849
- }
850
-
851
- /**
852
- * Iterates over all values for a specific key.
853
- * @remarks Time O(log n + m), Space O(1) where m is bucket size
854
3782
 
855
3783
 
856
3784
 
857
- * @example
858
- * // Get flat values for key
859
- * const mm = new TreeMultiMap<number, string>();
860
- * mm.add(1, 'a');
861
- * mm.add(1, 'b');
862
- * console.log([...mm.valuesOf(1)]); // ['a', 'b'];
863
- */
864
- *valuesOf(key: K): IterableIterator<V> {
865
- const bucket = this.get(key);
866
- if (!Array.isArray(bucket)) return;
867
- yield* bucket;
868
- }
869
-
870
- /**
871
- * Iterates over all [key, value] pairs (flattened from buckets).
872
- * @remarks Time O(T), Space O(1) where T is totalSize
873
3785
 
874
3786
 
875
3787
 
876
3788
  * @example
877
- * // All key-value pairs flattened
3789
+ * // Transform values
878
3790
  * const mm = new TreeMultiMap<number, string>();
879
3791
  * mm.add(1, 'a');
880
- * mm.add(1, 'b');
881
- * mm.add(2, 'c');
882
- * console.log([...mm.flatEntries()]); // [[1, 'a'], [1, 'b'], [2, 'c']];
3792
+ * const mapped = mm.map((v, k) => [k, v.map(s => s.toUpperCase())] as [number, string[]]);
3793
+ * console.log(mapped.get(1)); // ['A'];
883
3794
  */
884
- *flatEntries(): IterableIterator<[K, V]> {
885
- for (const [k, bucket] of this) {
886
- for (const v of bucket) yield [k, v];
3795
+ map<V2>(
3796
+ mapper: (value: V[], key: K, map: this) => [K, V2[]]
3797
+ ): TreeMultiMap<K, V2, R> {
3798
+ const mapped: [K, V2[]][] = [];
3799
+ for (const [k, v] of this) {
3800
+ mapped.push(mapper(v, k, this));
887
3801
  }
3802
+ return new TreeMultiMap<K, V2, R>(mapped, { comparator: this.comparator });
888
3803
  }
889
3804
 
890
- // ━━━ Navigable methods (return [K, V[]] | undefined) ━━━
891
-
892
3805
  /**
893
- * Returns the entry with the smallest key.
894
- * @remarks Time O(log n), Space O(1)
895
-
3806
+ * Reduces all entries to a single value.
3807
+ * @remarks Time O(n), Space O(1)
3808
+
3809
+
3810
+
3811
+
3812
+
3813
+
3814
+
3815
+
3816
+
3817
+
3818
+
3819
+
3820
+
3821
+
3822
+
3823
+
3824
+
3825
+
3826
+
3827
+
3828
+
3829
+
3830
+
3831
+
3832
+
3833
+
3834
+
3835
+
3836
+
3837
+
3838
+
3839
+
3840
+
3841
+
3842
+
3843
+
3844
+
3845
+
3846
+
3847
+
3848
+
3849
+
3850
+
3851
+
3852
+
3853
+
3854
+
3855
+
3856
+
3857
+
3858
+
3859
+
3860
+
3861
+
3862
+
3863
+
3864
+
3865
+
3866
+
3867
+
3868
+
3869
+
3870
+
3871
+
3872
+
3873
+
3874
+
3875
+
3876
+
3877
+
3878
+
3879
+
3880
+
3881
+
3882
+
3883
+
3884
+
896
3885
 
897
3886
 
898
3887
 
@@ -908,24 +3897,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
908
3897
 
909
3898
 
910
3899
 
911
- * @example
912
- * // First entry
913
- * const mm = new TreeMultiMap<number, string>();
914
- * mm.add(3, 'c');
915
- * mm.add(1, 'a');
916
- * console.log(mm.first()?.[0]); // 1;
917
- */
918
- first(): [K, V[]] | undefined {
919
- const k = this.#core.getLeftMost();
920
- if (k === undefined) return undefined;
921
- const b = this.get(k);
922
- return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
923
- }
924
-
925
- /**
926
- * Returns the entry with the largest key.
927
- * @remarks Time O(log n), Space O(1)
928
-
929
3900
 
930
3901
 
931
3902
 
@@ -941,69 +3912,12 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
941
3912
 
942
3913
 
943
3914
 
944
- * @example
945
- * // Last entry
946
- * const mm = new TreeMultiMap<number, string>();
947
- * mm.add(1, 'a');
948
- * mm.add(3, 'c');
949
- * console.log(mm.last()?.[0]); // 3;
950
- */
951
- last(): [K, V[]] | undefined {
952
- const k = this.#core.getRightMost();
953
- if (k === undefined) return undefined;
954
- const b = this.get(k);
955
- return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
956
- }
957
-
958
- /**
959
- * Removes and returns the entry with the smallest key.
960
- * @remarks Time O(log n), Space O(1)
961
-
962
3915
 
963
3916
 
964
3917
 
965
- * @example
966
- * // Remove and return first
967
- * const mm = new TreeMultiMap<number, string>();
968
- * mm.add(2, 'b');
969
- * mm.add(1, 'a');
970
- * const first = mm.pollFirst();
971
- * console.log(first?.[0]); // 1;
972
- * console.log(mm.has(1)); // false;
973
- */
974
- pollFirst(): [K, V[]] | undefined {
975
- const e = this.first();
976
- if (!e) return undefined;
977
- this.delete(e[0]);
978
- return e;
979
- }
980
-
981
- /**
982
- * Removes and returns the entry with the largest key.
983
- * @remarks Time O(log n), Space O(1)
984
-
985
3918
 
986
3919
 
987
3920
 
988
- * @example
989
- * // Remove and return last
990
- * const mm = new TreeMultiMap<number, string>();
991
- * mm.add(1, 'a');
992
- * mm.add(3, 'c');
993
- * const last = mm.pollLast();
994
- * console.log(last?.[0]); // 3;
995
- */
996
- pollLast(): [K, V[]] | undefined {
997
- const e = this.last();
998
- if (!e) return undefined;
999
- this.delete(e[0]);
1000
- return e;
1001
- }
1002
-
1003
- /**
1004
- * Returns the entry with the smallest key >= given key.
1005
- * @remarks Time O(log n), Space O(1)
1006
-
1007
3921
 
1008
3922
 
1009
3923
 
@@ -1050,29 +3964,24 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1050
3964
 
1051
3965
 
1052
3966
  * @example
1053
- * // Least key ≥ target
1054
- * const mm = new TreeMultiMap<number, string>();
1055
- * mm.add(10, 'a');
1056
- * mm.add(20, 'b');
1057
- * mm.add(30, 'c');
1058
- * console.log(mm.ceiling(15)?.[0]); // 20;
3967
+ * // Aggregate
3968
+ * const mm = new TreeMultiMap<number, number>();
3969
+ * mm.add(1, 10);
3970
+ * mm.add(2, 20);
3971
+ * const sum = mm.reduce((acc, v) => acc + v.reduce((a, b) => a + b, 0), 0);
3972
+ * console.log(sum); // 30;
1059
3973
  */
1060
- ceiling(key: K): [K, V[]] | undefined {
1061
- this._validateKey(key);
1062
- const k = this.#core.ceiling(key);
1063
- if (k === undefined) return undefined;
1064
- const b = this.get(k);
1065
- return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
3974
+ reduce<U>(callback: (accumulator: U, value: V[], key: K, map: this) => U, initialValue: U): U {
3975
+ let acc = initialValue;
3976
+ for (const [k, v] of this) {
3977
+ acc = callback(acc, v, k, this);
3978
+ }
3979
+ return acc;
1066
3980
  }
1067
3981
 
1068
3982
  /**
1069
- * Returns the entry with the largest key <= given key.
1070
- * @remarks Time O(log n), Space O(1)
1071
-
1072
-
1073
-
1074
-
1075
-
3983
+ * Sets multiple entries at once.
3984
+ * @remarks Time O(m log n), Space O(m) where m is input size
1076
3985
 
1077
3986
 
1078
3987
 
@@ -1114,26 +4023,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1114
4023
 
1115
4024
 
1116
4025
 
1117
- * @example
1118
- * // Greatest key ≤ target
1119
- * const mm = new TreeMultiMap<number, string>();
1120
- * mm.add(10, 'a');
1121
- * mm.add(20, 'b');
1122
- * mm.add(30, 'c');
1123
- * console.log(mm.floor(25)?.[0]); // 20;
1124
- */
1125
- floor(key: K): [K, V[]] | undefined {
1126
- this._validateKey(key);
1127
- const k = this.#core.floor(key);
1128
- if (k === undefined) return undefined;
1129
- const b = this.get(k);
1130
- return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
1131
- }
1132
-
1133
- /**
1134
- * Returns the entry with the smallest key > given key.
1135
- * @remarks Time O(log n), Space O(1)
1136
-
1137
4026
 
1138
4027
 
1139
4028
 
@@ -1167,25 +4056,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1167
4056
 
1168
4057
 
1169
4058
 
1170
- * @example
1171
- * // Least key > target
1172
- * const mm = new TreeMultiMap<number, string>();
1173
- * mm.add(10, 'a');
1174
- * mm.add(20, 'b');
1175
- * console.log(mm.higher(10)?.[0]); // 20;
1176
- */
1177
- higher(key: K): [K, V[]] | undefined {
1178
- this._validateKey(key);
1179
- const k = this.#core.higher(key);
1180
- if (k === undefined) return undefined;
1181
- const b = this.get(k);
1182
- return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
1183
- }
1184
-
1185
- /**
1186
- * Returns the entry with the largest key < given key.
1187
- * @remarks Time O(log n), Space O(1)
1188
-
1189
4059
 
1190
4060
 
1191
4061
 
@@ -1219,26 +4089,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1219
4089
 
1220
4090
 
1221
4091
 
1222
- * @example
1223
- * // Greatest key < target
1224
- * const mm = new TreeMultiMap<number, string>();
1225
- * mm.add(10, 'a');
1226
- * mm.add(20, 'b');
1227
- * console.log(mm.lower(20)?.[0]); // 10;
1228
- */
1229
- lower(key: K): [K, V[]] | undefined {
1230
- this._validateKey(key);
1231
- const k = this.#core.lower(key);
1232
- if (k === undefined) return undefined;
1233
- const b = this.get(k);
1234
- return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
1235
- }
1236
-
1237
- // ━━━ Tree utilities ━━━
1238
-
1239
- /**
1240
- * Prints the internal tree structure (for debugging).
1241
- * @remarks Time O(n), Space O(n)
1242
4092
 
1243
4093
 
1244
4094
 
@@ -1283,21 +4133,23 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1283
4133
 
1284
4134
 
1285
4135
  * @example
1286
- * // Display tree
4136
+ * // Set multiple entries
1287
4137
  * const mm = new TreeMultiMap<number, string>();
1288
- * mm.add(1, 'a');
1289
- * expect(() => mm.print()).not.toThrow();
4138
+ * mm.setMany([[1, ['a']], [2, ['b']]]);
4139
+ * console.log(mm.size); // 2;
1290
4140
  */
1291
- print(): void {
1292
- this.#core.print();
4141
+ setMany(keysNodesEntriesOrRaws: Iterable<K | [K | null | undefined, V[] | undefined]>): boolean[] {
4142
+ const results: boolean[] = [];
4143
+ for (const x of keysNodesEntriesOrRaws) {
4144
+ // Call implementation directly: entry can be K or [K, V[]] or [K, undefined]
4145
+ results.push(this.set(x));
4146
+ }
4147
+ return results;
1293
4148
  }
1294
4149
 
1295
4150
  /**
1296
- * Executes a callback for each entry.
1297
- * @remarks Time O(n), Space O(1)
1298
-
1299
-
1300
-
4151
+ * Searches for entries within a key range.
4152
+ * @remarks Time O(log n + k), Space O(k) where k is result size
1301
4153
 
1302
4154
 
1303
4155
 
@@ -1338,24 +4190,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1338
4190
 
1339
4191
 
1340
4192
 
1341
- * @example
1342
- * // Iterate entries
1343
- * const mm = new TreeMultiMap<number, string>();
1344
- * mm.add(1, 'a');
1345
- * mm.add(2, 'b');
1346
- * const keys: number[] = [];
1347
- * mm.forEach((v, k) => keys.push(k));
1348
- * console.log(keys); // [1, 2];
1349
- */
1350
- forEach(callback: (value: V[], key: K, map: this) => void): void {
1351
- for (const [k, v] of this) {
1352
- callback(v, k, this);
1353
- }
1354
- }
1355
-
1356
- /**
1357
- * Creates a new map with entries that pass the predicate.
1358
- * @remarks Time O(n), Space O(n)
1359
4193
 
1360
4194
 
1361
4195
 
@@ -1399,26 +4233,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1399
4233
 
1400
4234
 
1401
4235
 
1402
- * @example
1403
- * // Filter entries
1404
- * const mm = new TreeMultiMap<number, string>();
1405
- * mm.add(1, 'a');
1406
- * mm.add(2, 'b');
1407
- * mm.add(3, 'c');
1408
- * const filtered = mm.filter((v, k) => k > 1);
1409
- * console.log([...filtered.keys()]); // [2, 3];
1410
- */
1411
- filter(predicate: (value: V[], key: K, map: this) => boolean): TreeMultiMap<K, V, R> {
1412
- const filtered: [K, V[]][] = [];
1413
- for (const [k, v] of this) {
1414
- if (predicate(v, k, this)) filtered.push([k, v]);
1415
- }
1416
- return new TreeMultiMap<K, V, R>(filtered, { comparator: this.comparator });
1417
- }
1418
-
1419
- /**
1420
- * Creates a new map by transforming each entry.
1421
- * @remarks Time O(n log n), Space O(n)
1422
4236
 
1423
4237
 
1424
4238
 
@@ -1463,25 +4277,28 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1463
4277
 
1464
4278
 
1465
4279
  * @example
1466
- * // Transform values
4280
+ * // Find keys in range
1467
4281
  * const mm = new TreeMultiMap<number, string>();
1468
- * mm.add(1, 'a');
1469
- * const mapped = mm.map((v, k) => [k, v.map(s => s.toUpperCase())] as [number, string[]]);
1470
- * console.log(mapped.get(1)); // ['A'];
4282
+ * mm.add(10, 'a');
4283
+ * mm.add(20, 'b');
4284
+ * mm.add(30, 'c');
4285
+ * const result = mm.rangeSearch([15, 25]);
4286
+ * console.log(result.length); // 1;
1471
4287
  */
1472
- map<V2>(
1473
- mapper: (value: V[], key: K, map: this) => [K, V2[]]
1474
- ): TreeMultiMap<K, V2, R> {
1475
- const mapped: [K, V2[]][] = [];
1476
- for (const [k, v] of this) {
1477
- mapped.push(mapper(v, k, this));
1478
- }
1479
- return new TreeMultiMap<K, V2, R>(mapped, { comparator: this.comparator });
4288
+ rangeSearch<C extends (node: RedBlackTreeNode<K, V[]>) => unknown>(
4289
+ range: Range<K> | [K, K],
4290
+ callback?: C
4291
+ ): ReturnType<C>[] {
4292
+ return this.#core.rangeSearch(range, callback as (node: RedBlackTreeNode<K, V[]>) => ReturnType<C>);
1480
4293
  }
1481
4294
 
1482
4295
  /**
1483
- * Reduces all entries to a single value.
1484
- * @remarks Time O(n), Space O(1)
4296
+ * Creates a shallow clone of this map.
4297
+ * @remarks Time O(n log n), Space O(n)
4298
+
4299
+
4300
+
4301
+
1485
4302
 
1486
4303
 
1487
4304
 
@@ -1525,25 +4342,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1525
4342
 
1526
4343
 
1527
4344
 
1528
- * @example
1529
- * // Aggregate
1530
- * const mm = new TreeMultiMap<number, number>();
1531
- * mm.add(1, 10);
1532
- * mm.add(2, 20);
1533
- * const sum = mm.reduce((acc, v) => acc + v.reduce((a, b) => a + b, 0), 0);
1534
- * console.log(sum); // 30;
1535
- */
1536
- reduce<U>(callback: (accumulator: U, value: V[], key: K, map: this) => U, initialValue: U): U {
1537
- let acc = initialValue;
1538
- for (const [k, v] of this) {
1539
- acc = callback(acc, v, k, this);
1540
- }
1541
- return acc;
1542
- }
1543
-
1544
- /**
1545
- * Sets multiple entries at once.
1546
- * @remarks Time O(m log n), Space O(m) where m is input size
1547
4345
 
1548
4346
 
1549
4347
 
@@ -1579,24 +4377,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1579
4377
 
1580
4378
 
1581
4379
 
1582
- * @example
1583
- * // Set multiple entries
1584
- * const mm = new TreeMultiMap<number, string>();
1585
- * mm.setMany([[1, ['a']], [2, ['b']]]);
1586
- * console.log(mm.size); // 2;
1587
- */
1588
- setMany(keysNodesEntriesOrRaws: Iterable<K | [K | null | undefined, V[] | undefined]>): boolean[] {
1589
- const results: boolean[] = [];
1590
- for (const x of keysNodesEntriesOrRaws) {
1591
- // Call implementation directly: entry can be K or [K, V[]] or [K, undefined]
1592
- results.push(this.set(x));
1593
- }
1594
- return results;
1595
- }
1596
-
1597
- /**
1598
- * Searches for entries within a key range.
1599
- * @remarks Time O(log n + k), Space O(k) where k is result size
1600
4380
 
1601
4381
 
1602
4382
 
@@ -1631,25 +4411,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1631
4411
 
1632
4412
 
1633
4413
 
1634
- * @example
1635
- * // Find keys in range
1636
- * const mm = new TreeMultiMap<number, string>();
1637
- * mm.add(10, 'a');
1638
- * mm.add(20, 'b');
1639
- * mm.add(30, 'c');
1640
- * const result = mm.rangeSearch([15, 25]);
1641
- * console.log(result.length); // 1;
1642
- */
1643
- rangeSearch<C extends (node: RedBlackTreeNode<K, V[]>) => unknown>(
1644
- range: Range<K> | [K, K],
1645
- callback?: C
1646
- ): ReturnType<C>[] {
1647
- return this.#core.rangeSearch(range, callback as (node: RedBlackTreeNode<K, V[]>) => ReturnType<C>);
1648
- }
1649
-
1650
- /**
1651
- * Creates a shallow clone of this map.
1652
- * @remarks Time O(n log n), Space O(n)
1653
4414
 
1654
4415
 
1655
4416
 
@@ -1690,6 +4451,66 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1690
4451
 
1691
4452
 
1692
4453
 
4454
+ * @example
4455
+ * // Order-statistic on BST
4456
+ * const tree = new TreeMultiMap<number>([30, 10, 50, 20, 40], { enableOrderStatistic: true });
4457
+ * console.log(tree.getByRank(0)); // 10;
4458
+ * console.log(tree.getByRank(4)); // 50;
4459
+ * console.log(tree.getRank(30)); // 2;
4460
+ */
4461
+ // ─── Order-Statistic Methods ───────────────────────────
4462
+
4463
+ getByRank(k: number): [K, V[]] | undefined {
4464
+ const key = this.#core.getByRank(k);
4465
+ if (key === undefined) return undefined;
4466
+ return [key, this.#core.get(key) ?? []];
4467
+ }
4468
+
4469
+ /**
4470
+ * Get the rank of a key in sorted order
4471
+ * @example
4472
+ * // Get the rank of a key in sorted order
4473
+ * const tree = new TreeMultiMap<number>(
4474
+ * [10, 20, 30, 40, 50],
4475
+ * { enableOrderStatistic: true }
4476
+ * );
4477
+ * console.log(tree.getRank(10)); // 0; // smallest → rank 0
4478
+ * console.log(tree.getRank(30)); // 2; // 2 elements before 30 in tree order
4479
+ * console.log(tree.getRank(50)); // 4; // largest → rank 4
4480
+ * console.log(tree.getRank(25)); // 2;
4481
+ */
4482
+ getRank(key: K): number {
4483
+ return this.#core.getRank(key);
4484
+ }
4485
+
4486
+ /**
4487
+ * Get elements by rank range
4488
+
4489
+ * @example
4490
+ * // Pagination with rangeByRank
4491
+ * const tree = new TreeMultiMap<number>(
4492
+ * [10, 20, 30, 40, 50, 60, 70, 80, 90],
4493
+ * { enableOrderStatistic: true }
4494
+ * );
4495
+ * const pageSize = 3;
4496
+ *
4497
+ * // Page 1
4498
+ * console.log(tree.rangeByRank(0, pageSize - 1)); // [10, 20, 30];
4499
+ * // Page 2
4500
+ * console.log(tree.rangeByRank(pageSize, 2 * pageSize - 1)); // [40, 50, 60];
4501
+ * // Page 3
4502
+ * console.log(tree.rangeByRank(2 * pageSize, 3 * pageSize - 1)); // [70, 80, 90];
4503
+ */
4504
+ rangeByRank(start: number, end: number): Array<[K, V[]]> {
4505
+ const keys = this.#core.rangeByRank(start, end);
4506
+ return keys
4507
+ .filter((k): k is K => k !== undefined)
4508
+ .map(k => [k, this.#core.get(k) ?? []] as [K, V[]]);
4509
+ }
4510
+
4511
+ /**
4512
+ * Deep copy
4513
+
1693
4514
 
1694
4515
 
1695
4516