From f904019d40e4e152f15920194bce3fff380d6ab6 Mon Sep 17 00:00:00 2001 From: szdytom Date: Wed, 31 May 2023 15:37:47 +0800 Subject: [PATCH] add priority queue --- src/misc/priority_queue.js | 51 ++++++++++++++++++++++++++++++++++++ tests/priority_queue.test.js | 18 +++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 src/misc/priority_queue.js create mode 100644 tests/priority_queue.test.js diff --git a/src/misc/priority_queue.js b/src/misc/priority_queue.js new file mode 100644 index 0000000..e8f7da0 --- /dev/null +++ b/src/misc/priority_queue.js @@ -0,0 +1,51 @@ +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; + } +} \ No newline at end of file diff --git a/tests/priority_queue.test.js b/tests/priority_queue.test.js new file mode 100644 index 0000000..a65f07c --- /dev/null +++ b/tests/priority_queue.test.js @@ -0,0 +1,18 @@ +import assert from 'node:assert'; +import { PriorityQueue } from '../src/misc/priority_queue.js'; + +describe('PriorityQueue', function () { + it('everything', function() { + let q = new PriorityQueue(); + q.push(1).push(2).push(-1).push('hi', 4); + assert.equal(q.size(), 4); + assert.equal(q.top()[0], 'hi'); + + assert.equal(q.pop()[0], 'hi'); + assert.equal(q.pop()[0], 2); + assert.equal(q.pop()[0], 1); + assert.equal(q.pop()[0], -1); + + assert.ok(q.empty()); + }); +}); \ No newline at end of file