Stack: Linked List Implementation
Explore how a stack works using dynamic linked list implementation. Watch how nodes are created, linked, and managed with flexible memory allocation.
Interactive Operations
Linked List Implementation
O(1) Operations
Stack Visualization
HEAD
NULL
Size: 0
Memory: Dynamic allocation
Head: NULL
Current Step:
Select an operation to begin visualization
Complexity Analysis
O(1)
Push
O(1)
Pop
O(1)
Peek
O(n) Space
Dynamic allocation + pointer overhead
Advantages over Array
Dynamic Size: No fixed maximum capacity
Memory Efficient: Only allocates what's needed
No Overflow: Limited only by available memory
Memory Overhead: Extra storage for pointers
Operations
Push
Create new node, link to current head, update head pointer
Pop
Store head value, move head to next, deallocate old head
Peek
Return head node value without modification
Memory Management
• Dynamic Allocation: Nodes created on-demand
• Garbage Collection: Automatic in Java/Python/JS
• Manual Management: Required in C/C++
• Cache Performance: Generally worse than arrays
• Memory Fragmentation: Possible with frequent alloc/dealloc
Implementation
class Node:
    def __init__(self, value):
        self.value = value      # Data stored in the node
        self.next = None        # Reference to next node
class StackLinkedList:
    def __init__(self):
        self.head = None        # Reference to top of stack
        self.size = 0          # Track number of elements
    
    def push(self, value):
        # Create new node
        new_node = Node(value)
        
        # Link new node to current head
        new_node.next = self.head
        
        # Update head to point to new node
        self.head = new_node
        self.size += 1
        return value
    
    def pop(self):
        # Check for stack underflow
        if self.head is None:
            raise Exception("Stack Underflow")
        
        # Get value from head node
        value = self.head.value
        
        # Update head to next node
        self.head = self.head.next
        self.size -= 1
        
        # Note: In languages without garbage collection,
        # you would need to free the memory of the old head
        return value
    
    def peek(self):
        # Check if stack is empty
        if self.head is None:
            raise Exception("Stack is Empty")
        
        return self.head.value
    
    def is_empty(self):
        return self.head is None
    
    def get_size(self):
        return self.size
    
    def display(self):
        # Traverse and display all elements
        current = self.head
        elements = []
        while current:
            elements.append(current.value)
            current = current.next
        return elements