25% off

Use code FUNCMAIN at checkout to get 25% off all premium courses.

Get started →

Video:

Merge Sort Algorithm Overview

March 7, 2026

Course Instructor: Elliot Forbes

Hey Gophers! My name is Elliot and I'm the creator of TutorialEdge and I've been working with Go systems for roughly 5 years now.

Twitter: @Elliot_f

👋 Welcome Gophers! In this lesson, we are going to explore how the merge sort algorithm works and why it’s much more efficient than the simple sorting algorithms we’ve seen so far.

How Merge Sort Works

Merge sort is an efficient, general-purpose, comparison-based sorting algorithm that uses a divide-and-conquer approach. Instead of repeatedly comparing adjacent elements like bubble sort or insertion sort, merge sort divides the array into smaller pieces, sorts those pieces, and then merges them back together.

The basic process is:

  1. Divide: Split the array into two halves
  2. Conquer: Recursively sort each half
  3. Merge: Combine the two sorted halves into a single sorted array

Here’s how it works conceptually with an example array [5, 2, 4, 3, 1]:

[5, 2, 4, 3, 1]
    ↓
  Split
    ↓
[5, 2, 4] and [3, 1]
    ↓
  Split
    ↓
[5], [2, 4], [3], [1]
    ↓
  Split
    ↓
[5], [2], [4], [3], [1]
    ↓
  Merge
    ↓
[2, 5], [4], [1, 3]
    ↓
  Merge
    ↓
[2, 4, 5], [1, 3]
    ↓
  Merge
    ↓
[1, 2, 3, 4, 5]

The Merge Process

When merging two sorted arrays, we compare the first elements of each array and take the smaller one. We continue this process until both arrays are empty:

  • Compare 2 and 3, take 2
  • Compare 5 and 3, take 3
  • Compare 5 and 1, take 1
  • No elements left in second array, add remaining 5

Time and Space Complexity

  • Best Case: O(n log n) - even on already sorted data, we still divide and merge
  • Average Case: O(n log n) - consistent performance
  • Worst Case: O(n log n) - guaranteed performance
  • Space Complexity: O(n) - requires temporary arrays during merging

This guaranteed O(n log n) performance is why merge sort is so popular for large datasets, despite requiring extra space.

Visual Representation

Here’s a visual representation of how merge sort divides and merges:

