UNPKG

ts-data-forge

Version:

[![npm version](https://img.shields.io/npm/v/ts-data-forge.svg)](https://www.npmjs.com/package/ts-data-forge) [![npm downloads](https://img.shields.io/npm/dm/ts-data-forge.svg)](https://www.npmjs.com/package/ts-data-forge) [![License](https://img.shields.

210 lines 7.81 kB
import { Optional } from '../functional/index.mjs'; /** * Interface for a high-performance stack with LIFO (Last-In, First-Out) behavior. * * This interface defines a mutable stack data structure where elements are added to and removed * from the top, following the Last-In, First-Out principle. The implementation uses a dynamic * array for optimal performance, providing O(1) operations for both push and pop operations. * * **LIFO Behavior:** * - **push**: Adds elements to the top of the stack * - **pop**: Removes and returns elements from the top of the stack * - The last element added is the first element to be removed * * **Performance Characteristics:** * - push: O(1) amortized (O(n) when buffer needs resizing) * - pop: O(1) always * - size/isEmpty: O(1) always * - Memory efficient with automatic garbage collection of removed elements * * **Use Cases:** * - Function call management and recursion * - Undo/redo functionality * - Expression evaluation and parsing * - Depth-first search algorithms * - Backtracking algorithms * - Browser history management * * @template T The type of elements stored in the stack. * * @example * ```typescript * import { createStack, Stack } from './stack'; * * // Example 1: Basic LIFO operations * const operationStack: Stack<string> = createStack<string>(); * * operationStack.push("operation1"); // Add to top * operationStack.push("operation2"); // Add to top * operationStack.push("operation3"); // Add to top * * console.log(operationStack.size); // Output: 3 * * // Process operations in LIFO order * console.log(operationStack.pop().unwrap()); // "operation3" (last in, first out) * console.log(operationStack.pop().unwrap()); // "operation2" * console.log(operationStack.size); // Output: 1 * * // Example 2: Undo functionality * type Action = { type: string; data: any; timestamp: number }; * const undoStack: Stack<Action> = createStack<Action>(); * * undoStack.push({ type: "delete", data: { id: 123 }, timestamp: Date.now() }); * undoStack.push({ type: "edit", data: { field: "name", oldValue: "old" }, timestamp: Date.now() }); * * // Undo last action * if (!undoStack.isEmpty) { * const lastAction = undoStack.pop().unwrap(); * console.log(`Undoing: ${lastAction.type}`); * } * ``` */ export type Stack<T> = Readonly<{ /** Checks if the stack is empty. */ isEmpty: boolean; /** The number of elements in the stack. */ size: SizeType.Arr; /** * Removes and returns the element at the top of the stack. * @returns The element at the top of the stack, or `Optional.none` if the stack is empty. */ pop: () => Optional<T>; /** * Adds an element to the top of the stack. * @param value The element to add. */ push: (value: T) => void; }>; /** * Creates a new Stack instance with LIFO (Last-In, First-Out) behavior using a high-performance dynamic array. * * This factory function creates an optimized stack implementation that maintains excellent performance * characteristics for both push and pop operations. The underlying dynamic array automatically * resizes to accommodate growing workloads while providing predictable O(1) operations. * * **Implementation Features:** * - **O(1) push operations** (amortized - occasionally O(n) when resizing) * - **O(1) pop operations** (always) * - **Automatic buffer resizing** - starts at 8 elements, doubles when full * - **Memory efficient** - garbage collects removed elements immediately * - **Dynamic array design** - eliminates need for complex memory management * * **Performance Benefits:** * - No array shifting required for stack operations * - Minimal memory allocation overhead * - Predictable performance under high load * - Efficient memory usage with automatic cleanup * * @template T The type of elements stored in the stack. * @param initialValues Optional array of initial elements to populate the stack. * Elements will be popped in reverse order of how they appear in the array * (last array element will be popped first). * If provided, the initial buffer capacity will be at least twice the array length. * @returns A new Stack instance optimized for high-performance LIFO operations. * * @example * ```typescript * import { createStack } from './stack'; * * // Example 1: Function call simulation * type FunctionCall = { name: string; args: any[]; context: any }; * const callStack = createStack<FunctionCall>(); * * // Simulate function calls (push onto stack) * callStack.push({ name: "main", args: [], context: {} }); // O(1) * callStack.push({ name: "processData", args: [data], context: {} }); // O(1) * callStack.push({ name: "validateInput", args: [input], context: {} }); // O(1) * * // Simulate function returns (pop from stack) * while (!callStack.isEmpty) { * const call = callStack.pop().unwrap(); // O(1) * console.log(`Returning from: ${call.name}`); * } * // Output: * // Returning from: validateInput * // Returning from: processData * // Returning from: main * * // Example 2: Expression evaluation with operator precedence * const operatorStack = createStack<string>(); * const operandStack = createStack<number>(); * * // Simulate parsing "3 + 4 * 2" * operandStack.push(3); * operatorStack.push("+"); * operandStack.push(4); * operatorStack.push("*"); // Higher precedence * operandStack.push(2); * * // Process higher precedence first (LIFO) * const op = operatorStack.pop().unwrap(); // "*" * const b = operandStack.pop().unwrap(); // 2 * const a = operandStack.pop().unwrap(); // 4 * operandStack.push(a * b); // Push result: 8 * * // Example 3: Undo/Redo functionality * type EditAction = { * type: 'insert' | 'delete' | 'modify'; * position: number; * oldValue: string; * newValue: string; * }; * * const undoStack = createStack<EditAction>(); * const redoStack = createStack<EditAction>(); * * // Perform edits (push to undo stack) * const edit1: EditAction = { type: 'insert', position: 0, oldValue: '', newValue: 'Hello' }; * const edit2: EditAction = { type: 'insert', position: 5, oldValue: '', newValue: ' World' }; * * undoStack.push(edit1); * undoStack.push(edit2); * * // Undo last edit * if (!undoStack.isEmpty) { * const lastEdit = undoStack.pop().unwrap(); * redoStack.push(lastEdit); * console.log(`Undid: ${lastEdit.type} at position ${lastEdit.position}`); * } * * // Example 4: High-throughput data processing * const processingStack = createStack<number>(); * * // Add large amount of data (demonstrates amortized O(1) performance) * for (const i of range(100000)) { * processingStack.push(i); // Each push is O(1) amortized * } * * // Process data in LIFO order * let processedCount = 0; * while (!processingStack.isEmpty) { * const value = processingStack.pop().unwrap(); // O(1) * // Process value... * processedCount++; * } * console.log(`Processed ${processedCount} items`); // 100000 * * // Example 5: Stack with pre-populated data * const historyStack = createStack<string>([ * "page1.html", * "page2.html", * "page3.html", * "page4.html" * ]); * * console.log(historyStack.size); // Output: 4 * * // Navigate back through history (LIFO order) * while (!historyStack.isEmpty) { * const page = historyStack.pop().unwrap(); * console.log(`Going back to: ${page}`); * } * // Output: * // Going back to: page4.html (last added, first removed) * // Going back to: page3.html * // Going back to: page2.html * // Going back to: page1.html * ``` */ export declare const createStack: <T>(initialValues?: readonly T[]) => Stack<T>; //# sourceMappingURL=stack.d.mts.map