MaxStack

    Download zip
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    last year
    Downloads
    38

    No dependencies

    #MaxStack (Dual-Stack Implementation)

    A maximum stack implementation based on dual-stack data structure, capable of retrieving the maximum value in O(1) time complexity.

    #🚀 Core Features

    â€ĸ 📚 Standard Stack Operations - Supports basic stack operations like push, pop, peek â€ĸ 🔝 O(1) Maximum Value Query - Get maximum value in constant time â€ĸ 🧠 Generic Support - Works with any type implementing the Compare trait â€ĸ ⚡ Efficient Implementation - Optimized space and time complexity using dual-stack approach â€ĸ đŸ›Ąī¸ Exception Safety - Clear error handling for empty stack operations

    #đŸ“Ĩ Installation

    moon add SupremeHuaji/MaxStack

    #🚀 Usage Guide

    #🔨 Creating a MaxStack

    // Create a new empty stack
    let stack = @MaxStack.new()

    // Create type-specific stacks using generics
    let int_stack : MaxStack[Int] = @MaxStack.new()
    let string_stack : MaxStack[String] = @MaxStack.new()

    #➕ Adding Elements

    Use the push() method to add elements to the stack.

    let stack = @MaxStack.new()
    .push(10)
    .push(5)
    .push(20)
    .push(15)

    // Stack now contains: [10, 5, 20, 15] (bottom to top)

    #🔍 Viewing Top Element

    Use the peek() method to view the top element without removing it.

    let stack = @MaxStack.new()
    .push(10)
    .push(20)

    match stack.peek() {
    Ok(value) => println("Top element: \{value}") // Output: Top element: 20
    Err(StackError::EmptyStack) => println("Stack is empty")
    }

    #❌ Removing Elements

    Use the pop() method to remove and return the top element.

    let stack = @MaxStack.new()
    .push(10)
    .push(20)

    match stack.pop() {
    Ok((value, new_stack)) => {
    println("Popped element: \{value}") // Output: Popped element: 20
    // new_stack is the stack after removing the element
    }
    Err(StackError::EmptyStack) => println("Stack is empty, cannot pop")
    }

    #🔝 Getting Maximum Value

    Use the get_max() method to get the maximum value in O(1) time.

    let stack = @MaxStack.new()
    .push(10)
    .push(5)
    .push(20)
    .push(15)

    match stack.get_max() {
    Ok(max_value) => println("Maximum in stack: \{max_value}") // Output: Maximum in stack: 20
    Err(StackError::EmptyStack) => println("Stack is empty, no maximum")
    }

    #📏 Checking Stack Status

    let stack = @MaxStack.new()
    .push(10)
    .push(20)

    // Check if stack is empty
    if stack.is_empty() {
    println("Stack is empty")
    } else {
    println("Stack is not empty")
    }

    // Get stack size
    let size = stack.size()
    println("Stack size: \{size}") // Output: Stack size: 2

    #🧠 Generic Support

    MaxStack supports any type that implements the Compare trait.

    // Integer stack
    let int_stack = @MaxStack.new()
    .push(100)
    .push(50)
    .push(200)

    // Float stack
    let float_stack = @MaxStack.new()
    .push(10.5)
    .push(20.3)
    .push(15.7)

    // String stack (lexicographic comparison)
    let string_stack = @MaxStack.new()
    .push("apple")
    .push("banana")
    .push("cherry")

    #🔄 Method Chaining

    MaxStack supports method chaining for consecutive operations.

    let result = @MaxStack.new()
    .push(10)
    .push(5)
    .push(20)
    .push(15)

    match result.get_max() {
    Ok(max) => println("Maximum: \{max}") // Output: Maximum: 20
    Err(_) => println("Operation failed")
    }

    // Consecutive pop operations
    let stack = @MaxStack.new()
    .push(10)
    .push(20)
    .push(30)

    match stack.pop() {
    Ok((value1, stack1)) => {
    println("First pop: \{value1}") // Output: First pop: 30
    match stack1.pop() {
    Ok((value2, stack2)) => {
    println("Second pop: \{value2}") // Output: Second pop: 20
    match stack2.get_max() {
    Ok(max) => println("Remaining maximum: \{max}") // Output: Remaining maximum: 10
    Err(_) => println("Stack is empty")
    }
    }
    Err(_) => println("Second pop failed")
    }
    }
    Err(_) => println("First pop failed")
    }

    #âš ī¸ Error Handling

    MaxStack provides clear error handling for empty stack operations.

    let empty_stack = @MaxStack.new()

    // Operations on empty stack will return errors
    match empty_stack.peek() {
    Ok(value) => println("Top: \{value}")
    Err(StackError::EmptyStack) => println("Error: Attempting to peek empty stack")
    }

    match empty_stack.pop() {
    Ok((value, new_stack)) => println("Popped: \{value}")
    Err(StackError::EmptyStack) => println("Error: Attempting to pop from empty stack")
    }

    match empty_stack.get_max() {
    Ok(max) => println("Maximum: \{max}")
    Err(StackError::EmptyStack) => println("Error: Attempting to get maximum from empty stack")
    }

    #🚀 Performance Tips & Best Practices

    // ✅ Good: Use method chaining for batch operations
    let efficient_stack = @MaxStack.new()
    .push(10)
    .push(20)
    .push(5)
    .push(30)

    // ✅ Good: Properly handle error cases
    match stack.pop() {
    Ok((value, new_stack)) => {
    // Use value and new_stack for subsequent operations
    process_value(value)
    continue_with_stack(new_stack)
    }
    Err(StackError::EmptyStack) => {
    // Handle empty stack case
    handle_empty_stack()
    }
    }

    // ✅ Good: Leverage O(1) maximum value query advantage
    let stack = build_large_stack()
    match stack.get_max() {
    Ok(max) => println("Quickly found maximum in large stack: \{max}")
    Err(_) => println("Stack is empty")
    }

    #🔧 Implementation Principle

    MaxStack uses dual-stack approach:

    â€ĸ Main Stack (data_stack) - Stores actual data â€ĸ Auxiliary Stack (max_stack) - Stores maximum value at each position

    #Core Algorithm Idea:

    1. Push Operation: Push element to main stack, push current maximum to auxiliary stack
    2. Pop Operation: Pop elements from both stacks simultaneously
    3. GetMax Operation: Directly return top element from auxiliary stack

    This approach ensures all operations are O(1) time complexity.

    #📋 Complete API Reference

    #Constructor Methods

    MethodTime ComplexityDescription
    new()O(1)Create new empty stack

    #Core Operations

    MethodTime ComplexityReturn TypeDescription
    push(value)O(1)MaxStack[T]Push element, return new stack
    pop()O(1)Result[(T, MaxStack[T]), StackError]Pop top element
    peek()O(1)Result[T, StackError]View top element
    get_max()O(1)Result[T, StackError]Get maximum value in stack

    #Query Operations

    MethodTime ComplexityReturn TypeDescription
    is_empty()O(1)BoolCheck if stack is empty
    size()O(1)IntGet number of elements in stack

    #Error Types

    ErrorDescription
    StackError::EmptyStackThrown when operating on empty stack

    #âąī¸ Time Complexity Summary

    OperationTime ComplexitySpace ComplexityDescription
    new()O(1)O(1)Create empty stack
    push()O(1)O(1)Push element
    pop()O(1)O(1)Pop element
    peek()O(1)O(1)View top
    get_max()O(1)O(1)Get maximum
    is_empty()O(1)O(1)Check if empty
    size()O(1)O(1)Get stack size

    Overall Space Complexity: O(n), where n is the number of elements in the stack

    #📜 License

    This project is licensed under the Apache-2.0 License. See LICENSE for details.

    #đŸ“ĸ Contact & Support

    â€ĸ MoonBit Community: moonbit-community â€ĸ GitHub Issues: Report Issues

    👋 If you like this project, please give it a ⭐! Happy coding!

    CompareResult

    pub(all) enum CompareResult {
    NewMax
    EqualMax
    NotMax
    }

    Comparison operation result

    IterationOrder

    pub(all) enum IterationOrder {
    TopToBottom
    BottomToTop
    }

    Stack iteration direction

    MaxStack

    pub struct MaxStack[T] {
    data_stack : Array[T?]
    max_stack : Array[T?]
    size : Int
    auto_resize : Bool
    growth_factor : Double
    }

    MaxStack dual-stack implementation Uses two stacks: one for data storage, one for tracking max values at each position
    impl Eq for MaxStack[T]
    impl Show for MaxStack[T]

    MaxStack::capacity

    fn[T] MaxStack::capacity(self : MaxStack[T]) -> Int

    Get the capacity of the stack

    Example

    println("Stack capacity: \{stack.capacity()}")

    MaxStack::clear

    fn[T] MaxStack::clear(self : MaxStack[T]) -> Unit

    Clear the stack

    Example

    stack.clear() assert_eq!(stack.size(), 0)

    MaxStack::contains

    fn[T : Eq] MaxStack::contains(self : MaxStack[T], target : T) -> Bool

    Check if the stack contains a specific element

    Example

    if stack.contains(42) { println("Stack contains 42") }

    MaxStack::count_if

    fn[T] MaxStack::count_if(self : MaxStack[T], predicate : (T) -> Bool) -> Int

    Count elements in stack that satisfy a condition

    Example

    let count = stack.count_if(fn(x) { x > 10 }) println("Number of elements > 10: \{count}")

    MaxStack::equals

    fn[T : Eq] MaxStack::equals(self : MaxStack[T], other : MaxStack[T]) -> Bool

    Compare if two stacks are equal

    Example

    if stack1.equals(stack2) { println("Stacks are equal") }

    MaxStack::find

    fn[T : Eq] MaxStack::find(self : MaxStack[T], target : T) -> Int?

    Find the position of an element in the stack (counting from the top)

    Example

    match stack.find(42) { Some(index) => println("Found element at position \{index} from top") None => println("Element not found") }

    MaxStack::force_get_max

    fn[T : Compare + Eq] MaxStack::force_get_max(self : MaxStack[T]) -> T raise Error

    Force get current maximum (throws exception on empty stack)

    Example

    try { let max_val = stack.force_get_max()! println("Maximum value: \{max_val}") } catch { StackError::Underflow => println("Stack underflow") }

    MaxStack::force_peek

    fn[T : Compare + Eq] MaxStack::force_peek(self : MaxStack[T]) -> T raise Error

    Force get top element (throws exception on empty stack)

    Example

    try { let top = stack.force_peek()! println("Top: \{top}") } catch { StackError::Underflow => println("Stack underflow") }

    MaxStack::force_pop

    fn[T : Compare + Eq] MaxStack::force_pop(self : MaxStack[T]) -> T raise Error

    Force pop element (throws exception on empty stack)

    Example

    try { let value = stack.force_pop()! println("Popped: \{value}") } catch { StackError::Underflow => println("Stack underflow") }

    MaxStack::force_pop_n

    fn[T : Compare + Eq] MaxStack::force_pop_n(self : MaxStack[T], n : Int) -> Array[T] raise Error

    Batch pop elements (forced version)

    Example

    try { let popped = stack.force_pop_n(3)! println("Popped elements: \{popped}") } catch { StackError::Underflow => println("Not enough elements in stack") }

    MaxStack::get_max

    fn[T : Compare + Eq] MaxStack::get_max(self : MaxStack[T]) -> StackResult[T]

    Get the current maximum value

    Example

    match stack.get_max() { StackResult::Success(max_val) => println("Maximum: \{max_val}") StackResult::Empty => println("Stack is empty") _ => {} }

    MaxStack::get_min

    fn[T : Compare + Eq] MaxStack::get_min(self : MaxStack[T]) -> StackResult[T]

    Get the minimum value in the stack

    Example

    match stack.get_min() { StackResult::Success(min_val) => println("Minimum value: \{min_val}") StackResult::Empty => println("Stack is empty") _ => {} }

    MaxStack::get_nth

    fn[T : Compare + Eq] MaxStack::get_nth(self : MaxStack[T], index : Int) -> StackResult[T]

    Get the nth element in the stack (from top, 0-indexed)

    Example

    match stack.get_nth(2) { StackResult::Success(value) => println("3rd element: \{value}") StackResult::Empty => println("Stack empty or index out of bounds") _ => {} }

    MaxStack::is_empty

    fn[T] MaxStack::is_empty(self : MaxStack[T]) -> Bool

    Check if the stack is empty

    Example

    if stack.is_empty() { println("Stack is empty") }

    MaxStack::is_full

    fn[T] MaxStack::is_full(self : MaxStack[T]) -> Bool

    Check if the stack is full

    Example

    if stack.is_full() { println("Stack is full") }

    MaxStack::iter

    fn[T] MaxStack::iter(self : MaxStack[T], order : IterationOrder, f : (T) -> Unit) -> Unit

    Iterate through elements in the stack

    Example

    stack.iter(IterationOrder::TopToBottom, fn(value) { println("Element: \{value}") })

    MaxStack::peek

    fn[T : Compare + Eq] MaxStack::peek(self : MaxStack[T]) -> StackResult[T]

    Get the top element (without popping)

    Example

    match stack.peek() { StackResult::Success(value) => println("Top: \{value}") StackResult::Empty => println("Stack is empty") _ => {} }

    MaxStack::pop

    fn[T : Compare + Eq] MaxStack::pop(self : MaxStack[T]) -> StackResult[T]

    Pop an element from the stack

    Example

    match stack.pop() { StackResult::Success(value) => println("Popped: \{value}") StackResult::Empty => println("Stack is empty") _ => {} }

    MaxStack::pop_n

    fn[T : Compare + Eq] MaxStack::pop_n(self : MaxStack[T], n : Int) -> Array[T]

    Batch pop elements

    Example

    let popped_values = stack.pop_n(3)

    MaxStack::push

    fn[T : Compare + Eq] MaxStack::push(self : MaxStack[T], value : T) -> Unit raise Error

    Push an element onto the stack

    Example

    let stack = @MaxStack.default() stack.push(42)! stack.push(24)!

    MaxStack::push_all

    fn[T : Compare + Eq] MaxStack::push_all(self : MaxStack[T], values : Array[T]) -> Array[Result[Unit, StackError]]

    Batch push with error handling

    Example

    let results = stack.push_all([1, 2, 3])

    MaxStack::resize

    fn[T] MaxStack::resize(self : MaxStack[T]) -> Unit raise Error

    Resize the stack capacity

    Example

    stack.resize()!

    MaxStack::serialize

    fn[T] MaxStack::serialize(self : MaxStack[T]) -> SerializedMaxStack[T]

    Serialize stack

    Example

    let serialized = stack.serialize()

    MaxStack::size

    fn[T] MaxStack::size(self : MaxStack[T]) -> Int

    Get the size of the stack

    Example

    println("Stack size: \{stack.size()}")

    MaxStack::snapshot

    fn[T] MaxStack::snapshot(self : MaxStack[T]) -> StackSnapshot[T]

    Create a snapshot of the stack

    Example

    let snapshot = stack.snapshot() println("Snapshot timestamp: \{snapshot.timestamp}")

    MaxStack::state

    fn[T] MaxStack::state(self : MaxStack[T]) -> StackState

    Get the current state of the stack

    Example

    match stack.state() { StackState::Empty => println("Empty stack") StackState::Normal => println("Normal") StackState::NearFull => println("Nearly full") StackState::Full => println("Full") }

    MaxStack::stats

    fn[T] MaxStack::stats(self : MaxStack[T]) -> StackStats

    Get stack statistics

    Example

    let stats = stack.stats() println("Usage ratio: \{stats.usage_ratio}")

    MaxStack::to_array

    fn[T] MaxStack::to_array(self : MaxStack[T], order : IterationOrder) -> Array[T]

    Convert the stack to an array

    Example

    let arr = stack.to_array(IterationOrder::TopToBottom)

    MaxStack::try_force_pop

    fn[T : Compare + Eq] MaxStack::try_force_pop(self : MaxStack[T]) -> Result[T, StackError]

    Safe forced pop operation

    Example

    match stack.try_force_pop() { Ok(value) => println("Popped: \{value}") Err(StackError::Underflow) => println("Stack is empty") Err(error) => println("Other error: \{error}") }

    MaxStack::try_push

    fn[T : Compare + Eq] MaxStack::try_push(self : MaxStack[T], value : T) -> Result[Unit, StackError]

    Modified try_push function including Underflow handling

    MaxStackConfig

    pub struct MaxStackConfig {
    initial_capacity : Int
    auto_resize : Bool
    growth_factor : Double
    }

    MaxStack configuration parameters

    SerializedMaxStack

    pub struct SerializedMaxStack[T] {
    data : Array[T]
    max_data : Array[T]
    size : Int
    capacity : Int
    version : Int
    }

    Serialization format

    StackError

    type StackError

    Stack error types

    StackResult

    pub(all) enum StackResult[T] {
    Success(T)
    Empty
    Full
    }

    Stack operation result type

    StackSnapshot

    pub struct StackSnapshot[T] {
    data_stack : Array[T]
    max_stack : Array[T]
    current_size : Int
    current_max : T?
    timestamp : Int
    }

    Stack snapshot (for debugging and analysis)
    impl Eq for StackSnapshot[T]
    impl Show for StackSnapshot[T]

    StackState

    pub(all) enum StackState {
    Empty
    Normal
    NearFull
    Full
    }

    Stack state enumeration

    StackStats

    pub struct StackStats {
    size : Int
    capacity : Int
    usage_ratio : Double
    is_empty : Bool
    is_full : Bool
    }

    Stack statistics
    impl Eq for StackStats
    impl Show for StackStats

    default

    fn[T : Compare + Eq] default() -> MaxStack[T] raise Error

    Create a MaxStack with default configuration

    Example

    let stack = @MaxStack.default()

    deserialize

    fn[T : Compare + Eq] deserialize(data : SerializedMaxStack[T]) -> MaxStack[T] raise Error

    Deserialize stack

    Example

    let stack = @MaxStack.deserialize(serialized_data)!

    from_array

    fn[T : Compare + Eq] from_array(arr : Array[T]) -> MaxStack[T] raise Error

    Create a MaxStack from an array

    Example

    let stack = @MaxStack.from_array([3, 1, 4, 1, 5])

    new

    fn[T : Compare + Eq] new(config : MaxStackConfig) -> MaxStack[T] raise Error

    Create a new MaxStack

    Example

    let config = MaxStackConfig::{ initial_capacity: 10, auto_resize: true, growth_factor: 2.0 } let stack = @MaxStack.new(config)

    safe_operations

    fn[T : Compare + Eq] safe_operations(stack : MaxStack[T], value : T) -> String

    Modified safe_operations function including Underflow handling

    selective_error_handling

    fn[T : Compare + Eq] selective_error_handling(stack : MaxStack[T], value : T) -> Unit raise Error

    Modified selective_error_handling function including Underflow handling

    try_new

    fn[T : Compare + Eq] try_new(config : MaxStackConfig) -> Result[MaxStack[T], StackError]

    Safe creation operation

    Example

    let config = MaxStackConfig::{ initial_capacity: 10, auto_resize: true, growth_factor: 2.0 } match @MaxStack.try_new(config) { Ok(stack) => println("Creation successful") Err(error) => println("Creation failed: \{error}") }

    Powered by MoonBit

    Site sourceReport issueModulesSkillsCLIBuild queueStatistics

    Š 2026 mooncakes.io