Merge Sort (OCR A Level Computer Science)

Revision Note

Test yourself
Robert Hampton

Written by: Robert Hampton

Reviewed by: James Woodhouse

Merge sort

What is a Merge Sort?

  • Merge sort is an example of a divide and conquer algorithm that reduces the size of the problem into smaller problems that are more easily solvable by an algorithm

  • Specifically, the merge sort divides the list in half, creating two sub lists. Each sub list is then divided into two until each sub list contains only one item or element

  • Groups of two sub lists are then sorted and merged together to form new, larger sub lists until all sub lists have been merged into a single sorted list

  • The merge sort therefore contains two parts:

    • Part one: Divide the list into sub lists until each sub list contains only one element

    • Part two: Repeatedly merge groups of two and sort them, until all lists have been merged into a single sorted list

  • The merge sort has been illustrated below using a list of ten items: [15, 5, 2, 7, 4, 9, 10, 1, 8, 3]

Performing the Merge sort

performing-the-merge-sort-revision-notes-computer-science

Figure 1: Performing the Merge sort

  • Notice that halving the list sometimes produces odd numbers of elements in sub lists. When dividing, all sub lists must contain a single element before merging can begin.

  • When merging, only two sub lists can be merged at a time. Any left over sub lists are merged in the next merging iteration

  • In order to merge two sub lists, two pointers are required, one for each sub list. The pointer keeps track of which elements are to be compared. Once an element has been merged into the new list, the corresponding pointer is incremented. The process continues until a list contains no elements to compare, at which point the remaining elements are appended to the end of the new merged sub list.

Time Complexity of a Merge Sort

  • To determine the algorithm's execution time as measured by the number of instructions or steps carried out Big-O notation must be used

  • The time complexity of a merge sort is dependent on its divide and conquer nature O(logn) and the fact that n sub lists must be merged. This means the overall worst case time complexity of the merge sort is O(nlogn)

  • The best case and average case scenario time complexity of the merge sort is O(nlogn) as regardless of the number of elements or item, n must still be merged and halved

Space Complexity of a Merge Sort

  • The merge sort requires twice the amount of space of other sorting algorithms due to holding copies of the left and right halves of the list. Its space complexity is therefore O(n) original space and an additional O(n) space to store the copies of the list

Tracing a Merge Sort

  • In the trace table below, several calls to merge sort are made which splits the list. Each call generates a stack frame which is put on the stack. Stack frames are removed when the current stack frame reaches the end of its code

  • The list is gradually broken down into sub lists, starting with the left side of each sub list. Sub lists are created until each sub list contains only one element which is the base case. When a base case is reached the stack frame is removed and the program continues execution on the line after the call to merge sort

  • Each sub list is gradually merged, two at a time and passed up the stack to be merged with another sub list in a later merge sort call

  • Pointers are incremented during the merge such that the next element to merge in each sub list is tracked and appropriately added to the new list. NewListPointer tracks the position of elements in the new list

  • Row 25 shows the algorithm completing the left side of the list and the beginning of the merge of the right sub list which repeats the process outlined in the trace table

Trace Table for the Merge Sort

Row

Stack frame

len(list) > 1?

left

right

Split left, right or merge?

newList

mid

Left

Pointer

Right

Pointer

newListPointer

1

1

TRUE

15, 5, 2, 7, 4

9, 10, 1, 8, 3

LEFT

 

5

 

 

 

2

2

TRUE

15, 5

2, 7, 4

LEFT

 

2

 

 

 

3

3

TRUE

15

5

LEFT

 

0

 

 

 

4

4

FALSE

 

 

BASE CASE

 

 

 

 

 

5

3

TRUE

15

5

RIGHT

 

0

 

 

 

6

4

FALSE

 

 

BASE CASE

 

 

 

 

 

7

3

TRUE

15

5

MERGE

[5, 15]

0

0

0

0

8

3

TRUE

2

7, 4

