A stack is a linear data structure that enforces Last-In, First-Out (LIFO) ordering: the most recently added item is the first one removed. Think of a stack of plates—add to the top, remove from the top.
Time complexity for push/pop/peek is typically O(1); size can be O(1) if tracked, or O(n) if computed on demand.
Underflow occurs when popping an empty stack; always check emptiness or handle exceptions.
class Stack:
def __init__(self):
self._data = []
def push(self, x):
self._data.append(x)
def pop(self):
if not self._data:
raise IndexError("pop from empty stack")
return self._data.pop()
def peek(self):
if not self._data:
raise IndexError("peek from empty stack")
return self._data[-1]
def is_empty(self):
return not self._data
def size(self):
return len(self._data)
def is_balanced(s):
pairs = {')': '(', ']': '[', '}': '{'}
st = []
for ch in s:
if ch in '([{':
st.append(ch)
elif ch in ')]}':
if not st or st.pop() != pairs[ch]:
return False
return not st
# is_balanced("(a+[b*c]-{d/e})") == True
# is_balanced("(]") == False
def dfs_iterative(graph, start):
visited = set()
order = []
stack = [start]
while stack:
node = stack.pop()
if node in visited:
continue
visited.add(node)
order.append(node)
# Push neighbors (reverse to mimic recursive order if desired)
for nei in reversed(graph.get(node, [])):
if nei not in visited:
stack.append(nei)
return order
The call stack in a runtime system stores stack frames for active function calls (return addresses, locals). It is an application of the stack abstraction. Deep or infinite recursion can cause a stack overflow.
pop() or peek().