Back to All Algorithms
Merge Sort
Category: Sorting | Time: O(n log n) | Space: O(n)
Visualization
Visual representation of the data structure
About Merge Sort

An efficient, stable, comparison-based sorting algorithm. Most implementations produce a stable sort, which means that the order of equal elements is the same in the input and output. Merge sort is a divide and conquer algorithm that was invented by John von Neumann in 1945. The algorithm splits the array into two halves, recursively sorts them, and then merges the two sorted halves.

Code Editor
The code is for reference. Editing it won't affect the visualization.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Variable State
{
  "arr": "[38,27,43,3,9,82,10]"
}
Merge Sort: How It Works
Last updated October 28, 2026

Overview

Merge Sort is the classic divide-and-conquer sort. It splits the array in half, sorts each half recursively, and then merges the two sorted halves into one sorted run. An array of length one is already sorted, which ends the recursion.

All of the real work happens in the merge step. Two pointers walk the left and right halves; at each step the smaller front element is copied to the output. Because each level of recursion touches every element once and there are log2(n) levels, the total cost is O(n log n) for every input.

With the default input 38, 27, 43, 3, 9, 82, 10, the visualizer first drills down to single elements such as [38] and [27], then merges them back up: [27, 38], [3, 27, 38, 43], and finally the full sorted array.

Step by step

  1. If the current range has one element or fewer, return — it is sorted.
  2. Find the middle index m and recursively sort l..m and m+1..r.
  3. Copy the two halves into temporary arrays L and R.
  4. Repeatedly copy the smaller of L[i] and R[j] back into the array, advancing that pointer.
  5. When one half runs out, copy whatever remains of the other half.

Complexity

CaseCostWhy
Best caseO(n log n)The split-and-merge structure does not depend on input order.
Average caseO(n log n)log2(n) levels, each doing O(n) merge work.
Worst caseO(n log n)Guaranteed — no bad pivot problem as in Quick Sort.
Extra spaceO(n)The temporary arrays used while merging.

When to use it

  • When you need a guaranteed O(n log n) and a stable sort, e.g. sorting records by a secondary key.
  • Sorting linked lists, where merging needs no extra array and random access is unavailable.
  • External sorting of data too large for memory: sort chunks, then merge them from disk.

Common mistakes

  • Using < instead of <= when comparing L[i] and R[j] takes equal elements from the right first and makes the sort unstable.
  • Computing the middle as (l + r) / 2 can overflow in fixed-width integer languages; l + (r - l) / 2 is safe.
  • Allocating new temporary arrays on every call is a common performance trap; production code allocates one buffer up front.
Worked Example: Merge Sort Dry Run
Generated from the same trace that drives the visualizer above, using the default input.

A dry run is the best way to check your understanding of Merge Sort: follow each row, predict the next one, and compare. The run below takes 138 steps in total. Steps that only re-print loop counters are left out so the decisions stand out. The Line column refers to the line numbers in the code listing above.

