From dd9851674c203b449d57722dbd4a2e42ad9545c6 Mon Sep 17 00:00:00 2001 From: szdytom Date: Thu, 2 Nov 2023 09:17:34 +0800 Subject: [PATCH] [utils] add class `PriorityQueue` --- utils/index.mjs | 1 + utils/priority-queue.mjs | 52 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 utils/priority-queue.mjs diff --git a/utils/index.mjs b/utils/index.mjs index 7eb218c..8f5488a 100644 --- a/utils/index.mjs +++ b/utils/index.mjs @@ -4,3 +4,4 @@ export { readJsonFile, writeJsonFile, parseLogin, waitEvent, export { Queue, QueueEmptyError } from './queue.mjs'; export { AsyncLock } from './async-lock.mjs'; export { Task, TaskInteruptedError } from './task.mjs'; +export { PriorityQueue } from './priority-queue.mjs'; diff --git a/utils/priority-queue.mjs b/utils/priority-queue.mjs new file mode 100644 index 0000000..16a8f37 --- /dev/null +++ b/utils/priority-queue.mjs @@ -0,0 +1,52 @@ + +export class PriorityQueue { + constructor() { + this.val = [null]; + } + + push(value, priority) { + if (priority == null) { + priority = value; + } + + this.val.push([value, priority]); + let id = this.val.length - 1; + while (id > 1 && this.val[id][1] > this.val[id >>> 1][1]) { + const kid = id >>> 1; + [this.val[id], this.val[kid]] = [this.val[kid], this.val[id]]; + id = kid; + } + return this; + } + + pop() { + let lv = this.val.pop(); + if (this.val.length == 1) { return lv; } + + let res = this.val[1]; + this.val[1] = lv; + let id = 1; + while (id * 2 < this.val.length) { + if (this.val[id][1] > this.val[id * 2][1] && (id * 2 + 1 >= this.val.length || this.val[id][1] > this.val[id * 2 + 1][1])) { + break; + } + + let kid = (id * 2 + 1 >= this.val.length || this.val[id * 2][1] > this.val[id * 2 + 1][1]) ? id * 2 : id * 2 + 1; + [this.val[id], this.val[kid]] = [this.val[kid], this.val[id]]; + id = kid; + } + return res; + } + + top() { + return this.val[1]; + } + + size() { + return this.val.length - 1; + } + + empty() { + return this.size() == 0; + } +};