📚 DAA Tutorial

Design and Analysis of Algorithms

Learn Design and Analysis of Algorithms concepts with simple explanations, algorithms, examples and practical notes.

← Back to DAA

Merge Sort

Assume the elements are to be sorted in non-decreasing order. Given a sequence of n elements (also called keys) a[1], …, a[n], the idea is to imagine them split into two sets a[1], …, a[n/2] and a[n/2+1], …, a[n]. Each set is individually sorted, and the resulting sorted sequences are merged to produce a single sorted sequence of n elements.

  1. Divide: partition the array into two sublists S₁ and S₂ with n/2 elements each.
  2. Conquer: recursively sort S₁ and S₂.
  3. Combine: merge S₁ and S₂ into a single sorted group.

Algorithm MergeSort(low, high)

Algorithm MergeSort(low, high)
// a[low:high] is a global array to be sorted.
// Small(P) is true if there is only one element.
{
    if (low < high) then          // if there are more than one element
    {
        // Divide P into subproblems
        mid := ⌊(low + high) / 2⌋;
        // Solve the subproblems
        MergeSort(low, mid);
        MergeSort(mid + 1, high);
        // Combine the solutions
        Merge(low, mid, high);
    }
}

Algorithm Merge(low, mid, high)

Algorithm Merge(low, mid, high)
/* a[low:high] is a global array containing two sorted subsets
   in a[low:mid] and a[mid+1:high]. This algorithm merges these
   two sets into a single set residing in a[low:high].
   b[ ] is an auxiliary global array. */
{
    h := low; i := low; j := mid + 1;
    while ((i ≤ mid) and (j ≤ high)) do
    {
        if (a[i] ≤ a[j]) then
        {
            b[h] := a[i]; i := i + 1;
        }
        else
        {
            b[h] := a[j]; j := j + 1;
        }
        h := h + 1;
    }
    if (i > mid) then
        for k := j to high do
        {
            b[h] := a[k]; h := h + 1;
        }
    else
        for k := i to mid do
        {
            b[h] := a[k]; h := h + 1;
        }
    for k := low to high do a[k] := b[k];
}

Examples

Ex. 1: a[1:10] = (310, 285, 179, 662, 351, 423, 861, 254, 450, 520). Trace merge sort on this array.

Ex. 2: a[1:7] = E, X, A, M, P, L, E

PhaseStepSublists
DivideStart[E X A M P L E]
Split[E X A M]   [P L E]
Split again[E X] [A M]   [P L] [E]
Single elements–[E] [X] [A] [M]   [P] [L] [E]
Conquer / MergeMerge pairs[E X] [A M]   [L P] [E]
Merge again[A E M X]   [E L P]
Final merge[A E E L M P X]

Tree of calls of MergeSort(1, 7)

1,71,45,7 1,23,45,67,7 1,12,23,34,45,56,6 mid = 4mid = 2mid = 6 mid = 1mid = 3mid = 5

Tree of calls of Merge

Each box is Merge(low, mid, high).

1,1,23,3,45,5,6 1,2,45,6,7 1,4,7

Tracing Merge(1, 4, 7)

Merging (A, E, M, X) and (E, L, P) gives (A, E, E, L, M, P, X). Here low = 1, mid = 4 and high = 7.

Index[1][2][3][4][5][6][7]
aAEMXELP
hiji ≤ mid and j ≤ highTest a[i] ≤ a[j]Actionb so far
1151 ≤ 4 and 5 ≤ 7A ≤ E, truecopy a[1] to b[1]A
2252 ≤ 4 and 5 ≤ 7E ≤ E, truecopy a[2] to b[2]A E
3353 ≤ 4 and 5 ≤ 7M ≤ E, falsecopy a[5] to b[3]A E E
4363 ≤ 4 and 6 ≤ 7M ≤ L, falsecopy a[6] to b[4]A E E L
5373 ≤ 4 and 7 ≤ 7M ≤ P, truecopy a[3] to b[5]A E E L M
6474 ≤ 4 and 7 ≤ 7X ≤ P, falsecopy a[7] to b[6]A E E L M P
7488 ≰ 7, loop ends–i = 4 ≤ mid, so copy a[4] to b[7]A E E L M P X

The leftover elements are copied with for k := i to mid, here k = 4 to 4. Finally b[1..7] is copied back to a[1..7].

Limitations

  1. It needs an auxiliary array with the same amount of storage as the input array, so this algorithm is not an in-place algorithm.
  2. It needs stack space for recursion, because the algorithm is designed in a top-down fashion. The stack takes O(log₂n) space.

Time complexity

T(n) = 1               when n = 1
     = 2T(n/2) + cn    otherwise

When n = 2k:

T(n) = 2[2T(n/4) + cn/2] + cn
     = 2²T(n/2²) + 2cn
       ⋮
     = 2ᵏT(n/2ᵏ) + k·cn
     = n + log₂n · cn

⇒ T(n) = O(n log₂ n)

Space complexity

Merge sort needs an auxiliary array of size n, plus O(log₂n) stack space for the recursion, so the extra space is O(n).

Merge sort is a stable sorting method (see the notes on quick sort).