Stack
A stack is a LIFO (last-in, first-out) structure: push and pop at the same end (the top). Used in DFS, parsing, undo stacks, and monotonic-stack patterns.
When to use a stack
| Scenario |
Example |
| Matching brackets / tags |
Valid parentheses |
| Reverse processing order |
Evaluate postfix |
| DFS (iterative) |
Explicit stack instead of recursion |
| Monotonic stack |
Next greater element, histogram area |
| Backtracking path |
Current path before undo |
Complexity
| Operation |
List-based stack |
Linked-list stack |
| Push |
O(1)* |
O(1) |
| Pop |
O(1) |
O(1) |
| Peek |
O(1) |
O(1) |
| Search |
O(n) |
O(n) |
| Space |
O(n) |
O(n) |
*Amortized for dynamic array growth on push.
In Python, list.append / list.pop() is the standard stack — no custom class needed unless demonstrating implementation.
Only the top is accessible; every push and pop touches the same end (see diagram).

Monotonic stack (FAANG)
Maintain a stack of indices (or values) that stays monotonically increasing or decreasing. Scan left to right; before pushing, pop while the top violates the property and process the popped index.
| Signal |
Stack type |
Examples |
| Next greater/smaller element |
Decreasing stack of indices |
LC 739, 496 |
| Largest rectangle in histogram |
Increasing stack |
LC 84 |
| Daily temperatures |
Decreasing stack |
LC 739 |
Complexity: each index pushed and popped at most once → O(n) time, O(n) space. See Stack pattern.
Using List
| class StackList:
def __init__(self):
self.stack = []
def push(self, item):
"""Push item onto the stack."""
self.stack.append(item)
def pop(self):
"""Pop item from the stack and return it."""
if not self.is_empty():
return self.stack.pop()
return None
def peek(self):
"""Return the top item of the stack."""
if not self.is_empty():
return self.stack[-1]
return None
def is_empty(self):
"""Check if the stack is empty."""
return len(self.stack) == 0
def size(self):
"""Return the size of the stack."""
return len(self.stack)
def balanced_parentheses(self, expression):
"""Evaluate balanced parentheses."""
for char in expression:
if char == '(':
self.push(char)
elif char == ')':
if self.is_empty():
return False
self.pop()
return self.is_empty()
def infix_to_postfix(self, expression):
"""Convert infix to postfix."""
precedence = {'+': 1, '-': 1, '*': 2, '/': 2, '^': 3}
output = []
for char in expression:
if char.isalnum(): # Operand
output.append(char)
elif char == '(': # Left Parenthesis
self.push(char)
elif char == ')': # Right Parenthesis
while not self.is_empty() and self.peek() != '(':
output.append(self.pop())
self.pop() # Pop '('
else: # Operator
while (not self.is_empty() and self.peek() != '(' and
precedence[char] <= precedence.get(self.peek(), 0)):
output.append(self.pop())
self.push(char)
while not self.is_empty():
output.append(self.pop())
return ''.join(output)
def evaluate_postfix(self, expression):
"""Evaluate a postfix expression."""
for char in expression:
if char.isdigit(): # Operand
self.push(int(char))
else: # Operator
right = self.pop()
left = self.pop()
if char == '+':
self.push(left + right)
elif char == '-':
self.push(left - right)
elif char == '*':
self.push(left * right)
elif char == '/':
self.push(left / right)
elif char == '^':
self.push(left ** right)
return self.pop()
def infix_to_prefix(self, expression):
"""Convert infix to prefix."""
# Reverse the infix expression
expression = expression[::-1]
expression = expression.replace('(', 'temp').replace(')', '(').replace('temp', ')')
postfix = self.infix_to_postfix(expression)
return postfix[::-1]
def evaluate_prefix(self, expression):
"""Evaluate a prefix expression."""
# Reverse the expression to handle it from left to right
expression = expression[::-1]
for char in expression:
if char.isdigit(): # Operand
self.push(int(char))
else: # Operator
left = self.pop()
right = self.pop()
if char == '+':
self.push(left + right)
elif char == '-':
self.push(left - right)
elif char == '*':
self.push(left * right)
elif char == '/':
self.push(left / right)
elif char == '^':
self.push(left ** right)
return self.pop()
expression = "3 + 5 * (2 - 8)"
# Using Stack with List
stack_list = StackList()
postfix = stack_list.infix_to_postfix(expression)
print("Postfix:", postfix) # Postfix conversion
postfix_eval = stack_list.evaluate_postfix(postfix)
print("Postfix evaluation:", postfix_eval)
prefix = stack_list.infix_to_prefix(expression)
print("Prefix:", prefix) # Prefix conversion
prefix_eval = stack_list.evaluate_prefix(prefix)
print("Prefix evaluation:", prefix_eval)
|
Using Linked List
| class Node:
def __init__(self, data):
self.data = data
self.next = None
class StackLinkedList:
def __init__(self):
self.top = None
def push(self, item):
"""Push item onto the stack."""
new_node = Node(item)
new_node.next = self.top
self.top = new_node
def pop(self):
"""Pop item from the stack and return it."""
if self.is_empty():
return None
popped_node = self.top
self.top = self.top.next
return popped_node.data
def peek(self):
"""Return the top item of the stack."""
if self.is_empty():
return None
return self.top.data
def is_empty(self):
"""Check if the stack is empty."""
return self.top is None
def size(self):
"""Return the size of the stack."""
current = self.top
count = 0
while current:
count += 1
current = current.next
return count
def balanced_parentheses(self, expression):
"""Evaluate balanced parentheses."""
for char in expression:
if char == '(':
self.push(char)
elif char == ')':
if self.is_empty():
return False
self.pop()
return self.is_empty()
def infix_to_postfix(self, expression):
"""Convert infix to postfix."""
precedence = {'+': 1, '-': 1, '*': 2, '/': 2, '^': 3}
output = []
for char in expression:
if char.isalnum(): # Operand
output.append(char)
elif char == '(': # Left Parenthesis
self.push(char)
elif char == ')': # Right Parenthesis
while not self.is_empty() and self.peek() != '(':
output.append(self.pop())
self.pop() # Pop '('
else: # Operator
while (not self.is_empty() and self.peek() != '(' and
precedence[char] <= precedence.get(self.peek(), 0)):
output.append(self.pop())
self.push(char)
while not self.is_empty():
output.append(self.pop())
return ''.join(output)
def evaluate_postfix(self, expression):
"""Evaluate a postfix expression."""
for char in expression:
if char.isdigit(): # Operand
self.push(int(char))
else: # Operator
right = self.pop()
left = self.pop()
if char == '+':
self.push(left + right)
elif char == '-':
self.push(left - right)
elif char == '*':
self.push(left * right)
elif char == '/':
self.push(left / right)
elif char == '^':
self.push(left ** right)
return self.pop()
def infix_to_prefix(self, expression):
"""Convert infix to prefix."""
# Reverse the infix expression
expression = expression[::-1]
expression = expression.replace('(', 'temp').replace(')', '(').replace('temp', ')')
postfix = self.infix_to_postfix(expression)
return postfix[::-1]
def evaluate_prefix(self, expression):
"""Evaluate a prefix expression."""
# Reverse the expression to handle it from left to right
expression = expression[::-1]
for char in expression:
if char.isdigit(): # Operand
self.push(int(char))
else: # Operator
left = self.pop()
right = self.pop()
if char == '+':
self.push(left + right)
elif char == '-':
self.push(left - right)
elif char == '*':
self.push(left * right)
elif char == '/':
self.push(left / right)
elif char == '^':
self.push(left ** right)
return self.pop()
expression = "3 + 5 * (2 - 8)"
# Using Stack with Linked List
stack_linked_list = StackLinkedList()
postfix = stack_linked_list.infix_to_postfix(expression)
print("Postfix:", postfix) # Postfix conversion
postfix_eval = stack_linked_list.evaluate_postfix(postfix)
print("Postfix evaluation:", postfix_eval)
prefix = stack_linked_list.infix_to_prefix(expression)
print("Prefix:", prefix) # Prefix conversion
prefix_eval = stack_linked_list.evaluate_prefix(prefix)
print("Prefix evaluation:", prefix_eval)
|