Abstract Merge Sort splits the array in half, recursively sorts each half, then merges the two sorted halves back together — the canonical Divide and Conquer sorting algorithm.
- Category: Divide and Conquer / Sorting (Deterministic)
- Input: An array
- Output: The array, sorted
- Paradigm: Divide and Conquer
- Typical use cases: general-purpose stable sorting; external/merge-based sorting of data too large to fit in memory; the go-to when a guaranteed worst case matters more than average-case speed
Core Logic (High-Level)
- Divide: split the array into two halves.
- Conquer: recursively sort each half.
- Combine: merge the two now-sorted halves into one sorted array.
Key Idea
All the real work happens in the merge step, not the split — splitting an array in half is trivial, but merging two already-sorted lists into one sorted list can be done in linear time by repeatedly comparing the fronts of each list and taking the smaller one. That single linear-time combine step, applied at every level of the recursion, is what gives the whole algorithm its bound (see Sorting for why is also the best any comparison sort can do).
Pseudocode (Mid-Level Implementation)
Algorithm 9 Merge Sort
Input: array to be sorted
Output: sorted array
procedure mergesort()
if then
return
else
return
Variables & Data Structures
| Name | Type | Purpose |
|---|---|---|
a[1...n] | Array | The input to be sorted |
ML, MR | Sorted arrays | The recursively-sorted left and right halves |
Helper Functions / Operations Used
merge(ML, MR)— combines two already-sorted lists into one sorted list. Repeatedly compares the fronts ofMLandMR, appending whichever is smaller and advancing that list’s pointer, until one list is exhausted, then appends the rest of the other. Runs in time.
Proof of Correctness
Base case: — mergesort returns the original single-element array a, which is trivially sorted.
Inductive Hypothesis: suppose that for some , mergesort(a[1...k]) correctly outputs the elements of a in sorted order for all inputs of size where . We want to show it works for inputs of size .
Inductive Step: since , mergesort(a[1...n]) returns merge(ML, MR) where and . Since (and the size of the second half is also ), the Inductive Hypothesis ensures both and are sorted. And merge correctly combines two sorted lists into one sorted list, so the algorithm returns the elements of a in sorted order.
Time & Space Complexity Analysis
General Case
Suppose mergesort runs in time for inputs of length . Each recursive call runs in time, and merge runs in time where , so merge runs in time:
\begin{align*} T(n) &= 2T\left(\frac{n}{2}\right) + O(n) \ &= \boxed{O(n\log n)} \end{align*}
By the Master Theorem (, so — Case 2): .
| Complexity | Notes | |
|---|---|---|
| Time | — worst, best, and average case are all the same | The split is always exactly in half regardless of input, so there’s no “unlucky” input the way there is for Quick Sort |
| Space | auxiliary | merge needs extra space to hold the merged output before it can overwrite the original array positions |
Best / Worst / Average Case
- Best / Worst / Average case: all — Merge Sort’s split is data-independent (always exactly in half), so unlike Quick Sort, there’s no input arrangement that makes it faster or slower.
Drawbacks / Constraints
- Not in-place. Requires auxiliary space for the merge step, unlike Quick Sort’s partition, which can be done with extra space (see Partition with Pivot).
- Not adaptive. Runs in even on already-sorted input — algorithms like Insertion Sort can detect and exploit partial sortedness to run faster on nearly-sorted data, but Merge Sort always does the same amount of work.
- Slower in practice than Quick Sort, often, despite the better worst-case guarantee — Quick Sort’s in-place partitioning tends to have better cache locality and a smaller constant factor, so Merge Sort is usually chosen specifically for its guaranteed worst case, not for raw speed.
- Alternatives to consider: Quick Sort when average-case speed matters more than worst-case guarantees; Insertion Sort for small or nearly-sorted inputs (often used as the base case inside a real Merge Sort implementation once the array is small enough).