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)

  1. Divide: split the array into two halves.
  2. Conquer: recursively sort each half.
  3. 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(a[1n]a[1 \dots n])

if n>1n > 1 then

ML=mergesort(a[1n2])ML = mergesort(a[1 \dots \lfloor \frac{n}{2} \rfloor])

MR=mergesort(a[n2+1,n])MR = mergesort(a[\lfloor \frac{n}{2} + 1, \dots n])

return merge(ML,MR)merge(ML, MR)

else

return aa

Variables & Data Structures

NameTypePurpose
a[1...n]ArrayThe input to be sorted
ML, MRSorted arraysThe 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 of ML and MR, 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): .

ComplexityNotes
Time — worst, best, and average case are all the sameThe split is always exactly in half regardless of input, so there’s no “unlucky” input the way there is for Quick Sort
Space auxiliarymerge 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).

References / Links