Imagine two friends each hand you a neatly sorted pile of exam papers, ordered by mark. You want to combine them into one sorted pile. Do you shuffle everything together and start again? No — you glance at the top paper of each pile, take whichever has the smaller mark, and drop it face-down onto your new pile. Repeat. Because each pile is already in order, the smallest paper left is always at the top of one pile or the other, so you never have to look deeper. In a single sweep the two sorted piles become one sorted pile.
That merging trick is the heart of merge sort — one of the fastest and most elegant ways to sort a list. It is built from just two ideas, and this page is really about those two:
Merge sort is the classic example of a divide-and-conquer algorithm: a hard problem is broken into smaller copies of the same problem, each solved the same way, and the answers are combined. Sorting a whole list is hard; sorting a list of one item is trivial (it's already sorted!). So the plan is:
The recursion does the splitting; the merge does the real work of putting things in order. Watch one list travel all the way down to single items and back up to sorted:
Read the top half downwards — the list halves until each piece is a lone number (which is trivially "sorted"). Then read the bottom half: neighbouring pieces are merged, pair by pair, until the whole list is back together and in order.
Everything depends on merging, so let's do one carefully by hand. We are merging two sorted lists:
Keep a finger on the front of each list. Compare the two fingers, take the smaller number into the result, and move that finger on one place:
Notice the very last line: once one list runs out, the other is already sorted, so we can
tip the whole remainder onto the end without any more comparing. Merging two lists of total length
This is the whole algorithm: a merge helper that fuses two sorted lists, and a
recursive mergeSort that splits, recurses, then merges. Press Run and
read the merges it prints — you'll see it merge tiny lists first, then bigger and bigger ones.
The function has recursion's two hallmarks: a base case (a list of length 0 or 1) and a recursive case that calls itself on smaller lists (the two halves). Because each half is strictly shorter, the splitting is guaranteed to stop.
Simple sorts like
The gap is enormous once lists get big. Sorting a million items:
Merge sort was described by John von Neumann in 1945, at the very dawn of the stored-program computer — making it one of the oldest algorithms still in everyday use. It has a lovely practical superpower: because it only ever needs to look at the fronts of two lists at a time, it can sort data far too big to fit in memory. Old machines sorted enormous files by streaming sorted chunks off separate magnetic tapes and merging them — "external" merge sort. The same idea still powers the sorting inside huge databases today.
The merge step feels like magic — one clean pass and two lists become one sorted list — but the
magic only works because both halves are already sorted. If you handed
merge two unsorted lists, taking the smaller front item would give
nonsense, because the smallest number might be buried deep in a pile, not on top.
So don't picture merge sort as "one merge." The recursion's whole job is to guarantee the halves are sorted before you merge them — you sort the smallest pieces first, then merge upward. That's why the base case matters: a single item is sorted for free, giving merge something correct to build on.
One more gotcha: merging cannot happen "in place" like bubble sort's swaps. You need somewhere to
put the merged result — the result array in the code above. Merge sort
trades a little extra memory (about