@hardlydifficult/queue 1.1.2 → 1.1.4
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 +147 -114
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @hardlydifficult/queue
|
|
2
2
|
|
|
3
|
-
A high-performance priority queue
|
|
3
|
+
A high-performance priority queue with O(1) enqueue/dequeue operations and FIFO ordering within priority levels.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -15,195 +15,228 @@ import { createPriorityQueue } from "@hardlydifficult/queue";
|
|
|
15
15
|
|
|
16
16
|
const queue = createPriorityQueue<string>();
|
|
17
17
|
|
|
18
|
-
queue.enqueue("low-priority", "low");
|
|
19
|
-
queue.enqueue("urgent", "high");
|
|
20
|
-
queue.enqueue("standard"); // defaults to 'medium'
|
|
18
|
+
queue.enqueue("low-priority task", "low");
|
|
19
|
+
queue.enqueue("urgent fix", "high");
|
|
21
20
|
|
|
22
|
-
//
|
|
23
|
-
console.log(queue.dequeue()?.data); // "urgent"
|
|
24
|
-
console.log(queue.dequeue()?.data); // "
|
|
25
|
-
console.log(queue.dequeue()?.data); // "low-priority"
|
|
21
|
+
// High priority item dequeued first
|
|
22
|
+
console.log(queue.dequeue()?.data); // "urgent fix"
|
|
23
|
+
console.log(queue.dequeue()?.data); // "low-priority task"
|
|
26
24
|
```
|
|
27
25
|
|
|
28
|
-
##
|
|
26
|
+
## Priority-Based Ordering
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
Creates a new priority queue instance.
|
|
28
|
+
Items are dequeued in priority order: high → medium → low. Within each priority level, items follow FIFO (first-in, first-out) order.
|
|
33
29
|
|
|
34
30
|
```typescript
|
|
35
|
-
|
|
31
|
+
const queue = createPriorityQueue<string>();
|
|
36
32
|
|
|
37
|
-
|
|
33
|
+
queue.enqueue("a", "low");
|
|
34
|
+
queue.enqueue("b", "high");
|
|
35
|
+
queue.enqueue("c", "medium");
|
|
36
|
+
queue.enqueue("d", "high");
|
|
37
|
+
|
|
38
|
+
// Dequeue order: b, d, c, a
|
|
39
|
+
console.log(queue.toArray().map(i => i.data)); // ["b", "d", "c", "a"]
|
|
38
40
|
```
|
|
39
41
|
|
|
40
|
-
###
|
|
42
|
+
### Priority Levels
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
| Priority | Dequeue Order |
|
|
45
|
+
|----------|---------------|
|
|
46
|
+
| `high` | First |
|
|
47
|
+
| `medium` | Second (default) |
|
|
48
|
+
| `low` | Third |
|
|
43
49
|
|
|
44
|
-
|
|
50
|
+
## Queue Operations
|
|
45
51
|
|
|
46
|
-
|
|
52
|
+
### `enqueue(data, priority?)`
|
|
47
53
|
|
|
48
|
-
|
|
49
|
-
|-----------|-----------|-----------|------------------------------|
|
|
50
|
-
| data | `T` | — | The item data to enqueue |
|
|
51
|
-
| priority | `Priority`| `"medium"`| Priority level: `"high"`, `"medium"`, or `"low"` |
|
|
54
|
+
Adds an item to the queue.
|
|
52
55
|
|
|
53
|
-
|
|
56
|
+
- **Parameters**:
|
|
57
|
+
- `data`: The item to queue
|
|
58
|
+
- `priority`: `"high"`, `"medium"`, or `"low"` (default: `"medium"`)
|
|
59
|
+
- **Returns**: `QueueItem<T>` with metadata (`data`, `priority`, `enqueuedAt`, `id`)
|
|
60
|
+
- **Time complexity**: O(1)
|
|
54
61
|
|
|
55
62
|
```typescript
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
console.log(item.priority); // "high"
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
#### dequeue()
|
|
62
|
-
|
|
63
|
-
Removes and returns the highest-priority item (FIFO within same priority).
|
|
63
|
+
const queue = createPriorityQueue<number>();
|
|
64
|
+
const item = queue.enqueue(42, "high");
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
const item = queue.dequeue();
|
|
67
|
-
if (item) {
|
|
68
|
-
console.log(item.data); // "urgent"
|
|
69
|
-
}
|
|
66
|
+
console.log(item); // { data: 42, priority: "high", enqueuedAt: 1712345678901, id: "q_1" }
|
|
70
67
|
```
|
|
71
68
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
#### peek()
|
|
69
|
+
### `dequeue()`
|
|
75
70
|
|
|
76
|
-
|
|
71
|
+
Removes and returns the highest-priority item.
|
|
77
72
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (next) {
|
|
81
|
-
console.log(next.data); // First item to be dequeued
|
|
82
|
-
}
|
|
83
|
-
```
|
|
73
|
+
- **Returns**: `QueueItem<T> | undefined`
|
|
74
|
+
- **Time complexity**: O(1)
|
|
84
75
|
|
|
85
|
-
|
|
76
|
+
### `peek()`
|
|
86
77
|
|
|
87
|
-
|
|
78
|
+
Returns the next item without removing it.
|
|
88
79
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const removed = queue.remove(item.id); // true
|
|
92
|
-
const absent = queue.remove("unknown"); // false
|
|
93
|
-
```
|
|
80
|
+
- **Returns**: `QueueItem<T> | undefined`
|
|
81
|
+
- **Time complexity**: O(1)
|
|
94
82
|
|
|
95
|
-
|
|
83
|
+
### `size` & `isEmpty`
|
|
96
84
|
|
|
97
|
-
|
|
85
|
+
Accessors for queue state.
|
|
98
86
|
|
|
99
87
|
```typescript
|
|
100
|
-
|
|
101
|
-
```
|
|
88
|
+
const queue = createPriorityQueue<string>();
|
|
102
89
|
|
|
103
|
-
|
|
90
|
+
console.log(queue.size); // 0
|
|
91
|
+
console.log(queue.isEmpty); // true
|
|
104
92
|
|
|
105
|
-
|
|
93
|
+
queue.enqueue("item");
|
|
106
94
|
|
|
107
|
-
|
|
108
|
-
console.log(queue.isEmpty);
|
|
95
|
+
console.log(queue.size); // 1
|
|
96
|
+
console.log(queue.isEmpty); // false
|
|
109
97
|
```
|
|
110
98
|
|
|
111
|
-
|
|
99
|
+
### `toArray()`
|
|
112
100
|
|
|
113
|
-
|
|
101
|
+
Returns all items in dequeue order (snapshot).
|
|
114
102
|
|
|
115
|
-
Returns
|
|
103
|
+
- **Returns**: `readonly QueueItem<T>[]`
|
|
104
|
+
- Does not modify the queue
|
|
116
105
|
|
|
117
106
|
```typescript
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
107
|
+
const queue = createPriorityQueue<string>();
|
|
108
|
+
queue.enqueue("c", "low");
|
|
109
|
+
queue.enqueue("a", "high");
|
|
110
|
+
queue.enqueue("b", "medium");
|
|
121
111
|
|
|
122
|
-
queue.
|
|
123
|
-
unsubscribe();
|
|
124
|
-
queue.enqueue("ignored"); // callback no longer invoked
|
|
112
|
+
console.log(queue.toArray().map(i => i.data)); // ["a", "b", "c"]
|
|
125
113
|
```
|
|
126
114
|
|
|
127
|
-
|
|
115
|
+
### `clear()`
|
|
128
116
|
|
|
129
|
-
|
|
117
|
+
Removes all items from the queue.
|
|
130
118
|
|
|
131
119
|
```typescript
|
|
132
|
-
const
|
|
133
|
-
|
|
120
|
+
const queue = createPriorityQueue<string>();
|
|
121
|
+
queue.enqueue("item");
|
|
122
|
+
queue.clear();
|
|
123
|
+
console.log(queue.size); // 0
|
|
134
124
|
```
|
|
135
125
|
|
|
136
|
-
|
|
126
|
+
## Item Management
|
|
137
127
|
|
|
138
|
-
|
|
128
|
+
### `remove(id)`
|
|
129
|
+
|
|
130
|
+
Removes a specific item by ID.
|
|
131
|
+
|
|
132
|
+
- **Returns**: `boolean` (`true` if found and removed)
|
|
133
|
+
- **Time complexity**: O(n) (due to linear search)
|
|
139
134
|
|
|
140
135
|
```typescript
|
|
141
|
-
queue
|
|
142
|
-
queue.enqueue("
|
|
143
|
-
queue.
|
|
144
|
-
|
|
136
|
+
const queue = createPriorityQueue<string>();
|
|
137
|
+
const item = queue.enqueue("remove-me");
|
|
138
|
+
queue.enqueue("keep-me");
|
|
139
|
+
|
|
140
|
+
console.log(queue.remove(item.id)); // true
|
|
141
|
+
console.log(queue.size); // 1
|
|
142
|
+
console.log(queue.dequeue()?.data); // "keep-me"
|
|
145
143
|
```
|
|
146
144
|
|
|
147
|
-
###
|
|
145
|
+
### `updatePriority(id, newPriority)`
|
|
148
146
|
|
|
149
|
-
|
|
147
|
+
Changes an item's priority.
|
|
150
148
|
|
|
151
|
-
|
|
149
|
+
- **Returns**: `boolean` (`true` if item found)
|
|
150
|
+
- Preserves `data` and `enqueuedAt`; appends to new priority bucket
|
|
152
151
|
|
|
153
152
|
```typescript
|
|
153
|
+
const queue = createPriorityQueue<string>();
|
|
154
154
|
const item = queue.enqueue("task", "low");
|
|
155
|
-
queue.
|
|
155
|
+
queue.enqueue("other", "high");
|
|
156
|
+
|
|
157
|
+
console.log(queue.toArray().map(i => i.priority)); // ["high", "low"]
|
|
158
|
+
|
|
159
|
+
queue.updatePriority(item.id, "high");
|
|
160
|
+
console.log(queue.toArray().map(i => i.priority)); // ["high", "high"]
|
|
156
161
|
```
|
|
157
162
|
|
|
158
|
-
|
|
163
|
+
### `moveBefore(itemId, beforeItemId)`
|
|
159
164
|
|
|
160
|
-
|
|
165
|
+
Reorders items within the same priority bucket.
|
|
161
166
|
|
|
162
|
-
|
|
167
|
+
- **Returns**: `boolean` (`true` if move succeeded)
|
|
168
|
+
- Both items must exist and share the same priority
|
|
163
169
|
|
|
164
170
|
```typescript
|
|
165
|
-
const
|
|
166
|
-
const
|
|
167
|
-
const
|
|
171
|
+
const queue = createPriorityQueue<string>();
|
|
172
|
+
const a = queue.enqueue("first");
|
|
173
|
+
const b = queue.enqueue("second");
|
|
174
|
+
const c = queue.enqueue("third");
|
|
168
175
|
|
|
169
|
-
queue.moveBefore(c.id, a.id);
|
|
170
|
-
console.log(queue.toArray().map(i => i.data)); // ["
|
|
176
|
+
queue.moveBefore(c.id, a.id);
|
|
177
|
+
console.log(queue.toArray().map(i => i.data)); // ["third", "first", "second"]
|
|
171
178
|
```
|
|
172
179
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
#### moveToEnd(itemId)
|
|
180
|
+
### `moveToEnd(itemId)`
|
|
176
181
|
|
|
177
182
|
Moves an item to the end of its priority bucket.
|
|
178
183
|
|
|
184
|
+
- **Returns**: `boolean` (`true` if item found)
|
|
185
|
+
- No-op if already at end
|
|
186
|
+
|
|
179
187
|
```typescript
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
queue.
|
|
183
|
-
|
|
188
|
+
const queue = createPriorityQueue<string>();
|
|
189
|
+
queue.enqueue("first");
|
|
190
|
+
queue.enqueue("second");
|
|
191
|
+
const last = queue.enqueue("third");
|
|
192
|
+
|
|
193
|
+
queue.moveToEnd(last.id); // No change (already at end)
|
|
194
|
+
console.log(queue.toArray().map(i => i.data)); // ["first", "second", "third"]
|
|
184
195
|
```
|
|
185
196
|
|
|
186
|
-
|
|
197
|
+
## Observer Pattern
|
|
198
|
+
|
|
199
|
+
### `onEnqueue(callback)`
|
|
187
200
|
|
|
188
|
-
|
|
201
|
+
Registers a listener for new items.
|
|
189
202
|
|
|
190
|
-
|
|
203
|
+
- **Returns**: Unsubscribe function
|
|
191
204
|
|
|
192
205
|
```typescript
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
206
|
+
const queue = createPriorityQueue<string>();
|
|
207
|
+
const handler = (item) => {
|
|
208
|
+
console.log("Enqueued:", item.data, "at", item.enqueuedAt);
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const unsubscribe = queue.onEnqueue(handler);
|
|
212
|
+
|
|
213
|
+
queue.enqueue("test"); // Logs the enqueue event
|
|
214
|
+
unsubscribe();
|
|
215
|
+
queue.enqueue("ignored"); // Not logged
|
|
199
216
|
```
|
|
200
217
|
|
|
201
|
-
##
|
|
218
|
+
## API Reference
|
|
219
|
+
|
|
220
|
+
### Types
|
|
221
|
+
|
|
222
|
+
| Name | Description |
|
|
223
|
+
|--------------|------------------------------------------|
|
|
224
|
+
| `Priority` | `"high" | "medium" | "low"` |
|
|
225
|
+
| `QueueItem<T>` | Item with `data`, `priority`, `enqueuedAt`, `id` |
|
|
226
|
+
| `PriorityQueue<T>` | Core queue interface |
|
|
227
|
+
|
|
228
|
+
### Exports
|
|
202
229
|
|
|
203
|
-
|
|
230
|
+
| Export | Description |
|
|
231
|
+
|----------------------|----------------------------------|
|
|
232
|
+
| `createPriorityQueue<T>()` | Factory function for new queues |
|
|
233
|
+
| `PriorityQueue<T>` | Queue interface type |
|
|
234
|
+
| `QueueItem<T>` | Item interface type |
|
|
235
|
+
| `Priority` | Priority type alias |
|
|
204
236
|
|
|
205
|
-
|
|
206
|
-
2. `"medium"` (default)
|
|
207
|
-
3. `"low"`
|
|
237
|
+
### Time Complexity
|
|
208
238
|
|
|
209
|
-
|
|
239
|
+
| Operation | Complexity |
|
|
240
|
+
|------------------------|------------|
|
|
241
|
+
| `enqueue`, `dequeue`, `peek`, `toArray`, `size`, `isEmpty`, `clear` | O(1) |
|
|
242
|
+
| `remove`, `updatePriority`, `moveBefore`, `moveToEnd` | O(n) |
|