LEFT

 

1

 

 

 

9

4

FALSE

 

 

BASE CASE

 

 

 

 

 

10

3

TRUE

7

4

LEFT

 

0

 

 

 

11

4

FALSE

 

 

BASE CASE

 

 

 

 

 

12

3

TRUE

7

4

RIGHT

 

0

 

 

 

13

4

FALSE

 

 

BASE CASE

 

 

 

 

 

14

3

TRUE

7

4

MERGE

[4, 7]

0

0

0

0

15

3

TRUE

2

4, 7

MERGE

 

1

0

0

0

16

 

 

 

 

 

[2]

 

1

 

1

17

 

 

 

 

 

[2, 4]

 

 

1

2

18

 

 

 

 

 

[2, 4, 7]

 

 

2

3

19

3

TRUE

5, 15

2, 4, 7

MERGE

 

2

0

0

0

20

 

 

 

 

 

[2]

 

 

1

1

21

 

 

 

 

 

[2, 4]

 

 

2

2

22

 

 

 

 

 

[2, 4, 5]

 

1

2

3

23

 

 

 

 

 

[2, 4, 5, 7]

 

1

3

4

24

 

 

 

 

 

[2, 4, 5, 7, 15]

 

1

4

5

25

2

TRUE

9, 10

1, 8 3

LEFT

 

2

 

 

 

Examiner Tips and Tricks

Merge sort is a complex algorithm. You will not be asked to derive its time or space complexity in detail.

  • You will however be expected to know and justify its time and space complexity

Implementing a merge sort

Pseudocode

procedure mergesort(list)
	if len(list) > 1 then
		mid = len(list) div 2
		left = list[:mid]
		right = list[mid:]
		
		mergesort(left)
		mergesort(right)
		
		leftPointer = 0
		rightPointer = 0
		newListPointer = 0
		while leftPointer < len(left) and rightPointer < len(right)
			if left[leftPointer] < right[rightPointer] then
				list[newListPointer] = left[leftPointer]
				leftPointer = leftPointer + 1
			else
				list[newListPointer] = right[rightPointer]
				rightPointer = rightPointer + 1
			endif
		
			newListPointer = newListPointer + 1
		endwhile
		
		while leftPointer < len(left)
			list[newListPointer] = left[leftPointer]
			leftPointer = leftPointer + 1
			newListPointer = newListPointer + 1
		endwhile

		while rightPointer < len(right)
			list[newListPointer] = right[rightPointer]
			rightPointer = rightPointer + 1
			newListPointer = newListPointer + 1
		endwhile
	endif
endprocedure

list = [15, 5, 2, 7, 4, 9, 10, 1, 8, 3]
mergesort(list)
print(list)
  • It is important to note that the merge sort uses [popover id="N-tIO9JV~O-0w97n" label="recursion"] in order to work. To divide the list into sub lists, the merge sort algorithm must call itself, using a [popover id="5UjdORCO7kg2tW1L" label="base case"] of one element. Repeated calls to the algorithm are put on the [popover id="vZKPSwu5BsgHPpV_" label="stack"]. Once each list is composed on one element, [popover id="eAY1NI_y6NFvH4Le" label="stack frame"] are removed from the stack and processed

  • It is furthermore important to note that [:mid] means “all elements up to but not including the mid value” and [mid:] means “all elements starting from and including the mid value”

    • This technique is known as slicing

  • Once the list has been split, and no more recursive calls are made, three new variables are defined per stack frame:

    • leftPointer (keeps track of the left sub list)

    • rightPointer (keeps track of the right sub list)

    • newListPointer (keeps track of the next available space in the sorted list)

  • The new list is merged in two stages:

    • Stage one: Merge all elements until one list is empty

      • The first while loop manages this process. The left and right pointers increment over the left and right lists, comparing elements one at a time. If one is smaller than the other then it is placed in the next available space in the new list

    • Stage two: Append the non-empty list's remaining elements to the new list

      • This is managed by the final two while loops. One merges if the left half has remaining elements. The other merges if the right half has remaining elements. Only one will be called, not both

Python

def merge_sort(list):
  if len(list) > 1:
    mid = len(list) // 2
    left = list[:mid]
    right = list[mid:]
    merge_sort(left)
    merge_sort(right)
    left_pointer, right_pointer, new_list_pointer = 0, 0, 0
    new_list = [None] * len(list)
    while left_pointer < len(left) and right_pointer < len(right):
      if left[left_pointer] < right[right_pointer]:
        new_list[new_list_pointer] = left[left_pointer]
        left_pointer = left_pointer + 1
      else:
        new_list[new_list_pointer] = right[right_pointer]
        right_pointer = right_pointer + 1
      new_list_pointer = new_list_pointer + 1
    while left_pointer < len(left):
      new_list[new_list_pointer] = left[left_pointer]
      left_pointer = left_pointer + 1
      new_list_pointer = new_list_pointer + 1
    while right_pointer < len(right):
      new_list[new_list_pointer] = right[right_pointer]
      right_pointer = right_pointer + 1
      new_list_pointer = new_list_pointer + 1
    list[:] = new_list
  return list

list = [15, 5, 2, 7, 4, 9, 10, 1, 8, 3]
merge_sort(list)
print(list)  # Output: [1, 2, 3, 4, 5, 7, 8, 9, 10, 15]

Java

public class MergeSort {

    public static void mergeSort(int[] data) {
        if (data.length > 1) {
            int mid = data.length / 2;
            int[] left = new int[mid];
            int[] right = new int[data.length - mid];
            System.arraycopy(data, 0, left, 0, mid);
            System.arraycopy(data, mid, right, 0, data.length - mid);
            mergeSort(left);
            mergeSort(right);
            merge(data, left, right);
        }
    }

    private static void merge(int[] data, int[] left, int[] right) {
        int leftPointer = 0, rightPointer = 0, newListPointer = 0;
        while (leftPointer < left.length && rightPointer < right.length) {
            if (left[leftPointer] < right[rightPointer]) {
                data[newListPointer] = left[leftPointer];
                leftPointer++;
            } else {
                data[newListPointer] = right[rightPointer];
                rightPointer++;
            }
            newListPointer++;
        }
        System.arraycopy(left, leftPointer, data, newListPointer, left.length - leftPointer);
        System.arraycopy(right, rightPointer, data, newListPointer, right.length - rightPointer);
    }

    public static void main(String[] args) {
        int[] data = {15, 5, 2, 7, 4, 9, 10, 1, 8, 3};
        mergeSort(data);
        System.out.println(Arrays.toString(data));  // Output: [1, 2, 3, 4, 5, 7, 8, 9, 10, 15]
    }
}

Last updated:

You've read 0 of your 5 free revision notes this week

Sign up now. It’s free!

Join the 100,000+ Students that ❤️ Save My Exams

the (exam) results speak for themselves:

Did this page help you?

Robert Hampton

Author: Robert Hampton

Expertise: Computer Science Content Creator

Rob has over 16 years' experience teaching Computer Science and ICT at KS3 & GCSE levels. Rob has demonstrated strong leadership as Head of Department since 2012 and previously supported teacher development as a Specialist Leader of Education, empowering departments to excel in Computer Science. Beyond his tech expertise, Robert embraces the virtual world as an avid gamer, conquering digital battlefields when he's not coding.

James Woodhouse

Author: James Woodhouse

Expertise: Computer Science

James graduated from the University of Sunderland with a degree in ICT and Computing education. He has over 14 years of experience both teaching and leading in Computer Science, specialising in teaching GCSE and A-level. James has held various leadership roles, including Head of Computer Science and coordinator positions for Key Stage 3 and Key Stage 4. James has a keen interest in networking security and technologies aimed at preventing security breaches.