class Node:
def __init__(self, data):
self.data = data
self.next = None
# Singly Linked List
head = Node(1)
head.next = Node(2)
head.next.next = Node(3)
Stacks
Stacks
Operation
Time
Push
O(1)
Pop
O(1)
Peek
O(1)
# LIFO - Last In, First Out
stack = []
stack.append(1) # Push
stack.append(2)
stack.append(3)
top = stack[-1] # Peek
item = stack.pop() # Pop
Queues
Queues
Operation
Time
Enqueue
O(1)
Dequeue
O(1)
Front
O(1)
from collections import deque
# FIFO - First In, First Out
queue = deque()
queue.append(1) # Enqueue
queue.append(2)
queue.append(3)
front = queue[0] # Front
item = queue.popleft() # Dequeue
Trees
Trees
Operation
Time
Search
O(log n) - balanced
Insert
O(log n) - balanced
Delete
O(log n) - balanced
class TreeNode:
def __init__(self, val):
self.val = val
self.left = None
self.right = None
# Binary Search Tree
root = TreeNode(5)
root.left = TreeNode(3)
root.right = TreeNode(7)
# Space Complexity Examples
def constant_space(n):
return n + 1 # O(1) space
def linear_space(n):
return [i for i in range(n)] # O(n) space
def quadratic_space(n):
return [[0]*n for _ in range(n)] # O(n²) space
Advanced Trees
Advanced Trees
Tree Type
Use Case
AVL Tree
Self-balancing BST
Red-Black Tree
Balanced tree with colors
B-Tree
Database indexing
Splay Tree
Recently accessed items
# AVL Tree Node
class AVLNode:
def __init__(self, key):
self.key = key
self.left = None
self.right = None
self.height = 1
# Red-Black Tree Node
class RBNode:
def __init__(self, key):
self.key = key
self.left = None
self.right = None
self.parent = None
self.color = "RED" # RED or BLACK
Advanced Graphs
Advanced Graphs
Algorithm
Time
Dijkstra
O((V + E) log V)
Bellman-Ford
O(VE)
Floyd-Warshall
O(V³)
Kruskal
O(E log E)
Prim
O(E log V)
# Dijkstra's Algorithm
import heapq
def dijkstra(graph, start):
distances = {node: float('inf') for node in graph}
distances[start] = 0
pq = [(0, start)]
while pq:
dist, node = heapq.heappop(pq)
if dist > distances[node]:
continue
for neighbor, weight in graph[node].items():
if distances[node] + weight < distances[neighbor]:
distances[neighbor] = distances[node] + weight
heapq.heappush(pq, (distances[neighbor], neighbor))
return distances
Tries (Prefix Trees)
Tries
Operation
Time
Insert
O(m)
Search
O(m)
Prefix Search
O(m)
class TrieNode:
def __init__(self):
self.children = {}
self.is_end = False
class Trie:
def __init__(self):
self.root = TrieNode()
def insert(self, word):
node = self.root
for char in word:
if char not in node.children:
node.children[char] = TrieNode()
node = node.children[char]
node.is_end = True
def search(self, word):
node = self.root
for char in word:
if char not in node.children:
return False
node = node.children[char]
return node.is_end
class FenwickTree:
def __init__(self, n):
self.n = n
self.tree = [0] * (n + 1)
def update(self, i, val):
while i <= self.n:
self.tree[i] += val
i += i & -i
def query(self, i):
res = 0
while i > 0:
res += self.tree[i]
i -= i & -i
return res
def range_query(self, l, r):
return self.query(r) - self.query(l - 1)