Lesson 6
Exploring Merge Sort in C++
Welcome to Merge Sort in C++

Welcome, aspiring programmer! Today's topic is Merge Sort. Merge Sort is a sorting technique similar to arranging a deck of shuffled cards in order. However, for data on an Internet scale, Merge Sort outperforms regular techniques. Today, we'll explore Merge Sort, code it in C++, and analyze its speed. Ready? Let's get started!

What is Merge Sort?

In computer science, Merge Sort is a popular method for sorting elements. Merge Sort uses the same 'divide-and-conquer' strategy for sorting as the familiar Quick Sort algorithm. In the three steps of Merge Sort:

  1. Split the array into halves.
  2. Sort each half separately.
  3. Merge the sorted halves back together.
Understanding the Merge Process

We will start by building code for merging two sorted parts. The merge process makes two halves play sort and seek. It compares elements from two halves and merges them so that the resulting list is sorted as well.

Let's code a merge() function in C++ that will do just that. Note that the final variant of the Merge Sort function will perform every operation "in place," meaning there will not be actual two arrays; we will operate on parts of one array. Bearing this in mind, let's implement the merge function to take just one array and treat its parts like separate arrays.

C++
1void merge(int arr[], int left, int mid, int right) 2{ 3 int n1 = mid - left + 1; // Find number of elements in the left array 4 int n2 = right - mid; // Find the number of elements in the right array 5 6 int* Left = new int[n1]; // Define left array 7 int* Right = new int[n2]; // Define right array 8 9 // Let's fill in these arrays 10 for (int i = 0; i < n1; i++) 11 Left[i] = arr[left + i]; 12 for (int j = 0; j < n2; j++) 13 Right[j] = arr[mid + 1 + j]; 14}

So far, we've divided our original list into two halves, Left and Right.

Merging the Halves Back Together

Now, we'll sort and merge these halves:

C++
1 int i = 0, j = 0; 2 int k = left; 3 while (i < n1 && j < n2) 4 { 5 if (Left[i] <= Right[j]) 6 { 7 arr[k++] = Left[i++]; 8 } 9 else 10 { 11 arr[k++] = Right[j++]; 12 } 13 } 14}

Seemingly tricky, the code is very straightforward:

  • We place two pointers, i and j, at the beginning of the Left and Right arrays.

  • We choose the smaller element, put it in the final array arr, and move the corresponding pointer further.

  • We keep doing this until one of the pointers reaches the end of its array.

Handling Leftovers

We stop the process when one of the pointers reaches the end of its array, but some elements could be left in the other array.

To handle this, let's copy the remaining elements of both arrays (if any) to the end of the resulting arr array.

C++
1 // Copy remaining elements of Left[] if any 2 while (i < n1) 3 { 4 arr[k++] = Left[i++]; 5 } 6 7 // Copy remaining elements of Right[] if any 8 while (j < n2) 9 { 10 arr[k++] = Right[j++]; 11 } 12 13 delete[] Left; // Clean up dynamically allocated memory 14 delete[] Right; // Clean up dynamically allocated memory

The merge section is completed. It successfully merges two halves back together in sorted order.

Implementing Divide and Conquer Strategy

Now, let's implement the method to divide the array into two halves. Coding-wise, we'll need to define a sort() method to split the array and manage the merge process. We will split the array and its halves recursively until we end up with small arrays of just one element, which are naturally sorted! Next, we will merge these arrays back together into one big sorted array.

Splitting the Array into Halves

Let's start building the sort() method. Initially, we'll handle the splitting part:

C++
1void sort(int arr[], int left, int right) 2{ 3 if (left < right) 4 { 5 int mid = left + (right - left) / 2; // Finding the midpoint 6 } 7}

Now, we can split our list into two halves, but they still need to be sorted.

Marshalling the Merge Process

Next, we need to sort these halves and merge them together:

C++
1 sort(arr, left, mid); // Sorting the left half 2 sort(arr, mid + 1, right); // Sorting the right half 3 merge(arr, left, mid, right); // Merging the sorted halves 4 } 5}

Phew! We've now implemented our Merge Sort algorithm in C++.

Complete Merge Sort Implementation in C++

Here is the full code for the Merge Sort algorithm implemented in C++:

C++
1#include <iostream> 2 3using namespace std; 4 5// Method to merge two halves 6void merge(int arr[], int left, int mid, int right) 7{ 8 int n1 = mid - left + 1; 9 int n2 = right - mid; 10 11 int* Left = new int[n1]; 12 int* Right = new int[n2]; 13 14 // Fill the left and right arrays 15 for (int i = 0; i < n1; i++) 16 Left[i] = arr[left + i]; 17 for (int j = 0; j < n2; j++) 18 Right[j] = arr[mid + 1 + j]; 19 20 int i = 0, j = 0; 21 int k = left; 22 while (i < n1 && j < n2) 23 { 24 if (Left[i] <= Right[j]) 25 { 26 arr[k++] = Left[i++]; 27 } 28 else 29 { 30 arr[k++] = Right[j++]; 31 } 32 } 33 34 // Copy remaining elements of Left[] if any 35 while (i < n1) 36 { 37 arr[k++] = Left[i++]; 38 } 39 40 // Copy remaining elements of Right[] if any 41 while (j < n2) 42 { 43 arr[k++] = Right[j++]; 44 } 45 46 delete[] Left; 47 delete[] Right; 48} 49 50// Method to divide and sort the array 51void sort(int arr[], int left, int right) 52{ 53 if (left < right) 54 { 55 int mid = left + (right - left) / 2; 56 57 // Recursively sorting the first and second halves 58 sort(arr, left, mid); 59 sort(arr, mid + 1, right); 60 61 // Merging the sorted halves 62 merge(arr, left, mid, right); 63 } 64} 65 66int main() 67{ 68 int arr[] = {38, 27, 43, 3, 9, 82, 10}; 69 int arr_size = sizeof(arr)/sizeof(arr[0]); 70 71 cout << "Given array is \n"; 72 for(int i = 0; i < arr_size; i++) 73 cout << arr[i] << " "; 74 cout << endl; 75 76 sort(arr, 0, arr_size - 1); 77 78 cout << "\nSorted array is \n"; 79 for(int i = 0; i < arr_size; i++) 80 cout << arr[i] << " "; 81 cout << endl; 82 83 return 0; 84}
Decoding Merge Sort Efficiency

In the computing world, performance matters. The less time it takes for a sorting algorithm to run, the better. Merge Sort shows good performance with a time complexity of O(n log n), similar to sorting a huge deck of cards quickly. Thus, it excels when dealing with massive data sets.

Strengths and Pitfalls of Merge Sort

Merge Sort is consistent. It's like a reliable late-night tutor that offers predictable performance, regardless of the initial order of the data input. However, it tends to use extra memory, creating new arrays during the merge process.

Summary

Great job! We've broken down Merge Sort and coded it in C++. Next up, we have some exciting hands-on exercises for you. Ready to put what you've learned into practice? Let's dive into the fun part! Let's get coding!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.