TransFlow/node_modules/js-sdsl/dist/cjs/container/OtherContainer/PriorityQueue.js

125 lines
4.4 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = require("../ContainerBase/index");
class PriorityQueue extends index_1.Base {
/**
* @description PriorityQueue's constructor.
* @param container Initialize container, must have a forEach function.
* @param cmp Compare function.
* @param copy When the container is an array, you can choose to directly operate on the original object of
* the array or perform a shallow copy. The default is shallow copy.
*/
constructor(container = [], cmp = (x, y) => {
if (x > y)
return -1;
if (x < y)
return 1;
return 0;
}, copy = true) {
super();
this.cmp = cmp;
if (Array.isArray(container)) {
this.priorityQueue = copy ? [...container] : container;
}
else {
this.priorityQueue = [];
container.forEach(element => this.priorityQueue.push(element));
}
this.length = this.priorityQueue.length;
for (let parent = (this.length - 1) >> 1; parent >= 0; --parent) {
let curParent = parent;
let curChild = (curParent << 1) | 1;
while (curChild < this.length) {
const left = curChild;
const right = left + 1;
let minChild = left;
if (right < this.length &&
this.cmp(this.priorityQueue[left], this.priorityQueue[right]) > 0) {
minChild = right;
}
if (this.cmp(this.priorityQueue[curParent], this.priorityQueue[minChild]) <= 0)
break;
[this.priorityQueue[curParent], this.priorityQueue[minChild]] =
[this.priorityQueue[minChild], this.priorityQueue[curParent]];
curParent = minChild;
curChild = (curParent << 1) | 1;
}
}
}
/**
* @description Adjusting parent's children to suit the nature of the heap.
* @param parent Parent's index.
* @private
*/
adjust(parent) {
const left = (parent << 1) | 1;
const right = (parent << 1) + 2;
if (left < this.length &&
this.cmp(this.priorityQueue[parent], this.priorityQueue[left]) > 0) {
[this.priorityQueue[parent], this.priorityQueue[left]] =
[this.priorityQueue[left], this.priorityQueue[parent]];
}
if (right < this.length &&
this.cmp(this.priorityQueue[parent], this.priorityQueue[right]) > 0) {
[this.priorityQueue[parent], this.priorityQueue[right]] =
[this.priorityQueue[right], this.priorityQueue[parent]];
}
}
clear() {
this.length = 0;
this.priorityQueue.length = 0;
}
/**
* @description Push element into a container in order.
* @param element The element you want to push.
*/
push(element) {
this.priorityQueue.push(element);
this.length += 1;
if (this.length === 1)
return;
let curNode = this.length - 1;
while (curNode > 0) {
const parent = (curNode - 1) >> 1;
if (this.cmp(this.priorityQueue[parent], element) <= 0)
break;
this.adjust(parent);
curNode = parent;
}
}
/**
* @description Removes the top element.
*/
pop() {
if (!this.length)
return;
const last = this.priorityQueue[this.length - 1];
this.length -= 1;
let parent = 0;
while (parent < this.length) {
const left = (parent << 1) | 1;
const right = (parent << 1) + 2;
if (left >= this.length)
break;
let minChild = left;
if (right < this.length &&
this.cmp(this.priorityQueue[left], this.priorityQueue[right]) > 0) {
minChild = right;
}
if (this.cmp(this.priorityQueue[minChild], last) >= 0)
break;
this.priorityQueue[parent] = this.priorityQueue[minChild];
parent = minChild;
}
this.priorityQueue[parent] = last;
this.priorityQueue.pop();
}
/**
* @description Accesses the top element.
*/
top() {
return this.priorityQueue[0];
}
}
exports.default = PriorityQueue;