DEV Community

James Robb
James Robb

Posted on

Merge sort

In my mind, merge sort is a more complex version of quick sort but this complexity brings more consistent performance gains over quick sort, which is impressive considering that quick sort is already O(n log n) in performance which is as fast as we can get for a comparison algorithm.

Implementation

Below we can see an example of merge sort written in JavaScript:

function merge(left, right) {
  const result = [];

  while(left.length || right.length) {
    if(left.length && right.length) {
      result.push(left[0] < right[0] ? left.shift() : right.shift());
    } else {
      result.push(left.length ? left.shift() : right.shift());
    }
  }

  return result;
}

function mergeSort(array) {
  if(array.length <= 1) return array;

  const middle = array.length / 2 ;
  const left = array.slice(0, middle);
  const right = array.slice(middle, array.length);

  return merge(
    mergeSort(left),
    mergeSort(right)
  );
}
Enter fullscreen mode Exit fullscreen mode

We have 2 function declarations, one to run the merge sort algorithm over an array and another to merge the left and right arrays which we will generate in that algorithm.

Looking at the mergeSort function we can see that just like in our quick sort implementation we return the array straight away if it contains 1 or less items. If we have more than one item, we reach for the middle of the array and take left and right slices from the array using the middle as the cut off point for each side. You may be asking yourself:

What happens if the array has a length which is odd?

Well, let's look at a working example with an even length array:

const array = [3, 1, 4, 2];
const middle = array.length / 2; // 2
const left = array.slice(0, middle); // [3, 1]
const right = array.slice(middle, array.length); // [4, 2]
Enter fullscreen mode Exit fullscreen mode

And an odd length array:

const array = [3, 1, 4];
const middle = array.length / 2; // 1.5
const left = array.slice(0, middle); // [3]
const right = array.slice(middle, array.length); // [1, 4]
Enter fullscreen mode Exit fullscreen mode

As we can see, in JavaScripts case, if we slice with a float, the float is floored and with the example above we can see how the left and right slices are formed! Ok, so, from here, we will move onto the return value of the mergeSort function which basically recursively splits the left and right arrays and merges them back together in the right order via the merge function which we will look at next.

The merge function runs a loop that lasts for as long as the left and right arrays have items within them. With each iteration, we check if left AND right have items and if so, we compare the first items from each side and if the first item of left is less than the first item of right, we push the first item of left into the result array otherwise the first of right. If left OR right have no length, we check which one has items still and add the first item from it into the result array until no items remain and the loop exits, whereby we finally return the sorted output array.

Use case and Performance

Merge sort has a great Big O time complexity of O(n log n) on average. This means that the time it takes to run the algorithm is the square of the size of the input array, otherwise known as linearithmic time which is the fastest possible time complexity for a comparison sort algorithm.

Let's look at some example runtimes from given input sizes:

Input size Time complexity (Big O)
10 O(10 log 10) = O(10)
100 O(100 log 100) = O(200)
1000 O(1,000 log 1,000) = O(3,000)

Compared to quick sort, these performance statistics aren't much to write home about but that only accounts for the average case, merge sort trumps quick sort in performance because the worst case is also O(n log n) whereas the worst for quick sort is O(n²). Merge sort is great and adds complexity as a tradeoff for performance. In general though, it is up to you if you prefer quick sort or merge sort but both are great divide-and-conquer option to have under your belt!

Top comments (0)