feat: binary-heap event queue with stable tie-breaking
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
// Binary min-heap keyed by (time, insertion sequence).
|
||||
export class EventQueue {
|
||||
constructor() {
|
||||
this.heap = [];
|
||||
this.seq = 0;
|
||||
}
|
||||
|
||||
get size() {
|
||||
return this.heap.length;
|
||||
}
|
||||
|
||||
push(time, type, data) {
|
||||
const e = { time, seq: this.seq++, type, data };
|
||||
const h = this.heap;
|
||||
h.push(e);
|
||||
let i = h.length - 1;
|
||||
while (i > 0) {
|
||||
const p = (i - 1) >> 1;
|
||||
if (!before(h[i], h[p])) break;
|
||||
[h[i], h[p]] = [h[p], h[i]];
|
||||
i = p;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
peek() {
|
||||
return this.heap[0] ?? null;
|
||||
}
|
||||
|
||||
pop() {
|
||||
const h = this.heap;
|
||||
if (h.length === 0) return null;
|
||||
const top = h[0];
|
||||
const last = h.pop();
|
||||
if (h.length > 0) {
|
||||
h[0] = last;
|
||||
let i = 0;
|
||||
for (;;) {
|
||||
const l = 2 * i + 1, r = 2 * i + 2;
|
||||
let m = i;
|
||||
if (l < h.length && before(h[l], h[m])) m = l;
|
||||
if (r < h.length && before(h[r], h[m])) m = r;
|
||||
if (m === i) break;
|
||||
[h[i], h[m]] = [h[m], h[i]];
|
||||
i = m;
|
||||
}
|
||||
}
|
||||
return top;
|
||||
}
|
||||
}
|
||||
|
||||
function before(a, b) {
|
||||
return a.time < b.time || (a.time === b.time && a.seq < b.seq);
|
||||
}
|
||||
Reference in New Issue
Block a user