Input
38, 27, 43, 3, 9, 82, 10
Result
return value = [3, 9, 10, 27, 38, 43, 82]
StepLineArrayWhat happens
11[38, 27, 43, 3, 9, 82, 10]
22[38, 27, 43, 3, 9, 82, 10]condition = 7 <= 1
62[38, 27, 43, 3, 9, 82, 10]condition = 4 <= 1
102[38, 27, 43, 3, 9, 82, 10]condition = 2 <= 1
142[38, 27, 43, 3, 9, 82, 10]condition = 1 <= 1
182[38, 27, 43, 3, 9, 82, 10]condition = 1 <= 1
2313[38, 27, 43, 3, 9, 82, 10]left = [38], right = [27], condition = 38 < 27
2518[27, 27, 43, 3, 9, 82, 10]resultArray = [27], rightIndex = 0
2825[27, 38, 43, 3, 9, 82, 10]resultArray = [27,38]
312[27, 38, 43, 3, 9, 82, 10]condition = 2 <= 1
352[27, 38, 43, 3, 9, 82, 10]condition = 1 <= 1
392[27, 38, 43, 3, 9, 82, 10]condition = 1 <= 1
4413[27, 38, 43, 3, 9, 82, 10]left = [43], right = [3], condition = 43 < 3
4618[27, 38, 3, 3, 9, 82, 10]resultArray = [3], rightIndex = 0
4925[27, 38, 3, 43, 9, 82, 10]resultArray = [3,43]
5313[27, 38, 3, 43, 9, 82, 10]left = [27,38], right = [3,43], condition = 27 < 3
5518[3, 38, 3, 43, 9, 82, 10]resultArray = [3], rightIndex = 0
5713[3, 38, 3, 43, 9, 82, 10]left = [27,38], right = [3,43], condition = 27 < 43
5915[3, 27, 3, 43, 9, 82, 10]resultArray = [3,27], leftIndex = 0
6113[3, 27, 3, 43, 9, 82, 10]left = [27,38], right = [3,43], condition = 38 < 43
6315[3, 27, 38, 43, 9, 82, 10]resultArray = [3,27,38], leftIndex = 1
692[3, 27, 38, 43, 9, 82, 10]condition = 3 <= 1
732[3, 27, 38, 43, 9, 82, 10]condition = 2 <= 1
772[3, 27, 38, 43, 9, 82, 10]condition = 1 <= 1
812[3, 27, 38, 43, 9, 82, 10]condition = 1 <= 1
8613[3, 27, 38, 43, 9, 82, 10]left = [9], right = [82], condition = 9 < 82
942[3, 27, 38, 43, 9, 82, 10]condition = 1 <= 1
9913[3, 27, 38, 43, 9, 82, 10]left = [9,82], right = [10], condition = 9 < 10
10313[3, 27, 38, 43, 9, 82, 10]left = [9,82], right = [10], condition = 82 < 10
10518[3, 27, 38, 43, 9, 10, 10]resultArray = [9,10], rightIndex = 0
10825[3, 27, 38, 43, 9, 10, 82]resultArray = [9,10,82]
11213[3, 27, 38, 43, 9, 10, 82]left = [3,27,38,43], right = [9,10,82], condition = 3 < 9
11613[3, 27, 38, 43, 9, 10, 82]left = [3,27,38,43], right = [9,10,82], condition = 27 < 9
11818[3, 9, 38, 43, 9, 10, 82]resultArray = [3,9], rightIndex = 0
12013[3, 9, 38, 43, 9, 10, 82]left = [3,27,38,43], right = [9,10,82], condition = 27 < 10
12218[3, 9, 10, 43, 9, 10, 82]resultArray = [3,9,10], rightIndex = 1
12413[3, 9, 10, 43, 9, 10, 82]left = [3,27,38,43], right = [9,10,82], condition = 27 < 82
12615[3, 9, 10, 27, 9, 10, 82]resultArray = [3,9,10,27], leftIndex = 1
12813[3, 9, 10, 27, 9, 10, 82]left = [3,27,38,43], right = [9,10,82], condition = 38 < 82
13015[3, 9, 10, 27, 38, 10, 82]resultArray = [3,9,10,27,38], leftIndex = 2

The remaining 3 key steps follow the same pattern. Press play in the visualizer to watch every step through to the result.

Frequently Asked Questions
About Merge Sort

How does Merge Sort work?

Merge Sort is a classic divide-and-conquer algorithm. It works by recursively dividing the unsorted list into n sublists, each containing one element. Then, it repeatedly merges these sublists to produce new sorted sublists until there is only one sublist remaining, which is the final sorted list.

What is the time complexity of Merge Sort?

Merge Sort has a consistent time complexity of O(n log n) in all cases—best, average, and worst. This reliability is one of its main strengths.

What is the space complexity of Merge Sort?

The typical implementation of Merge Sort has a space complexity of O(n) because it requires an auxiliary array of the same size as the input to store the merged results during the merging phase.

Is Merge Sort a stable algorithm?

Yes, Merge Sort is a stable sorting algorithm. During the merge step, if two elements are equal, the element from the left sub-array is placed first, preserving the original relative order.

Is Merge Sort an external sorting algorithm?

Yes, Merge Sort is highly effective for external sorting, where the data to be sorted is too large to fit into memory. Its sequential access pattern (reading and writing large blocks of data) is ideal for working with slower media like hard drives.

What is the 'merge' step in Merge Sort?

The merge step is the core of the algorithm. It takes two sorted sub-arrays and combines them into a single sorted array. It does this by iterating through both sub-arrays with two pointers, and at each step, it copies the smaller of the two elements into the result array.

Can Merge Sort be done in-place?

While it's theoretically possible to perform an in-place merge, it is extremely complex and not practical, as it would lose the simplicity and efficiency of the standard algorithm. Therefore, almost all practical implementations use O(n) extra space.

How does Merge Sort compare to Quick Sort?

Merge Sort has a better worst-case time complexity (O(n log n) vs Quick Sort's O(n^2)), is stable, and is better for external sorting. However, Quick Sort is often faster in practice for in-memory arrays due to lower constant factors and better cache performance.

What is a bottom-up Merge Sort?

A bottom-up (or iterative) Merge Sort avoids recursion. It starts by merging pairs of single elements, then merges pairs of 2-element runs, then 4-element runs, and so on, until the entire array is sorted. It achieves the same O(n log n) time complexity.

Is Merge Sort a comparison-based sort?

Yes, Merge Sort is a comparison-based sorting algorithm because it relies on comparing elements to determine their order during the merge step.

Where can I learn more?

You can find a more detailed explanation on GeeksforGeeks.