Merge sort & divide-and-conquer
◈ 4 cardsDivide / conquer / combine; the Θ(n) MERGE step; the recurrence T(n)=2T(n/2)+Θ(n) and its recursion-tree solution Θ(n lg n).
The divide-and-conquer template
Divide-and-conquer solves a problem by breaking it into smaller instances of the same problem:
- Divide the instance into subproblems.
- Conquer each subproblem recursively (or directly, if small enough — the base case).
- Combine the subsolutions into a solution for the original.
Merge sort is the canonical example. To sort : divide at the midpoint , recursively sort and , then merge the two sorted halves. The recursion bottoms out at a one-element subarray (), which is trivially sorted. Almost all the work lives in the combine step — the opposite of quicksort, where the work is in the divide.
MERGE is the engine, and it is Θ(n)
MERGE(A, p, q, r) assumes and are each already sorted, and weaves them into one sorted run. It copies the two halves into temporaries and , then repeatedly appends the smaller of the two current front elements:
MERGE(L, R):
i = j = 0; out = []
while i < |L| and j < |R|
if L[i] <= R[j]: out.append(L[i]); i = i + 1
else: out.append(R[j]); j = j + 1
append the rest of L, then the rest of R
return out
Why temporaries? Merging in place would overwrite values still needed for later comparisons. The cost: each of the elements is moved from into and then back into exactly once, so MERGE runs in — and that linear merge is precisely what makes the whole sort . Using <= (not <) in the comparison keeps merge sort stable.
The recurrence and its solution
Divide costs (a midpoint); conquer is ; combine is . So:
Recursion-tree argument. Picture the tree of subproblem costs. Level has nodes, each of size , so each node does merge work — and the level's total is , the same at every level. The doubling of nodes exactly cancels the halving of cost-per-node. The tree has levels (you can halve down to exactly times). So the total is
Unlike insertion sort, merge sort's running time is in all cases — it always splits, always recurses, always merges, regardless of the input order. The price is extra space for the temporaries.