d-ary-heap 2.1.1

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.
@@ -0,0 +1,388 @@
1
+ /**
2
+ * d-ary Heap Priority Queue - TypeScript Implementation
3
+ *
4
+ * A generic d-ary heap (d-heap) priority queue with:
5
+ * - Configurable arity (d): number of children per node
6
+ * - Min-heap or max-heap behavior via comparator functions
7
+ * - O(1) item lookup using Map for efficient priority updates
8
+ * - O(1) access to highest-priority item
9
+ * - O(log_d n) insert and priority increase operations
10
+ * - O(d · log_d n) pop and priority decrease operations
11
+ *
12
+ * @version 2.0.0
13
+ * @license Apache-2.0
14
+ * @copyright 2023-2025 Eric Jacopin
15
+ */
16
+ /** Type alias for position indices (cross-language consistency) */
17
+ type Position = number;
18
+ /**
19
+ * Comparator function type for priority comparison.
20
+ * Returns true if `a` has higher priority than `b`.
21
+ */
22
+ type Comparator<T> = (a: T, b: T) => boolean;
23
+ /**
24
+ * Key extractor function type for identity-based lookup.
25
+ * Must return a value that can be used as a Map key (string or number recommended).
26
+ */
27
+ type KeyExtractor<T, K> = (item: T) => K;
28
+ /**
29
+ * Configuration options for PriorityQueue construction.
30
+ */
31
+ interface PriorityQueueOptions<T, K> {
32
+ /** Number of children per node (arity). Must be >= 1. Default: 2 */
33
+ d?: number;
34
+ /** Comparator function. Returns true if first arg has higher priority. */
35
+ comparator: Comparator<T>;
36
+ /** Key extractor for identity-based lookup. Required for decrease/increase priority. */
37
+ keyExtractor: KeyExtractor<T, K>;
38
+ /** Initial capacity hint for pre-allocation */
39
+ initialCapacity?: number;
40
+ }
41
+ /**
42
+ * Generic d-ary heap priority queue with O(1) lookup.
43
+ *
44
+ * A d-ary heap is a tree structure where:
45
+ * - Each node has at most d children
46
+ * - The root contains the highest-priority item
47
+ * - Each parent has higher priority than all its children
48
+ * - The tree is complete (filled left-to-right, level by level)
49
+ *
50
+ * This implementation uses an array-based representation with O(1) item lookup
51
+ * via a Map that tracks each item's position in the heap.
52
+ *
53
+ * ## Time Complexities
54
+ * - front(), peek(): O(1)
55
+ * - insert(): O(log_d n)
56
+ * - pop(): O(d · log_d n)
57
+ * - increasePriority(): O(log_d n)
58
+ * - decreasePriority(): O(d · log_d n)
59
+ * - contains(): O(1)
60
+ * - len(), isEmpty(), d(): O(1)
61
+ *
62
+ * @typeParam T - Item type stored in the queue
63
+ * @typeParam K - Key type for identity lookup (typically string or number)
64
+ */
65
+ declare class PriorityQueue<T, K = string | number> {
66
+ /** Array-based heap storage (complete tree representation) */
67
+ private container;
68
+ /** Maps each item's key to its position in the container for O(1) lookup */
69
+ private positions;
70
+ /** Number of children per node (arity of the heap) */
71
+ private depth;
72
+ /** Comparator determining heap order (min vs max) */
73
+ private readonly comparator;
74
+ /** Key extractor for identity-based lookup */
75
+ private readonly keyExtractor;
76
+ /**
77
+ * Create a new d-ary heap priority queue.
78
+ *
79
+ * @param options - Configuration options
80
+ * @throws Error if d < 1
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * // Min-heap by cost
85
+ * const pq = new PriorityQueue<Item, number>({
86
+ * d: 4,
87
+ * comparator: (a, b) => a.cost < b.cost,
88
+ * keyExtractor: (item) => item.id
89
+ * });
90
+ * ```
91
+ */
92
+ constructor(options: PriorityQueueOptions<T, K>);
93
+ /**
94
+ * Create a new priority queue with an initial item already inserted.
95
+ * Equivalent to Rust's `with_first()` constructor.
96
+ *
97
+ * @param options - Configuration options
98
+ * @param firstItem - First item to insert
99
+ * @returns New PriorityQueue with the item already inserted
100
+ */
101
+ static withFirst<T, K>(options: PriorityQueueOptions<T, K>, firstItem: T): PriorityQueue<T, K>;
102
+ /**
103
+ * Get the number of items in the heap.
104
+ * Time complexity: O(1)
105
+ */
106
+ len(): number;
107
+ /** Alias for len() - backward compatibility */
108
+ get size(): number;
109
+ /**
110
+ * Check if the heap is empty.
111
+ * Time complexity: O(1)
112
+ */
113
+ isEmpty(): boolean;
114
+ /** Alias for isEmpty() - snake_case for cross-language consistency */
115
+ is_empty(): boolean;
116
+ /**
117
+ * Get the arity (number of children per node) of the heap.
118
+ * Time complexity: O(1)
119
+ */
120
+ d(): number;
121
+ /**
122
+ * Check if an item with the given key exists in the heap.
123
+ * Time complexity: O(1)
124
+ *
125
+ * @param item - Item to check (uses keyExtractor for identity)
126
+ */
127
+ contains(item: T): boolean;
128
+ /**
129
+ * Check if an item with the given key exists in the heap.
130
+ * Time complexity: O(1)
131
+ *
132
+ * @param key - Key to check directly
133
+ */
134
+ containsKey(key: K): boolean;
135
+ /**
136
+ * Get the current position (index) of an item in the heap.
137
+ * Time complexity: O(1)
138
+ *
139
+ * @param item - Item to find (uses keyExtractor for identity)
140
+ * @returns Position index, or undefined if not found
141
+ */
142
+ getPosition(item: T): Position | undefined;
143
+ /**
144
+ * Get the current position (index) of an item by its key.
145
+ * Time complexity: O(1)
146
+ *
147
+ * @param key - Key to find
148
+ * @returns Position index, or undefined if not found
149
+ */
150
+ getPositionByKey(key: K): Position | undefined;
151
+ /**
152
+ * Get the highest-priority item without removing it.
153
+ * Time complexity: O(1)
154
+ *
155
+ * @returns The highest-priority item
156
+ * @throws Error if heap is empty
157
+ */
158
+ front(): T;
159
+ /**
160
+ * Get the highest-priority item without removing it.
161
+ * Safe alternative to front().
162
+ * Time complexity: O(1)
163
+ *
164
+ * @returns The highest-priority item, or undefined if empty
165
+ */
166
+ peek(): T | undefined;
167
+ /**
168
+ * Insert a new item into the heap.
169
+ * Time complexity: O(log_d n)
170
+ *
171
+ * @param item - Item to insert
172
+ *
173
+ * @remarks
174
+ * If an item with the same key already exists, behavior is undefined.
175
+ * Use contains() to check first, or use increasePriority()/decreasePriority()
176
+ * to update existing items.
177
+ */
178
+ insert(item: T): void;
179
+ /**
180
+ * Insert multiple items into the heap.
181
+ * Uses heapify algorithm which is O(n) for bulk insertion vs O(n log n) for individual inserts.
182
+ * Time complexity: O(n) where n is total items after insertion
183
+ *
184
+ * @param items - Array of items to insert
185
+ *
186
+ * @remarks
187
+ * More efficient than calling insert() repeatedly when adding many items at once.
188
+ * If any item has a key that already exists, behavior is undefined.
189
+ */
190
+ insertMany(items: T[]): void;
191
+ /**
192
+ * Build heap property from unordered array.
193
+ * Uses Floyd's algorithm - O(n) time complexity.
194
+ * Called internally by insertMany when starting from empty heap.
195
+ */
196
+ private heapify;
197
+ /**
198
+ * Increase the priority of an existing item (move toward root).
199
+ * Time complexity: O(log_d n)
200
+ *
201
+ * @param updatedItem - Item with same identity but updated priority
202
+ * @throws Error if item not found
203
+ *
204
+ * @remarks
205
+ * For min-heap: decreasing the priority value increases importance.
206
+ * For max-heap: increasing the priority value increases importance.
207
+ * This method only moves items upward for performance.
208
+ */
209
+ increasePriority(updatedItem: T): void;
210
+ /** Alias for increasePriority() - snake_case for cross-language consistency */
211
+ increase_priority(updatedItem: T): void;
212
+ /**
213
+ * Increase the priority of the item at the given index.
214
+ * Time complexity: O(log_d n)
215
+ *
216
+ * @param index - Index of the item in the heap array
217
+ * @throws Error if index is out of bounds
218
+ *
219
+ * @remarks
220
+ * This is a lower-level method. Prefer increasePriority() with the item itself.
221
+ */
222
+ increasePriorityByIndex(index: number): void;
223
+ /** Alias for increasePriorityByIndex() - snake_case for cross-language consistency */
224
+ increase_priority_by_index(index: number): void;
225
+ /**
226
+ * Decrease the priority of an existing item (move toward leaves).
227
+ * Time complexity: O(d · log_d n)
228
+ *
229
+ * @param updatedItem - Item with same identity but updated priority
230
+ * @throws Error if item not found
231
+ *
232
+ * @remarks
233
+ * For min-heap: increasing the priority value decreases importance.
234
+ * For max-heap: decreasing the priority value decreases importance.
235
+ * This method checks both directions for robustness.
236
+ */
237
+ decreasePriority(updatedItem: T): void;
238
+ /** Alias for decreasePriority() - snake_case for cross-language consistency */
239
+ decrease_priority(updatedItem: T): void;
240
+ /**
241
+ * Remove and return the highest-priority item.
242
+ * Time complexity: O(d · log_d n)
243
+ *
244
+ * @returns The removed item, or undefined if empty
245
+ */
246
+ pop(): T | undefined;
247
+ /**
248
+ * Remove and return multiple highest-priority items.
249
+ * More efficient than calling pop() repeatedly.
250
+ * Time complexity: O(count · d · log_d n)
251
+ *
252
+ * @param count - Number of items to remove
253
+ * @returns Array of removed items in priority order
254
+ */
255
+ popMany(count: number): T[];
256
+ /**
257
+ * Clear all items from the heap, optionally changing the arity.
258
+ * Time complexity: O(1) (references cleared, GC handles memory)
259
+ *
260
+ * @param newD - Optional new arity value (must be >= 1 if provided)
261
+ * @throws Error if newD < 1
262
+ */
263
+ clear(newD?: number): void;
264
+ /**
265
+ * Get a string representation of the heap contents.
266
+ * Time complexity: O(n)
267
+ *
268
+ * @returns Formatted string showing all items in heap order
269
+ */
270
+ toString(): string;
271
+ /** Alias for toString() - snake_case for cross-language consistency */
272
+ to_string(): string;
273
+ /**
274
+ * Get all items in heap order (for debugging/iteration).
275
+ * Time complexity: O(n) - creates a copy
276
+ *
277
+ * @returns Copy of internal array
278
+ */
279
+ toArray(): T[];
280
+ /**
281
+ * Iterate over items in heap order (not priority order).
282
+ */
283
+ [Symbol.iterator](): Iterator<T>;
284
+ /**
285
+ * Swap two items in the heap and update their position mappings.
286
+ * V8 optimizes simple swap patterns well.
287
+ */
288
+ private swap;
289
+ /**
290
+ * Find the child with highest priority among all children of node i.
291
+ */
292
+ private bestChildPosition;
293
+ /**
294
+ * Move an item upward in the heap to restore heap property.
295
+ * Uses simple swap pattern which V8 optimizes well.
296
+ */
297
+ private moveUp;
298
+ /**
299
+ * Move an item downward in the heap to restore heap property.
300
+ */
301
+ private moveDown;
302
+ }
303
+
304
+ /**
305
+ * Pre-built comparator factories for common use cases.
306
+ *
307
+ * @module comparators
308
+ * @version 2.0.0
309
+ * @license Apache-2.0
310
+ */
311
+
312
+ /**
313
+ * Create a min-heap comparator using a key extractor.
314
+ * Lower key values have higher priority (appear closer to root).
315
+ *
316
+ * @param keyFn - Function to extract the comparable key from an item
317
+ * @returns Comparator function for min-heap behavior
318
+ *
319
+ * @example
320
+ * ```typescript
321
+ * const minByCost = minBy<Item, number>(item => item.cost);
322
+ * ```
323
+ */
324
+ declare function minBy<T, K>(keyFn: (item: T) => K): Comparator<T>;
325
+ /**
326
+ * Create a max-heap comparator using a key extractor.
327
+ * Higher key values have higher priority (appear closer to root).
328
+ *
329
+ * @param keyFn - Function to extract the comparable key from an item
330
+ * @returns Comparator function for max-heap behavior
331
+ *
332
+ * @example
333
+ * ```typescript
334
+ * const maxByCost = maxBy<Item, number>(item => item.cost);
335
+ * ```
336
+ */
337
+ declare function maxBy<T, K>(keyFn: (item: T) => K): Comparator<T>;
338
+ /**
339
+ * Min-heap comparator for primitive number values.
340
+ * Lower numbers have higher priority.
341
+ */
342
+ declare const minNumber: Comparator<number>;
343
+ /**
344
+ * Max-heap comparator for primitive number values.
345
+ * Higher numbers have higher priority.
346
+ */
347
+ declare const maxNumber: Comparator<number>;
348
+ /**
349
+ * Min-heap comparator for primitive string values.
350
+ * Lexicographically smaller strings have higher priority.
351
+ */
352
+ declare const minString: Comparator<string>;
353
+ /**
354
+ * Max-heap comparator for primitive string values.
355
+ * Lexicographically larger strings have higher priority.
356
+ */
357
+ declare const maxString: Comparator<string>;
358
+ /**
359
+ * Create a comparator that reverses another comparator.
360
+ *
361
+ * @param cmp - Original comparator to reverse
362
+ * @returns Reversed comparator
363
+ *
364
+ * @example
365
+ * ```typescript
366
+ * const maxByCost = reverse(minBy<Item, number>(item => item.cost));
367
+ * ```
368
+ */
369
+ declare function reverse<T>(cmp: Comparator<T>): Comparator<T>;
370
+ /**
371
+ * Create a comparator that compares by multiple keys in order.
372
+ * Falls back to subsequent comparators when items are equal.
373
+ *
374
+ * @param comparators - Array of comparators to apply in order
375
+ * @returns Combined comparator
376
+ *
377
+ * @example
378
+ * ```typescript
379
+ * // Sort by priority first, then by timestamp
380
+ * const cmp = chain(
381
+ * minBy<Task, number>(t => t.priority),
382
+ * minBy<Task, number>(t => t.timestamp)
383
+ * );
384
+ * ```
385
+ */
386
+ declare function chain<T>(...comparators: Comparator<T>[]): Comparator<T>;
387
+
388
+ export { type Comparator, type KeyExtractor, type Position, PriorityQueue, type PriorityQueueOptions, chain, maxBy, maxNumber, maxString, minBy, minNumber, minString, reverse };