<svg viewBox="0 0 700 450" xmlns="http://www.w3.org/2000/svg" style="background-color: #1a1a1a; font-family: monospace;">
  <!-- Title -->
  <text x="350" y="25" fill="#e0e0e0" font-size="16" text-anchor="middle" font-weight="bold">Merge Sort: Divide Phase</text>

  <!-- Level 0: Original array -->
  <g id="level0">
    <text x="20" y="55" fill="#888" font-size="12">Level 0:</text>
    <rect x="80" y="40" width="35" height="35" fill="#4a4a4a" stroke="#888" stroke-width="2"/>
    <text x="97" y="62" fill="#fff" text-anchor="middle" font-size="14">5</text>
    <rect x="125" y="40" width="35" height="35" fill="#4a4a4a" stroke="#888" stroke-width="2"/>
    <text x="142" y="62" fill="#fff" text-anchor="middle" font-size="14">2</text>
    <rect x="170" y="40" width="35" height="35" fill="#4a4a4a" stroke="#888" stroke-width="2"/>
    <text x="187" y="62" fill="#fff" text-anchor="middle" font-size="14">4</text>
    <rect x="215" y="40" width="35" height="35" fill="#4a4a4a" stroke="#888" stroke-width="2"/>
    <text x="232" y="62" fill="#fff" text-anchor="middle" font-size="14">3</text>
    <rect x="260" y="40" width="35" height="35" fill="#4a4a4a" stroke="#888" stroke-width="2"/>
    <text x="277" y="62" fill="#fff" text-anchor="middle" font-size="14">1</text>
  </g>

  <!-- Arrows down -->
  <path d="M 170 85 L 170 110" stroke="#666" stroke-width="2" fill="none" marker-end="url(#arrowhead)"/>

  <!-- Level 1: First split -->
  <g id="level1">
    <text x="20" y="135" fill="#888" font-size="12">Level 1:</text>
    <rect x="60" y="120" width="35" height="35" fill="#ff6b6b" stroke="#ff6b6b" stroke-width="2"/>
    <text x="77" y="142" fill="#fff" text-anchor="middle" font-size="14">5</text>
    <rect x="105" y="120" width="35" height="35" fill="#ff6b6b" stroke="#ff6b6b" stroke-width="2"/>
    <text x="122" y="142" fill="#fff" text-anchor="middle" font-size="14">2</text>
    <rect x="150" y="120" width="35" height="35" fill="#ff6b6b" stroke="#ff6b6b" stroke-width="2"/>
    <text x="167" y="142" fill="#fff" text-anchor="middle" font-size="14">4</text>

    <rect x="230" y="120" width="35" height="35" fill="#4169e1" stroke="#4169e1" stroke-width="2"/>
    <text x="247" y="142" fill="#fff" text-anchor="middle" font-size="14">3</text>
    <rect x="275" y="120" width="35" height="35" fill="#4169e1" stroke="#4169e1" stroke-width="2"/>
    <text x="292" y="142" fill="#fff" text-anchor="middle" font-size="14">1</text>
  </g>

  <!-- Arrows down -->
  <path d="M 120 165 L 120 190" stroke="#666" stroke-width="2" fill="none"/>
  <path d="M 260 165 L 260 190" stroke="#666" stroke-width="2" fill="none"/>

  <!-- Level 2: Final split -->
  <g id="level2">
    <text x="20" y="215" fill="#888" font-size="12">Level 2:</text>
    <rect x="60" y="200" width="35" height="35" fill="#ffa500" stroke="#ffa500" stroke-width="2"/>
    <text x="77" y="222" fill="#fff" text-anchor="middle" font-size="14">5</text>
    <rect x="105" y="200" width="35" height="35" fill="#ffa500" stroke="#ffa500" stroke-width="2"/>
    <text x="122" y="222" fill="#fff" text-anchor="middle" font-size="14">2</text>
    <rect x="150" y="200" width="35" height="35" fill="#ffa500" stroke="#ffa500" stroke-width="2"/>
    <text x="167" y="222" fill="#fff" text-anchor="middle" font-size="14">4</text>
    <rect x="230" y="200" width="35" height="35" fill="#51cf66" stroke="#51cf66" stroke-width="2"/>
    <text x="247" y="222" fill="#fff" text-anchor="middle" font-size="14">3</text>
    <rect x="275" y="200" width="35" height="35" fill="#51cf66" stroke="#51cf66" stroke-width="2"/>
    <text x="292" y="222" fill="#fff" text-anchor="middle" font-size="14">1</text>
  </g>

  <!-- Merge Phase label -->
  <text x="350" y="280" fill="#e0e0e0" font-size="16" text-anchor="middle" font-weight="bold">Merge Phase</text>

  <!-- Merge step 1 -->
  <text x="20" y="315" fill="#888" font-size="12">Merge 1:</text>
  <rect x="80" y="300" width="35" height="35" fill="#9c27b0" stroke="#9c27b0" stroke-width="2"/>
  <text x="97" y="322" fill="#fff" text-anchor="middle" font-size="14">2</text>
  <rect x="125" y="300" width="35" height="35" fill="#9c27b0" stroke="#9c27b0" stroke-width="2"/>
  <text x="142" y="322" fill="#fff" text-anchor="middle" font-size="14">5</text>
  <rect x="170" y="300" width="35" height="35" fill="#9c27b0" stroke="#9c27b0" stroke-width="2"/>
  <text x="187" y="322" fill="#fff" text-anchor="middle" font-size="14">4</text>
  <rect x="230" y="300" width="35" height="35" fill="#00bcd4" stroke="#00bcd4" stroke-width="2"/>
  <text x="247" y="322" fill="#fff" text-anchor="middle" font-size="14">1</text>
  <rect x="275" y="300" width="35" height="35" fill="#00bcd4" stroke="#00bcd4" stroke-width="2"/>
  <text x="292" y="322" fill="#fff" text-anchor="middle" font-size="14">3</text>

  <!-- Merge step 2 -->
  <text x="20" y="380" fill="#888" font-size="12">Merge 2:</text>
  <rect x="80" y="365" width="35" height="35" fill="#2196f3" stroke="#2196f3" stroke-width="2"/>
  <text x="97" y="387" fill="#fff" text-anchor="middle" font-size="14">1</text>
  <rect x="125" y="365" width="35" height="35" fill="#2196f3" stroke="#2196f3" stroke-width="2"/>
  <text x="142" y="387" fill="#fff" text-anchor="middle" font-size="14">2</text>
  <rect x="170" y="365" width="35" height="35" fill="#2196f3" stroke="#2196f3" stroke-width="2"/>
  <text x="187" y="387" fill="#fff" text-anchor="middle" font-size="14">3</text>
  <rect x="215" y="365" width="35" height="35" fill="#2196f3" stroke="#2196f3" stroke-width="2"/>
  <text x="232" y="387" fill="#fff" text-anchor="middle" font-size="14">4</text>
  <rect x="260" y="365" width="35" height="35" fill="#2196f3" stroke="#2196f3" stroke-width="2"/>
  <text x="277" y="387" fill="#fff" text-anchor="middle" font-size="14">5</text>

  <!-- Arrow marker definition -->
  <defs>
    <marker id="arrowhead" markerWidth="10" markerHeight="10" refX="5" refY="5" orient="auto">
      <polygon points="0 0, 10 5, 0 10" fill="#666"/>
    </marker>
  </defs>
</svg>

Why Merge Sort is Great

  • Guaranteed O(n log n): Unlike quicksort, merge sort has consistent performance
  • Stable sort: Maintains the relative order of equal elements
  • Suitable for linked lists: Can sort linked lists efficiently with O(1) extra space
  • Parallelizable: Can be split across multiple processors

The main tradeoff is that merge sort requires O(n) extra space, whereas insertion sort and bubble sort are O(1) space algorithms.

Quiz Time

Test your understanding of merge sort with these questions: