Algorithms
An algorithm is a precise sequence of steps for solving a problem, and the previous topic's data structures only matter because specific algorithms are what actually operate on them. Searching an array means finding a particular value: a linear search checks every element one at a time and works on any array, while a binary search exploits a sorted array's ordering by checking the middle element and discarding half the remaining range each time, the same divide-in-half instinct repeated until the value is found or the range runs out. Sorting rearranges an array into order so binary search and similar techniques even become possible: a simple approach like bubble sort repeatedly swaps adjacent out-of-order pairs in a slow crawl through the whole array, while a divide-and-conquer approach like merge sort splits the array in half, sorts each half, and merges the two sorted halves back together, finishing in a fraction of the comparisons a simple swap-based approach needs. Recursion is a function calling itself on a smaller version of the same problem until it reaches a simple base case, and it is exactly how binary search and merge sort are usually implemented in practice: each recursive call gets its own frame on the call stack covered in memory and program execution, so a recursive binary search narrowing a 1000-element array down to 1 element creates and destroys about ten stack frames along the way, one for each halving. Graph traversal walks a graph's nodes and edges systematically, and the filesystem tree from earlier in this series is a perfect concrete example: breadth-first search explores every node one step away before moving two steps away, guaranteeing the shortest path to a target file measured in folder hops, while depth-first search commits to one branch as far as it can go before backtracking, which is simpler to implement using the exact same call stack recursion already relies on. A greedy method builds a solution by always taking the locally best-looking choice at each step and never reconsidering it — fast, but only provably correct for problems with the right structure. Dynamic programming instead breaks a problem into overlapping subproblems and stores each subproblem's answer the first time it's computed, so every later reference to that same subproblem becomes a quick lookup instead of a full recomputation, turning what would be an exponential amount of repeated work into something far more manageable — the cached answers themselves are exactly the kind of longer-lived data that belongs on the heap rather than disappearing with a single stack frame. Every one of these six techniques is a direct answer to a specific problem shape built on top of the structures already introduced, and the next topic, algorithm analysis, is what actually measures how much each one costs.