UNPKG

min-priority-queue-typed

Version:
1,754 lines (1,195 loc) 41.5 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); // src/common/error.ts function raise(ErrorClass, message) { throw new ErrorClass(message); } __name(raise, "raise"); var ERR = { // Range / index indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"), invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"), // Type / argument invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"), comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"), invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"), notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"), invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"), invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"), invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"), reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"), callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"), // State / operation invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"), // Matrix matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"), matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"), matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"), matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"), matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch"), // Order statistic orderStatisticNotEnabled: /* @__PURE__ */ __name((method, ctx) => `${ctx ? ctx + ": " : ""}${method}() requires enableOrderStatistic: true.`, "orderStatisticNotEnabled") }; // src/common/index.ts var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => { DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT"; DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS"; return DFSOperation2; })(DFSOperation || {}); var _Range = class _Range { constructor(low, high, includeLow = true, includeHigh = true) { this.low = low; this.high = high; this.includeLow = includeLow; this.includeHigh = includeHigh; } // Determine whether a key is within the range isInRange(key, comparator) { const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0; const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0; return lowCheck && highCheck; } }; __name(_Range, "Range"); var Range = _Range; // src/data-structures/base/iterable-element-base.ts var _IterableElementBase = class _IterableElementBase { /** * Create a new iterable base. * * @param options Optional behavior overrides. When provided, a `toElementFn` * is used to convert a raw element (`R`) into a public element (`E`). * * @remarks * Time O(1), Space O(1). */ constructor(options) { /** * The converter used to transform a raw element (`R`) into a public element (`E`). * * @remarks * Time O(1), Space O(1). */ __publicField(this, "_toElementFn"); if (options) { const { toElementFn } = options; if (typeof toElementFn === "function") this._toElementFn = toElementFn; else if (toElementFn) raise(TypeError, "toElementFn must be a function type"); } } /** * Exposes the current `toElementFn`, if configured. * * @returns The converter function or `undefined` when not set. * @remarks * Time O(1), Space O(1). */ get toElementFn() { return this._toElementFn; } /** * Returns an iterator over the structure's elements. * * @param args Optional iterator arguments forwarded to the internal iterator. * @returns An `IterableIterator<E>` that yields the elements in traversal order. * * @remarks * Producing the iterator is O(1); consuming the entire iterator is Time O(n) with O(1) extra space. */ *[Symbol.iterator](...args) { yield* this._getIterator(...args); } /** * Returns an iterator over the values (alias of the default iterator). * * @returns An `IterableIterator<E>` over all elements. * @remarks * Creating the iterator is O(1); full iteration is Time O(n), Space O(1). */ *values() { for (const item of this) yield item; } /** * Tests whether all elements satisfy the predicate. * * @template TReturn * @param predicate Function invoked for each element with signature `(value, index, self)`. * @param thisArg Optional `this` binding for the predicate. * @returns `true` if every element passes; otherwise `false`. * * @remarks * Time O(n) in the worst case; may exit early when the first failure is found. Space O(1). */ every(predicate, thisArg) { let index = 0; for (const item of this) { if (thisArg === void 0) { if (!predicate(item, index++, this)) return false; } else { const fn = predicate; if (!fn.call(thisArg, item, index++, this)) return false; } } return true; } /** * Tests whether at least one element satisfies the predicate. * * @param predicate Function invoked for each element with signature `(value, index, self)`. * @param thisArg Optional `this` binding for the predicate. * @returns `true` if any element passes; otherwise `false`. * * @remarks * Time O(n) in the worst case; may exit early on first success. Space O(1). */ some(predicate, thisArg) { let index = 0; for (const item of this) { if (thisArg === void 0) { if (predicate(item, index++, this)) return true; } else { const fn = predicate; if (fn.call(thisArg, item, index++, this)) return true; } } return false; } /** * Invokes a callback for each element in iteration order. * * @param callbackfn Function invoked per element with signature `(value, index, self)`. * @param thisArg Optional `this` binding for the callback. * @returns `void`. * * @remarks * Time O(n), Space O(1). */ forEach(callbackfn, thisArg) { let index = 0; for (const item of this) { if (thisArg === void 0) { callbackfn(item, index++, this); } else { const fn = callbackfn; fn.call(thisArg, item, index++, this); } } } // Implementation signature find(predicate, thisArg) { let index = 0; for (const item of this) { if (thisArg === void 0) { if (predicate(item, index++, this)) return item; } else { const fn = predicate; if (fn.call(thisArg, item, index++, this)) return item; } } return; } /** * Checks whether a strictly-equal element exists in the structure. * * @param element The element to test with `===` equality. * @returns `true` if an equal element is found; otherwise `false`. * * @remarks * Time O(n) in the worst case. Space O(1). */ has(element) { for (const ele of this) if (ele === element) return true; return false; } /** * Check whether a value exists (Array-compatible alias for `has`). * @remarks Provided for familiarity when migrating from Array. Time O(n), Space O(1). * @param element - Element to search for (uses `===`). * @returns `true` if found. */ includes(element) { return this.has(element); } /** * Return an iterator of `[index, value]` pairs (Array-compatible). * @remarks Provided for familiarity when migrating from Array. Time O(n), Space O(1) per step. */ *entries() { let index = 0; for (const value of this) { yield [index++, value]; } } /** * Return an iterator of numeric indices (Array-compatible). * @remarks Provided for familiarity when migrating from Array. Time O(n), Space O(1) per step. */ *keys() { let index = 0; for (const _ of this) { yield index++; } } /** * Reduces all elements to a single accumulated value. * * @overload * @param callbackfn Reducer of signature `(acc, value, index, self) => nextAcc`. The first element is used as the initial accumulator. * @returns The final accumulated value typed as `E`. * * @overload * @param callbackfn Reducer of signature `(acc, value, index, self) => nextAcc`. * @param initialValue The initial accumulator value of type `E`. * @returns The final accumulated value typed as `E`. * * @overload * @template U The accumulator type when it differs from `E`. * @param callbackfn Reducer of signature `(acc: U, value, index, self) => U`. * @param initialValue The initial accumulator value of type `U`. * @returns The final accumulated value typed as `U`. * * @remarks * Time O(n), Space O(1). Throws if called on an empty structure without `initialValue`. */ reduce(callbackfn, initialValue) { let index = 0; const iter = this[Symbol.iterator](); let acc; if (arguments.length >= 2) { acc = initialValue; } else { const first = iter.next(); if (first.done) raise(TypeError, "Reduce of empty structure with no initial value"); acc = first.value; index = 1; } for (const value of iter) { acc = callbackfn(acc, value, index++, this); } return acc; } /** * Materializes the elements into a new array. * * @returns A shallow array copy of the iteration order. * @remarks * Time O(n), Space O(n). */ toArray() { return [...this]; } /** * Returns a representation of the structure suitable for quick visualization. * Defaults to an array of elements; subclasses may override to provide richer visuals. * * @returns A visual representation (array by default). * @remarks * Time O(n), Space O(n). */ toVisual() { return [...this]; } /** * Prints `toVisual()` to the console. Intended for quick debugging. * * @returns `void`. * @remarks * Time O(n) due to materialization, Space O(n) for the intermediate representation. */ print() { console.log(this.toVisual()); } }; __name(_IterableElementBase, "IterableElementBase"); var IterableElementBase = _IterableElementBase; // src/data-structures/heap/heap.ts var _Heap = class _Heap extends IterableElementBase { /** * Create a Heap and optionally bulk-insert elements. * @remarks Time O(N), Space O(N) * @param [elements] - Iterable of elements (or raw values if toElementFn is set). * @param [options] - Options such as comparator and toElementFn. * @returns New Heap instance. */ constructor(elements = [], options) { super(options); __publicField(this, "_equals", Object.is); __publicField(this, "_elements", []); __publicField(this, "_DEFAULT_COMPARATOR", /* @__PURE__ */ __name((a, b) => { if (typeof a === "object" || typeof b === "object") { raise(TypeError, ERR.comparatorRequired("Heap")); } if (a > b) return 1; if (a < b) return -1; return 0; }, "_DEFAULT_COMPARATOR")); __publicField(this, "_comparator", this._DEFAULT_COMPARATOR); if (options) { const { comparator } = options; if (comparator) this._comparator = comparator; } this.addMany(elements); } /** * Get the backing array of the heap. * @remarks Time O(1), Space O(1) * @returns Internal elements array. */ get elements() { return this._elements; } /** * Get the number of elements. * @remarks Time O(1), Space O(1) * @returns Heap size. * @example * // Track heap capacity * const heap = new Heap<number>(); * console.log(heap.size); // 0; * heap.add(10); * heap.add(20); * console.log(heap.size); // 2; * heap.poll(); * console.log(heap.size); // 1; */ get size() { return this.elements.length; } /** * Get the last leaf element. * @remarks Time O(1), Space O(1) * @returns Last element or undefined. */ get leaf() { var _a; return (_a = this.elements[this.size - 1]) != null ? _a : void 0; } /** * Create a heap of the same class from an iterable. * @remarks Time O(N), Space O(N) * @template T * @template R * @template S * @param [elements] - Iterable of elements or raw records. * @param [options] - Heap options including comparator. * @returns A new heap instance of this class. */ static from(elements, options) { return new this(elements, options); } /** * Build a Heap from an iterable in linear time given a comparator. * @remarks Time O(N), Space O(N) * @template EE * @template RR * @param elements - Iterable of elements. * @param options - Heap options including comparator. * @returns A new Heap built from elements. */ static heapify(elements, options) { return new _Heap(elements, options); } /** * Insert an element. * @remarks Time O(log N) amortized, Space O(1) * @param element - Element to insert. * @returns True. * @example * // basic Heap creation and add operation * // Create a min heap (default) * const minHeap = new Heap([5, 3, 7, 1, 9, 2]); * * // Verify size * console.log(minHeap.size); // 6; * * // Add new element * minHeap.add(4); * console.log(minHeap.size); // 7; * * // Min heap property: smallest element at root * const min = minHeap.peek(); * console.log(min); // 1; */ add(element) { this._elements.push(element); return this._bubbleUp(this.elements.length - 1); } /** * Insert many elements from an iterable. * @remarks Time O(N log N), Space O(1) * @param elements - Iterable of elements or raw values. * @returns Array of per-element success flags. * @example * // Add multiple elements * const heap = new Heap<number>([], { comparator: (a, b) => a - b }); * heap.addMany([5, 3, 7, 1]); * console.log(heap.peek()); // 1; * console.log(heap.size); // 4; */ addMany(elements) { const flags = []; for (const el of elements) { if (this.toElementFn) { const ok = this.add(this.toElementFn(el)); flags.push(ok); } else { const ok = this.add(el); flags.push(ok); } } return flags; } /** * Remove and return the top element. * @remarks Time O(log N), Space O(1) * @returns Top element or undefined. * @example * // Heap with custom comparator (MaxHeap behavior) * interface Task { * id: number; * priority: number; * name: string; * } * * // Custom comparator for max heap behavior (higher priority first) * const tasks: Task[] = [ * { id: 1, priority: 5, name: 'Email' }, * { id: 2, priority: 3, name: 'Chat' }, * { id: 3, priority: 8, name: 'Alert' } * ]; * * const maxHeap = new Heap(tasks, { * comparator: (a: Task, b: Task) => b.priority - a.priority * }); * * console.log(maxHeap.size); // 3; * * // Peek returns highest priority task * const topTask = maxHeap.peek(); * console.log(topTask?.priority); // 8; * console.log(topTask?.name); // 'Alert'; */ /** * @deprecated Use `pop` instead. Will be removed in a future major version. * @example * // Heap with custom comparator (MaxHeap behavior) * interface Task { * id: number; * priority: number; * name: string; * } * * // Custom comparator for max heap behavior (higher priority first) * const tasks: Task[] = [ * { id: 1, priority: 5, name: 'Email' }, * { id: 2, priority: 3, name: 'Chat' }, * { id: 3, priority: 8, name: 'Alert' } * ]; * * const maxHeap = new Heap(tasks, { * comparator: (a: Task, b: Task) => b.priority - a.priority * }); * * console.log(maxHeap.size); // 3; * * // Peek returns highest priority task * const topTask = maxHeap.peek(); * console.log(topTask?.priority); // 8; * console.log(topTask?.name); // 'Alert'; */ poll() { return this.pop(); } /** * Remove and return the top element (min or max depending on comparator). * @remarks Time O(log N) amortized, Space O(1) * @returns The removed top element, or undefined if empty. */ pop() { if (this.elements.length === 0) return; const value = this.elements[0]; const last = this.elements.pop(); if (this.elements.length) { this.elements[0] = last; this._sinkDown(0, this.elements.length >> 1); } return value; } /** * Get the current top element without removing it. * @remarks Time O(1), Space O(1) * @returns Top element or undefined. * @example * // Heap for event processing with priority * interface Event { * id: number; * type: 'critical' | 'warning' | 'info'; * timestamp: number; * message: string; * } * * // Custom priority: critical > warning > info * const priorityMap = { critical: 3, warning: 2, info: 1 }; * * const eventHeap = new Heap<Event>([], { * comparator: (a: Event, b: Event) => { * const priorityA = priorityMap[a.type]; * const priorityB = priorityMap[b.type]; * return priorityB - priorityA; // Higher priority first * } * }); * * // Add events in random order * eventHeap.add({ id: 1, type: 'info', timestamp: 100, message: 'User logged in' }); * eventHeap.add({ id: 2, type: 'critical', timestamp: 101, message: 'Server down' }); * eventHeap.add({ id: 3, type: 'warning', timestamp: 102, message: 'High memory' }); * eventHeap.add({ id: 4, type: 'info', timestamp: 103, message: 'Cache cleared' }); * eventHeap.add({ id: 5, type: 'critical', timestamp: 104, message: 'Database error' }); * * console.log(eventHeap.size); // 5; * * // Process events by priority (critical first) * const processedOrder: Event[] = []; * while (eventHeap.size > 0) { * const event = eventHeap.poll(); * if (event) { * processedOrder.push(event); * } * } * * // Verify critical events came first * console.log(processedOrder[0].type); // 'critical'; * console.log(processedOrder[1].type); // 'critical'; * console.log(processedOrder[2].type); // 'warning'; * console.log(processedOrder[3].type); // 'info'; * console.log(processedOrder[4].type); // 'info'; * * // Verify O(log n) operations * const newHeap = new Heap<number>([5, 3, 7, 1]); * * // Add - O(log n) * newHeap.add(2); * console.log(newHeap.size); // 5; * * // Poll - O(log n) * const removed = newHeap.poll(); * console.log(removed); // 1; * * // Peek - O(1) * const top = newHeap.peek(); * console.log(top); // 2; */ peek() { return this.elements[0]; } /** * Check whether the heap is empty. * @remarks Time O(1), Space O(1) * @returns True if size is 0. * @example * // Check if heap is empty * const heap = new Heap<number>([], { comparator: (a, b) => a - b }); * console.log(heap.isEmpty()); // true; * heap.add(1); * console.log(heap.isEmpty()); // false; */ isEmpty() { return this.size === 0; } /** * Remove all elements. * @remarks Time O(1), Space O(1) * @returns void * @example * // Remove all elements * const heap = new Heap<number>([1, 2, 3], { comparator: (a, b) => a - b }); * heap.clear(); * console.log(heap.isEmpty()); // true; */ clear() { this._elements = []; } /** * Check if an equal element exists in the heap. * @remarks Time O(N), Space O(1) * @param element - Element to search for. * @returns True if found. * @example * // Check element existence * const heap = new Heap<number>([3, 1, 2], { comparator: (a, b) => a - b }); * console.log(heap.has(1)); // true; * console.log(heap.has(99)); // false; */ has(element) { for (const el of this.elements) if (this._equals(el, element)) return true; return false; } /** * Delete one occurrence of an element. * @remarks Time O(N), Space O(1) * @param element - Element to delete. * @returns True if an element was removed. * @example * // Remove specific element * const heap = new Heap<number>([3, 1, 4, 1, 5], { comparator: (a, b) => a - b }); * heap.delete(4); * console.log(heap.toArray().includes(4)); // false; */ delete(element) { let index = -1; for (let i = 0; i < this.elements.length; i++) { if (this._equals(this.elements[i], element)) { index = i; break; } } if (index < 0) return false; if (index === 0) { this.pop(); } else if (index === this.elements.length - 1) { this.elements.pop(); } else { this.elements.splice(index, 1, this.elements.pop()); this._bubbleUp(index); this._sinkDown(index, this.elements.length >> 1); } return true; } /** * @deprecated Use `deleteWhere` instead. Will be removed in a future major version. */ deleteBy(predicate) { return this.deleteWhere(predicate); } /** * Delete the first element that matches a predicate. * @remarks Time O(N), Space O(1) * @param predicate - Function (element, index, heap) → boolean. * @returns True if an element was removed. */ deleteWhere(predicate) { let idx = -1; for (let i = 0; i < this.elements.length; i++) { if (predicate(this.elements[i], i, this)) { idx = i; break; } } if (idx < 0) return false; if (idx === 0) { this.pop(); } else if (idx === this.elements.length - 1) { this.elements.pop(); } else { this.elements.splice(idx, 1, this.elements.pop()); this._bubbleUp(idx); this._sinkDown(idx, this.elements.length >> 1); } return true; } /** * Set the equality comparator used by has/delete operations. * @remarks Time O(1), Space O(1) * @param equals - Equality predicate (a, b) → boolean. * @returns This heap. */ setEquality(equals) { this._equals = equals; return this; } /** * Traverse the binary heap as a complete binary tree and collect elements. * @remarks Time O(N), Space O(H) * @param [order] - Traversal order: 'PRE' | 'IN' | 'POST'. * @returns Array of visited elements. * @example * // Depth-first traversal * const heap = new Heap<number>([3, 1, 2], { comparator: (a, b) => a - b }); * const result = heap.dfs('IN'); * console.log(result.length); // 3; */ dfs(order = "PRE") { const result = []; const _dfs = /* @__PURE__ */ __name((index) => { const left = 2 * index + 1, right = left + 1; if (index < this.size) { if (order === "IN") { _dfs(left); result.push(this.elements[index]); _dfs(right); } else if (order === "PRE") { result.push(this.elements[index]); _dfs(left); _dfs(right); } else if (order === "POST") { _dfs(left); _dfs(right); result.push(this.elements[index]); } } }, "_dfs"); _dfs(0); return result; } /** * Restore heap order bottom-up (heapify in-place). * @remarks Time O(N), Space O(1) * @returns Array of per-node results from fixing steps. */ fix() { const results = []; for (let i = Math.floor(this.size / 2) - 1; i >= 0; i--) { results.push(this._sinkDown(i, this.elements.length >> 1)); } return results; } /** * Return all elements in ascending order by repeatedly polling. * @remarks Time O(N log N), Space O(N) * @returns Sorted array of elements. * @example * // Sort elements using heap * const heap = new Heap<number>([5, 1, 3, 2, 4]); * const sorted = heap.sort(); * console.log(sorted); // [1, 2, 3, 4, 5]; */ sort() { const visited = []; const cloned = this._createInstance(); for (const x of this.elements) cloned.add(x); while (!cloned.isEmpty()) { const top = cloned.poll(); if (top !== void 0) visited.push(top); } return visited; } /** * Deep clone this heap. * @remarks Time O(N), Space O(N) * @returns A new heap with the same elements. * @example * // Create independent copy * const heap = new Heap<number>([3, 1, 4], { comparator: (a, b) => a - b }); * const copy = heap.clone(); * copy.poll(); * console.log(heap.size); // 3; * console.log(copy.size); // 2; */ clone() { const next = this._createInstance(); for (const x of this.elements) next.add(x); return next; } /** * Filter elements into a new heap of the same class. * @remarks Time O(N log N), Space O(N) * @param callback - Predicate (element, index, heap) → boolean to keep element. * @param [thisArg] - Value for `this` inside the callback. * @returns A new heap with the kept elements. * @example * // Filter elements * const heap = new Heap<number>([1, 2, 3, 4, 5], { comparator: (a, b) => a - b }); * const evens = heap.filter(x => x % 2 === 0); * console.log(evens.size); // 2; */ filter(callback, thisArg) { const out = this._createInstance(); let i = 0; for (const x of this) { if (thisArg === void 0 ? callback(x, i++, this) : callback.call(thisArg, x, i++, this)) { out.add(x); } else { i++; } } return out; } /** * Map elements into a new heap of possibly different element type. * @remarks Time O(N log N), Space O(N) * @template EM * @template RM * @param callback - Mapping function (element, index, heap) → newElement. * @param options - Options for the output heap, including comparator for EM. * @param [thisArg] - Value for `this` inside the callback. * @returns A new heap with mapped elements. * @example * // Transform elements * const heap = new Heap<number>([1, 2, 3], { comparator: (a, b) => a - b }); * const doubled = heap.map(x => x * 2, { comparator: (a, b) => a - b }); * console.log(doubled.peek()); // 2; */ map(callback, options, thisArg) { const { comparator, toElementFn, ...rest } = options != null ? options : {}; if (!comparator) raise(TypeError, ERR.comparatorRequired("Heap.map")); const out = this._createLike([], { ...rest, comparator, toElementFn }); let i = 0; for (const x of this) { const v = thisArg === void 0 ? callback(x, i++, this) : callback.call(thisArg, x, i++, this); out.add(v); } return out; } /** * Map elements into a new heap of the same element type. * @remarks Time O(N log N), Space O(N) * @param callback - Mapping function (element, index, heap) → element. * @param [thisArg] - Value for `this` inside the callback. * @returns A new heap with mapped elements. */ mapSame(callback, thisArg) { const out = this._createInstance(); let i = 0; for (const x of this) { const v = thisArg === void 0 ? callback(x, i++, this) : callback.call(thisArg, x, i++, this); out.add(v); } return out; } /** * Get the comparator used to order elements. * @remarks Time O(1), Space O(1) * @returns Comparator function. */ get comparator() { return this._comparator; } *_getIterator() { for (const element of this.elements) yield element; } _bubbleUp(index) { const element = this.elements[index]; while (index > 0) { const parent = index - 1 >> 1; const parentItem = this.elements[parent]; if (this.comparator(parentItem, element) <= 0) break; this.elements[index] = parentItem; index = parent; } this.elements[index] = element; return true; } _sinkDown(index, halfLength) { const element = this.elements[index]; while (index < halfLength) { let left = index << 1 | 1; const right = left + 1; let minItem = this.elements[left]; if (right < this.elements.length && this.comparator(minItem, this.elements[right]) > 0) { left = right; minItem = this.elements[right]; } if (this.comparator(minItem, element) >= 0) break; this.elements[index] = minItem; index = left; } this.elements[index] = element; return true; } /** * (Protected) Create an empty instance of the same concrete class. * @remarks Time O(1), Space O(1) * @param [options] - Options to override comparator or toElementFn. * @returns A like-kind empty heap instance. */ _createInstance(options) { const Ctor = this.constructor; return new Ctor([], { comparator: this.comparator, toElementFn: this.toElementFn, ...options != null ? options : {} }); } /** * (Protected) Create a like-kind instance seeded by elements. * @remarks Time O(N log N), Space O(N) * @template EM * @template RM * @param [elements] - Iterable of elements or raw values to seed. * @param [options] - Options forwarded to the constructor. * @returns A like-kind heap instance. */ _createLike(elements = [], options) { const Ctor = this.constructor; return new Ctor(elements, options); } /** * (Protected) Spawn an empty like-kind heap instance. * @remarks Time O(1), Space O(1) * @template EM * @template RM * @param [options] - Options forwarded to the constructor. * @returns An empty like-kind heap instance. */ _spawnLike(options) { return this._createLike([], options); } }; __name(_Heap, "Heap"); var Heap = _Heap; var _FibonacciHeapNode = class _FibonacciHeapNode { constructor(element, degree = 0) { __publicField(this, "element"); __publicField(this, "degree"); __publicField(this, "left"); __publicField(this, "right"); __publicField(this, "child"); __publicField(this, "parent"); __publicField(this, "marked"); this.element = element; this.degree = degree; this.marked = false; } }; __name(_FibonacciHeapNode, "FibonacciHeapNode"); var FibonacciHeapNode = _FibonacciHeapNode; var _FibonacciHeap = class _FibonacciHeap { /** * Create a FibonacciHeap. * @remarks Time O(1), Space O(1) * @param [comparator] - Comparator to order elements (min-heap by default). * @returns New FibonacciHeap instance. */ constructor(comparator) { __publicField(this, "_root"); __publicField(this, "_size", 0); __publicField(this, "_min"); __publicField(this, "_comparator"); this.clear(); this._comparator = comparator || this._defaultComparator; if (typeof this.comparator !== "function") raise(TypeError, ERR.notAFunction("comparator", "FibonacciHeap")); } /** * Get the circular root list head. * @remarks Time O(1), Space O(1) * @returns Root node or undefined. */ get root() { return this._root; } get size() { return this._size; } /** * Get the current minimum node. * @remarks Time O(1), Space O(1) * @returns Min node or undefined. */ get min() { return this._min; } get comparator() { return this._comparator; } clear() { this._root = void 0; this._min = void 0; this._size = 0; } add(element) { this.push(element); return true; } /** * Push an element into the root list. * @remarks Time O(1) amortized, Space O(1) * @param element - Element to insert. * @returns True when the element is added. */ push(element) { const node = this.createNode(element); node.left = node; node.right = node; this.mergeWithRoot(node); if (!this.min || this.comparator(node.element, this.min.element) <= 0) this._min = node; this._size++; return true; } peek() { return this.min ? this.min.element : void 0; } /** * Collect nodes from a circular doubly linked list starting at head. * @remarks Time O(K), Space O(K) * @param [head] - Start node of the circular list. * @returns Array of nodes from the list. */ consumeLinkedList(head) { const elements = []; if (!head) return elements; let node = head; let started = false; while (true) { if (node === head && started) break; else if (node === head) started = true; elements.push(node); node = node.right; } return elements; } /** * Insert a node into a parent's child list (circular). * @remarks Time O(1), Space O(1) * @param parent - Parent node. * @param node - Child node to insert. * @returns void */ mergeWithChild(parent, node) { if (!parent.child) parent.child = node; else { node.right = parent.child.right; node.left = parent.child; parent.child.right.left = node; parent.child.right = node; } } poll() { return this.pop(); } /** * Remove and return the minimum element, consolidating the root list. * @remarks Time O(log N) amortized, Space O(1) * @returns Minimum element or undefined. */ pop() { if (this._size === 0) return void 0; const z = this.min; if (z.child) { const elements = this.consumeLinkedList(z.child); for (const node of elements) { this.mergeWithRoot(node); node.parent = void 0; } } this.removeFromRoot(z); if (z === z.right) { this._min = void 0; this._root = void 0; } else { this._min = z.right; this._consolidate(); } this._size--; return z.element; } /** * Meld another heap into this heap. * @remarks Time O(1), Space O(1) * @param heapToMerge - Another FibonacciHeap to meld into this one. * @returns void */ merge(heapToMerge) { if (heapToMerge.size === 0) return; if (this.root && heapToMerge.root) { const thisRoot = this.root, otherRoot = heapToMerge.root; const thisRootRight = thisRoot.right, otherRootLeft = otherRoot.left; thisRoot.right = otherRoot; otherRoot.left = thisRoot; thisRootRight.left = otherRootLeft; otherRootLeft.right = thisRootRight; } else if (!this.root && heapToMerge.root) { this._root = heapToMerge.root; } if (!this.min || heapToMerge.min && this.comparator(heapToMerge.min.element, this.min.element) < 0) { this._min = heapToMerge.min; } this._size += heapToMerge.size; heapToMerge.clear(); } createNode(element) { return new FibonacciHeapNode(element); } isEmpty() { return this._size === 0; } _defaultComparator(a, b) { if (a < b) return -1; if (a > b) return 1; return 0; } mergeWithRoot(node) { if (!this.root) this._root = node; else { node.right = this.root.right; node.left = this.root; this.root.right.left = node; this.root.right = node; } } removeFromRoot(node) { if (this.root === node) this._root = node.right; if (node.left) node.left.right = node.right; if (node.right) node.right.left = node.left; } _link(y, x) { this.removeFromRoot(y); y.left = y; y.right = y; this.mergeWithChild(x, y); x.degree++; y.parent = x; } _consolidate() { const A = new Array(this._size); const elements = this.consumeLinkedList(this.root); let x, y, d, t; for (const node of elements) { x = node; d = x.degree; while (A[d]) { y = A[d]; if (this.comparator(x.element, y.element) > 0) { t = x; x = y; y = t; } this._link(y, x); A[d] = void 0; d++; } A[d] = x; } for (let i = 0; i < A.length; i++) { if (A[i] && (!this.min || this.comparator(A[i].element, this.min.element) <= 0)) this._min = A[i]; } } }; __name(_FibonacciHeap, "FibonacciHeap"); var FibonacciHeap = _FibonacciHeap; // src/data-structures/priority-queue/priority-queue.ts var _PriorityQueue = class _PriorityQueue extends Heap { constructor(elements = [], options) { super(elements, options); } }; __name(_PriorityQueue, "PriorityQueue"); var PriorityQueue = _PriorityQueue; // src/data-structures/priority-queue/min-priority-queue.ts var _MinPriorityQueue = class _MinPriorityQueue extends PriorityQueue { /** * Creates a min-priority queue. * @param elements Optional initial elements to insert. * @param options Optional configuration (e.g., `comparator`, `toElementFn`). * @remarks Complexity — Time: O(n log n) when inserting n elements incrementally; Space: O(n). */ constructor(elements = [], options) { super(elements, options); } }; __name(_MinPriorityQueue, "MinPriorityQueue"); var MinPriorityQueue = _MinPriorityQueue; /** * data-structure-typed * * @author Pablo Zeng * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com> * @license MIT License */ /** * data-structure-typed * * @author Kirk Qi * @copyright Copyright (c) 2022 Kirk Qi <qilinaus@gmail.com> * @license MIT License */ export { DFSOperation, ERR, FibonacciHeap, FibonacciHeapNode, Heap, MinPriorityQueue, PriorityQueue, Range, raise }; //# sourceMappingURL=index.mjs.map //# sourceMappingURL=index.mjs.map