Vasu Patel logoVasu Patel
← Python DSA — Beginner
All chapters in this track
  1. 011. What is DSA & Why It Matters
  2. 022. Python's Built-in Collections
  3. 033. Arrays & Strings
  4. 044. Linked Lists
  5. 055. Stacks & Queues
  6. 066. Hash Maps & Sets
  7. 077. Trees
  8. 088. Heaps & Priority Queues
  9. 099. Graphs
  10. 1010. Sorting & Searching
  11. 1111. Recursion
  12. 1212. Dynamic Programming
  13. 1313. Tries
  14. 1414. DSA in Real Software

Chapter 14 of 14

14. DSA in Real Software

How Data Structures Map to Engineering Problems

This chapter connects each data structure to the real systems and components you'll build or encounter as a software engineer.


14.1 Databases

DSA conceptWhere it appears
B-Tree / BSTDatabase indexes (PostgreSQL, MySQL) — fast range queries
Hash mapHash indexes — exact-match lookups in O(1)O(1)
HeapORDER BY LIMIT k queries — finds top-k rows efficiently
TrieFull-text search prefix matching
GraphGraph databases (Neo4j), foreign key relationships

14.2 Operating Systems

DSA conceptWhere it appears
StackCall stack — each function call pushes a frame, return pops it
QueueCPU scheduling — process queue, I/O request queue
HeapMemory allocator — free memory blocks managed as a heap
Hash mapPage table — virtual address → physical address translation
Linked listFree list in memory management

14.3 Networking & Web

DSA conceptWhere it appears
TrieIP routing — longest-prefix matching in routing tables
GraphInternet topology, BGP routing, CDN path selection
QueueMessage queues (Kafka, RabbitMQ) — async task processing
Hash mapDNS cache, HTTP cache headers, session stores
Bloom filter (probabilistic set)Checking if a URL has been crawled

14.4 Common SWE Problem Patterns

# --- LRU Cache (Least Recently Used) ---
# Used in: database query caches, browser page caches, CPU caches
# Evicts the least recently accessed item when capacity is full
# Implementation: doubly linked list + hash map → all operations O(1)

from collections import OrderedDict

class LRUCache:
    def __init__(self, capacity: int):
        self.capacity = capacity
        self.cache = OrderedDict()   # maintains insertion order

    def get(self, key: int) -> int:
        if key not in self.cache:
            return -1
        self.cache.move_to_end(key)   # mark as recently used
        return self.cache[key]

    def put(self, key: int, value: int) -> None:
        if key in self.cache:
            self.cache.move_to_end(key)
        self.cache[key] = value
        if len(self.cache) > self.capacity:
            self.cache.popitem(last=False)   # evict least recently used (front)

lru = LRUCache(3)
lru.put(1, 10); lru.put(2, 20); lru.put(3, 30)
lru.get(1)      # access 1 → moves to end (recently used)
lru.put(4, 40)  # evicts 2 (least recently used)
print(list(lru.cache.keys()))   # [3, 1, 4]

# --- Rate Limiter (sliding window) ---
# Used in: API gateways, CDNs, auth systems
import time
from collections import deque

class RateLimiter:
    """Allow at most max_requests per window_seconds."""
    def __init__(self, max_requests: int, window_seconds: float):
        self.max_requests = max_requests
        self.window = window_seconds
        self.timestamps: deque[float] = deque()

    def allow(self) -> bool:
        now = time.time()
        # Remove timestamps outside the window
        while self.timestamps and self.timestamps[0] < now - self.window:
            self.timestamps.popleft()
        if len(self.timestamps) < self.max_requests:
            self.timestamps.append(now)
            return True
        return False   # too many requests

# --- Task Scheduler with priority ---
# Used in: job queues, OS schedulers, workflow engines
import heapq
from dataclasses import dataclass, field
from typing import Any

@dataclass(order=True)
class Job:
    priority: int
    task: Any = field(compare=False)

