@amaui/heap
Version:
156 lines (120 loc) • 5.69 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import is from '@amaui/utils/is';
export class AmauiNode {
constructor(value) {
this.value = value;
}
}
export class AmauiHeap {
static get min() {
return new AmauiHeap('min');
}
static get max() {
return new AmauiHeap('max');
}
static make(value, variant) {
return new AmauiHeap(variant).make(value);
}
static left(index) {
return 2 * index + 1;
}
static right(index) {
return 2 * index + 2;
}
static parent(index) {
return Math.floor((index - 1) / 2);
}
static isPriority(index) {
return index === 0;
}
static isLeft(index) {
return !!(index !== 0 && index % 2);
}
static isRight(index) {
return !!(index !== 0 && !(index % 2));
}
static isLeaf(index, values) {
return index >= Math.floor(values.length / 2) && index <= values.length - 1;
}
constructor() {
let variant = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'min';
this.variant = variant;
_defineProperty(this, "values", []);
}
get array() {
return this.values.map(item => item.value);
}
get first() {
return this.values[0];
}
get leafs() {
return this.values.filter((_, index) => AmauiHeap.isLeaf(index, this.values));
}
get remove() {
if (!this.values.length) return;
const first = this.first;
const end = this.values.pop();
this.values[0] = end; // Heapify down first values value
this.heapifyDown();
return first;
}
add(value) {
const amauiNode = value instanceof AmauiNode ? value : new AmauiNode(value); // Push to the end of the values array
this.values.push(amauiNode); // Heapify up the added values value
this.heapifyUp();
return this;
}
swap(index, index1) {
[this.values[index], this.values[index1]] = [this.values[index1], this.values[index]];
return this;
}
make(value) {
this.values = value.map(value_ => value_ instanceof AmauiNode ? value_ : new AmauiNode(value_));
for (let i = Math.floor(this.values.length / 2); i >= 0; i--) {
this.heapifyDown(i);
}
return this;
}
forEach(method) {
if (is('function', method)) this.values.forEach((value, index) => {
const parent = this.values[AmauiHeap.parent(index)];
const left = this.values[AmauiHeap.left(index)];
const right = this.values[AmauiHeap.right(index)];
const isPriority = AmauiHeap.isPriority(index);
const isLeaf = AmauiHeap.isLeaf(index, this.values);
const isLeft = AmauiHeap.isLeft(index);
const isRight = AmauiHeap.isRight(index);
method(value, index, parent, left, right, isPriority, isLeaf, isLeft, isRight);
});
}
heapifyUp() {
let index_ = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.values.length - 1;
if (this.values.length > 0) {
let index = index_;
let parentIndex = AmauiHeap.parent(index);
while (index > 0 && (this.variant === 'min' ? ((_this$values$parentIn = this.values[parentIndex]) === null || _this$values$parentIn === void 0 ? void 0 : _this$values$parentIn.value) > ((_this$values$index = this.values[index]) === null || _this$values$index === void 0 ? void 0 : _this$values$index.value) : ((_this$values$parentIn2 = this.values[parentIndex]) === null || _this$values$parentIn2 === void 0 ? void 0 : _this$values$parentIn2.value) < ((_this$values$index2 = this.values[index]) === null || _this$values$index2 === void 0 ? void 0 : _this$values$index2.value))) {
var _this$values$parentIn, _this$values$index, _this$values$parentIn2, _this$values$index2;
// Swap parent and child
this.swap(parentIndex, index);
index = parentIndex;
parentIndex = AmauiHeap.parent(index);
}
}
}
heapifyDown() {
let index_ = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
if (!AmauiHeap.isLeaf(index_, this.values)) {
var _this$values$left, _this$values$swapInde, _this$values$left2, _this$values$swapInde2, _this$values$right, _this$values$swapInde3, _this$values$right2, _this$values$swapInde4;
const index = index_;
const left = AmauiHeap.left(index);
const right = AmauiHeap.right(index);
let swapIndex = index; // Swap left and parent if swap to be made
if (this.variant === 'min' ? ((_this$values$left = this.values[left]) === null || _this$values$left === void 0 ? void 0 : _this$values$left.value) < ((_this$values$swapInde = this.values[swapIndex]) === null || _this$values$swapInde === void 0 ? void 0 : _this$values$swapInde.value) : ((_this$values$left2 = this.values[left]) === null || _this$values$left2 === void 0 ? void 0 : _this$values$left2.value) > ((_this$values$swapInde2 = this.values[swapIndex]) === null || _this$values$swapInde2 === void 0 ? void 0 : _this$values$swapInde2.value)) swapIndex = left; // Swap right and parent if swap to be made
if (this.variant === 'min' ? ((_this$values$right = this.values[right]) === null || _this$values$right === void 0 ? void 0 : _this$values$right.value) < ((_this$values$swapInde3 = this.values[swapIndex]) === null || _this$values$swapInde3 === void 0 ? void 0 : _this$values$swapInde3.value) : ((_this$values$right2 = this.values[right]) === null || _this$values$right2 === void 0 ? void 0 : _this$values$right2.value) > ((_this$values$swapInde4 = this.values[swapIndex]) === null || _this$values$swapInde4 === void 0 ? void 0 : _this$values$swapInde4.value)) swapIndex = right;
if (index !== swapIndex) {
this.swap(index, swapIndex);
this.heapifyDown(swapIndex);
}
}
}
}