UNPKG

@amaui/heap

Version:
156 lines (120 loc) 5.69 kB
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); } } } }