class Scheduler:
    def __init__(self):
        self._heap: list[Job] = []

    def submit(self, priority: int, task) -> None:
        heapq.heappush(self._heap, Job(priority, task))

    def run_next(self):
        if self._heap:
            job = heapq.heappop(self._heap)
            print(f"Running [priority={job.priority}]: {job.task}")
            return job.task

sched = Scheduler()
sched.submit(3, "send_newsletter")
sched.submit(1, "process_payment")    # highest priority (lowest number)
sched.submit(2, "generate_report")
sched.run_next()   # process_payment
sched.run_next()   # generate_report
sched.run_next()   # send_newsletter

# --- Dependency resolver (topological sort) ---
# Used in: package managers (pip, npm), build tools (make, gradle)
def install_order(packages: dict[str, list[str]]) -> list[str]:
    """
    packages = {"A": ["B", "C"], "B": ["D"], "C": [], "D": []}
    means A depends on B and C, B depends on D, etc.
    Returns install order starting from dependencies.
    """
    from collections import deque
    in_degree = {pkg: 0 for pkg in packages}
    for pkg, deps in packages.items():
        for dep in deps:
            in_degree[pkg] += 1   # this package depends on 'dep'

    # Recalculate: count how many packages depend on each
    in_degree = {pkg: 0 for pkg in packages}
    reverse_deps: dict[str, list[str]] = {pkg: [] for pkg in packages}
    for pkg, deps in packages.items():
        for dep in deps:
            reverse_deps[dep].append(pkg)
            in_degree[pkg] += 1

    queue = deque(pkg for pkg in packages if in_degree[pkg] == 0)
    order = []
    while queue:
        pkg = queue.popleft()
        order.append(pkg)
        for dependent in reverse_deps[pkg]:
            in_degree[dependent] -= 1
            if in_degree[dependent] == 0:
                queue.append(dependent)
    return order if len(order) == len(packages) else []   # [] = circular dep

pkgs = {"app": ["db", "cache"], "db": ["driver"], "cache": [], "driver": []}
print(install_order(pkgs))   # ['cache', 'driver', 'db', 'app'] (one valid order)

14.5 Choosing the Right Data Structure

Use this guide when designing a component:

Need fast lookup by key?
  → dict (hash map)   O(1) average

Need unique items / fast membership test?
  → set               O(1) average

Need ordered items with fast access by position?
  → list              O(1) index, O(n) search

Need frequent insert/delete at both ends?
  → deque             O(1) both ends

Need always process the highest/lowest priority item next?
  → heapq (heap)      O(log n)

Need range queries (sum/min/max of a[l..r])?
  → prefix sum (static) or segment tree (dynamic)

Need prefix-based string search / autocomplete?
  → Trie              O(L) per operation

Need to model relationships/connections?
  → dict of lists (adjacency list)

Need to sort a group once and then query?
  → sorted list + bisect   O(n log n) build, O(log n) query

Need to track connected components dynamically?
  → Union-Find        O(α(n)) ≈ O(1) per operation

14.6 Complexity Quick Reference

StructureAccessSearchInsertDeleteSpace
listO(1)O(1)O(n)O(n)O(1)O(1)†O(n)O(n)O(n)O(n)
Sorted listO(1)O(1)O(log⁡n)O(\log n)O(n)O(n)O(n)O(n)O(n)O(n)
dict / setO(1)O(1)O(1)O(1)O(1)O(1)†O(1)O(1)O(n)O(n)
dequeO(n)O(n)O(n)O(n)O(1)O(1) endsO(1)O(1) endsO(n)O(n)
HeapO(1)O(1) min—O(log⁡n)O(\log n)O(log⁡n)O(\log n)O(n)O(n)
BST (balanced)—O(log⁡n)O(\log n)O(log⁡n)O(\log n)O(log⁡n)O(\log n)O(n)O(n)
Trie—O(L)O(L)O(L)O(L)O(L)O(L)O(n⋅L)O(n \cdot L)

† Amortised


End of Python DSA for Software Engineers — August 2026