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.
package/README.md ADDED
@@ -0,0 +1,218 @@
1
+ ![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue.svg)
2
+ ![License: Apache-2.0](https://img.shields.io/badge/License-Apache_2.0-green.svg)
3
+
4
+ # d-Heap Priority Queue (TypeScript) v2.1.1
5
+
6
+ A high-performance, generic d-ary heap priority queue with O(1) item lookup, supporting both min-heap and max-heap behavior.
7
+
8
+ ## Strengths
9
+
10
+ - **Flexible behavior**: min-heap or max-heap via comparator functions, and configurable arity `d` at construction time.
11
+ - **Efficient operations** on n items:
12
+ - O(1): access the highest-priority item (`front()`, `peek()`).
13
+ - O(log_d n): `insert()` and upward reheapification.
14
+ - O(d · log_d n): delete-top (`pop()`), with up to d children examined per level.
15
+ - **O(1) item lookup**: internal Map tracks positions by item key, enabling efficient priority updates.
16
+ - **Practical API**: `insert`, `front`, `peek`, `pop`, `increasePriority`, `decreasePriority`, `isEmpty`, `len`, `contains`.
17
+ - **Unified API**: Cross-language standardized methods matching C++, Rust, and Zig implementations.
18
+ - **TypeScript-native**: Full type safety, generics, and IDE support.
19
+ - **Zero dependencies**: No runtime dependencies.
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install d-ary-heap
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ```typescript
30
+ import { PriorityQueue, minBy, maxBy } from 'd-ary-heap';
31
+
32
+ // Define your item type
33
+ interface Task {
34
+ id: number;
35
+ priority: number;
36
+ name: string;
37
+ }
38
+
39
+ // Create a min-heap (lower priority value = higher importance)
40
+ const pq = new PriorityQueue<Task, number>({
41
+ d: 4, // 4-ary heap
42
+ comparator: minBy(task => task.priority), // Min-heap by priority
43
+ keyExtractor: task => task.id, // Identity by id
44
+ });
45
+
46
+ // Insert items
47
+ pq.insert({ id: 1, priority: 10, name: 'Low priority task' });
48
+ pq.insert({ id: 2, priority: 1, name: 'High priority task' });
49
+ pq.insert({ id: 3, priority: 5, name: 'Medium priority task' });
50
+
51
+ // Get highest priority item (lowest priority value in min-heap)
52
+ console.log(pq.front()); // { id: 2, priority: 1, name: 'High priority task' }
53
+
54
+ // Update priority of existing item
55
+ pq.increasePriority({ id: 1, priority: 0, name: 'Now urgent!' });
56
+ console.log(pq.front()); // { id: 1, priority: 0, name: 'Now urgent!' }
57
+
58
+ // Remove items in priority order
59
+ while (!pq.isEmpty()) {
60
+ console.log(pq.pop());
61
+ }
62
+ ```
63
+
64
+ ## API Reference
65
+
66
+ ### Constructor
67
+
68
+ ```typescript
69
+ new PriorityQueue<T, K>(options: PriorityQueueOptions<T, K>)
70
+ ```
71
+
72
+ Options:
73
+ - `d`: Number of children per node (arity). Default: 2. Must be >= 1.
74
+ - `comparator`: Function `(a: T, b: T) => boolean` returning true if `a` has higher priority.
75
+ - `keyExtractor`: Function `(item: T) => K` extracting the identity key from an item.
76
+ - `initialCapacity`: Optional hint for pre-allocation.
77
+
78
+ ### Static Factory Methods
79
+
80
+ | Method | Description |
81
+ |--------|-------------|
82
+ | `PriorityQueue.withFirst(options, item)` | Create queue with initial item |
83
+
84
+ ### Query Methods
85
+
86
+ | Method | Description | Time |
87
+ |--------|-------------|------|
88
+ | `len()` | Number of items | O(1) |
89
+ | `size` | Property alias for `len()` | O(1) |
90
+ | `isEmpty()` / `is_empty()` | Check if empty | O(1) |
91
+ | `d()` | Get arity | O(1) |
92
+ | `contains(item)` | Check if item exists (by key) | O(1) |
93
+ | `containsKey(key)` | Check if key exists | O(1) |
94
+ | `getPosition(item)` | Get item's index in heap | O(1) |
95
+ | `getPositionByKey(key)` | Get index by key | O(1) |
96
+ | `front()` | Get highest-priority item (throws if empty) | O(1) |
97
+ | `peek()` | Get highest-priority item (returns undefined if empty) | O(1) |
98
+
99
+ ### Modification Methods
100
+
101
+ | Method | Description | Time |
102
+ |--------|-------------|------|
103
+ | `insert(item)` | Add new item | O(log_d n) |
104
+ | `pop()` | Remove and return highest-priority item | O(d · log_d n) |
105
+ | `increasePriority(item)` / `increase_priority(item)` | Update item to higher priority | O(log_d n) |
106
+ | `increasePriorityByIndex(i)` / `increase_priority_by_index(i)` | Update by index | O(log_d n) |
107
+ | `decreasePriority(item)` / `decrease_priority(item)` | Update item to lower priority | O(d · log_d n) |
108
+ | `clear(newD?)` | Remove all items, optionally change arity | O(1) |
109
+
110
+ ### Utility Methods
111
+
112
+ | Method | Description |
113
+ |--------|-------------|
114
+ | `toString()` / `to_string()` | String representation |
115
+ | `toArray()` | Copy of internal array |
116
+ | `[Symbol.iterator]()` | Iterate over items in heap order |
117
+
118
+ ## Comparator Helpers
119
+
120
+ ```typescript
121
+ import { minBy, maxBy, minNumber, maxNumber, reverse, chain } from 'd-ary-heap';
122
+
123
+ // Min-heap by extracted key
124
+ const minByCost = minBy<Item, number>(item => item.cost);
125
+
126
+ // Max-heap by extracted key
127
+ const maxByCost = maxBy<Item, number>(item => item.cost);
128
+
129
+ // For primitive numbers
130
+ const minHeap = minNumber; // (a, b) => a < b
131
+ const maxHeap = maxNumber; // (a, b) => a > b
132
+
133
+ // Reverse any comparator
134
+ const reversed = reverse(minByCost);
135
+
136
+ // Chain comparators (tiebreaker)
137
+ const byPriorityThenTime = chain(
138
+ minBy<Task, number>(t => t.priority),
139
+ minBy<Task, number>(t => t.timestamp)
140
+ );
141
+ ```
142
+
143
+ ## Priority Update Semantics
144
+
145
+ The `increasePriority()` and `decreasePriority()` methods have an intentionally **asymmetric design**:
146
+
147
+ - **`increasePriority()`**: Make an item **more important** (moves toward heap root). Only moves up for O(log_d n) performance.
148
+ - **`decreasePriority()`**: Make an item **less important** (moves toward leaves). Checks both directions for robustness.
149
+
150
+ **Heap Context:**
151
+ - **Min-heap**: Lower priority values = higher importance
152
+ - **Max-heap**: Higher priority values = higher importance
153
+
154
+ ## Performance
155
+
156
+ ### Benchmark Results (Node.js v20, typical hardware)
157
+
158
+ | Operation | d=2 | d=4 | d=8 |
159
+ |-----------|-----|-----|-----|
160
+ | 100k inserts | ~21ms | ~13ms | ~11ms |
161
+ | 100k pops | ~187ms | ~136ms | ~140ms |
162
+ | Throughput (insert) | ~2.2M ops/sec | | |
163
+ | Throughput (pop+insert) | ~900k ops/sec | | |
164
+
165
+ ### Performance Tips
166
+
167
+ 1. **Choose arity wisely**: d=4 is often optimal, balancing tree height vs comparison work per level.
168
+
169
+ 2. **Use inline comparators**: `(a, b) => a.cost < b.cost` is faster than `minBy(x => x.cost)` in hot paths.
170
+
171
+ 3. **Pre-allocate**: Use `initialCapacity` if you know the approximate size.
172
+
173
+ 4. **Simple key extractors**: Keep `keyExtractor` simple—`(item) => item.id` is ideal.
174
+
175
+ 5. **Avoid unnecessary updates**: Check if priority actually changed before calling update methods.
176
+
177
+ ### Running Benchmarks
178
+
179
+ ```bash
180
+ # Full benchmark suite
181
+ npx tsx benchmarks/run-benchmarks.ts
182
+
183
+ # Compare with naive implementation
184
+ npx tsx benchmarks/compare-implementations.ts
185
+ ```
186
+
187
+ ## What is a d-Heap?
188
+
189
+ A [d-ary heap](https://en.wikipedia.org/wiki/D-ary_heap) is a tree where:
190
+ - Each node has up to d children
191
+ - The root holds the highest priority
192
+ - Children are unordered
193
+ - Priorities decrease along any root-to-leaf path
194
+
195
+ Time complexities over n items:
196
+ - O(1): access top
197
+ - O(d · log_d n): delete-top
198
+ - O(log_d n): insert and upward update
199
+
200
+ ## Development
201
+
202
+ ```bash
203
+ # Install dependencies
204
+ npm install
205
+
206
+ # Run tests
207
+ npm test
208
+
209
+ # Build
210
+ npm run build
211
+
212
+ # Type check
213
+ npm run typecheck
214
+ ```
215
+
216
+ ## Reference
217
+
218
+ Section A.3, [d-Heaps](https://en.wikipedia.org/wiki/D-ary_heap), pp. 773–778 of Ravindra Ahuja, Thomas Magnanti & James Orlin, **Network Flows** (Prentice Hall, 1993).