Foundations — Quick sort — Lomuto - Hoare partition, pivot strategies, expected O(n log n), worst case
Before you can read a line of that parent note, you need a vocabulary. Below is every symbol and idea it silently assumes, each built from nothing, in an order where each rung of the ladder rests on the one below it. If a term already makes total sense to you, skim — but the [!recall] checklist at the bottom is the real test.
1. An array and its indices

The picture: look at the strip above. The teal number under each box is its index ; the plum number inside is the value . So here is the fourth box.
Why the topic needs it: every pointer in Lomuto and Hoare (i, j, lo, hi, q) is just an index — a finger pointing at one box. If "index" is fuzzy, all the pointer-chasing is noise.
2. Subarray and the range
The picture: imagine two brackets you can slide inward around any chunk of the row. Everything between them is the subarray you are currently working on.
Why the topic needs it: quicksort is recursive — it calls itself on smaller pieces. Each call says "sort just this slice, from lo to hi." Without a way to name a slice, recursion cannot even be stated.
3. Swap — the one physical move
The picture: two boxes trade the numbers inside them, like two people swapping seats. The indices stay put; only the values travel.
Why the topic needs it: quicksort is in-place — it never builds a second array, it only rearranges the boxes it already has. The only tool for rearranging is swap. Every partition routine is a sequence of swaps.
4. The pivot and "partition"

The picture: three coloured zones. The orange left zone holds everything ; the single teal box is the pivot in its home ; the plum right zone holds everything . The zones are unsorted within themselves — that is what recursion fixes next.
Why the topic needs it: this is the whole engine. Once is at , the problem splits into two smaller, independent problems (left zone, right zone) that never interact again. "" is exactly the return value of Lomuto's partition.
5. Comparisons: , , ,
Why the topic needs it: partition decides which zone a value belongs to by comparing it to the pivot. The exact choice of vs is what the loop invariant pins down (e.g. "" uses strict less-than). Getting these boundaries right is the difference between correct code and an infinite loop — especially with duplicate (equal) values, which is why the parent note flags equal elements as dangerous.
6. Pointers i, j and their invariants

The picture: j (plum arrow) sweeps left-to-right inspecting values; i (orange arrow) lags behind, sitting at the last box already known to be . Every time j finds a small value, i steps forward and swaps it in.
Why the topic needs it: the parent's proof of correctness is its invariant (, etc.). An invariant is how you trust code without tracing every case: if it holds at the start, and each step preserves it, then it holds at the end — and the end statement is exactly "the array is partitioned." This is the logical backbone of both Lomuto and Hoare.
7. Recursion and the recursion tree

The picture: the balanced tree (left) halves each time → short and bushy, depth . The lopsided chain (right) peels one element per call → depth . Same algorithm, wildly different shapes depending on pivot luck.
Why the topic needs it: the entire complexity story lives in this tree. Each level does work (one partition pass over its boxes). So total work = work-per-level × depth. Bushy tree → . Chain → . That is literally where and the worst case come from.
8. Big-O and — the size labels
Why the topic needs it: the whole reason quicksort matters is its speed label. "Expected , worst " is a one-line summary of the recursion-tree analysis. Without these labels you cannot compare quicksort to Merge Sort or Heap Sort.
9. Logarithm — the depth of a bushy tree
The picture: each level of a balanced recursion tree cuts the slice in half. The number of levels until size is the number of halvings — that is . That's why a balanced quicksort tree has depth .
Why the topic needs it: the "log" in is this halving count. It is why doubling the array only adds one level of work, not double the work.
10. Sum and the harmonic number
Why the topic needs it: the parent's expected-comparison count is . If and are unfamiliar, the elegant "" derivation is unreadable. You do not need to derive here — just recognise that this friendly sum is what produces the in the average case.
Recall Why does a sum of
give a logarithm? Because adding up from to is close to the area under the curve , and that area is exactly . (Full detail lives with the Master Theorem toolkit — here just trust the shape.)
How the foundations feed the topic
Equipment checklist
Test yourself — cover the right side and answer out loud.
What does mean, and why do indices start at 0?
How many boxes are in the slice ?
Why does quicksort use swap instead of inserting?
After partitioning, where is the pivot ?
What is a loop invariant?
Why does each level of the recursion tree cost ?
What question does answer?
Difference between and ?
What is and roughly how big is it?
Ready? If every line above felt solid, jump to the parent note and read the Lomuto trace — every pointer will now be a familiar finger on a familiar box.