Search code examples
c++arrayspointersmergesort

C++ How MergeSort returns nothing but works fine?


This is the implementation of merge sort below. However, I don't understand how this code even works. We don't use pointers and nothing is returned in main(). So, how does it manipulate myarray? Can anyone explain?

Here is the code:

#include <iostream>
using namespace std;

void merge(int arr[], int l, int m, int r) {
  int i = l;
  int j = m + 1;
  int k = l;

  /* create temp array */
  int temp[5];

  while (i <= m && j <= r) {
    if (arr[i] <= arr[j]) {
      temp[k] = arr[i];
      i++;
      k++;
    } else {
      temp[k] = arr[j];
      j++;
      k++;
    }
  }

  /* Copy the remaining elements of first half, if there are any */
  while (i <= m) {
    temp[k] = arr[i];
    i++;
    k++;
  }

  /* Copy the remaining elements of second half, if there are any */
  while (j <= r) {
    temp[k] = arr[j];
    j++;
    k++;
  }

  /* Copy the temp array to original array */
  for (int p = l; p <= r; p++) {
    arr[p] = temp[p];
  }
}

mergeSort function:

/* l is for left index and r is right index of the 
   sub-array of arr to be sorted */
void mergeSort(int arr[], int l, int r) {
  if (l < r) {
    // find midpoint
    int m = (l + r) / 2;

    // recursive mergesort first and second halves 
    mergeSort(arr, l, m);
    mergeSort(arr, m + 1, r);

    // merge
    merge(arr, l, m, r);
  }
}

Main function:

int main() {
  int myarray[5];
  //int arr_size = sizeof(myarray)/sizeof(myarray[0]);
  int arr_size = 5;

  cout << "Enter 5 integers in any order: " << endl;
  for (int i = 0; i < 5; i++) {
    cin >> myarray[i];
  }
  cout << "Before Sorting" << endl;
  for (int i = 0; i < 5; i++) {
    cout << myarray[i] << " ";
  }
  cout << endl;
  mergeSort(myarray, 0, (arr_size - 1)); // mergesort(arr,left,right) called

  cout << "After Sorting" << endl;
  for (int i = 0; i < 5; i++) {
    cout << myarray[i] << " ";
  }

  return 0;
}

Solution

  • This program uses two obscure features of C++ that were acquired from C for backwards compatibility.

    1. Array-to-pointer decay. In most contexts, mentioning an array name is actually a shorthand of taking the address of the array's first element. Thus, mergeSort(myarray, ...) is the same as mergeSort(&myarray[0], ...).
    2. Function parameter type adjustments. You cannot pass an array to a function by value, so what does void mergeSort(int arr[], ...) ever mean? Just like in C, a function parameter of type array-of-something gets adjusted to pointer-to-something. So this function is exactly the same as void mergeSort(int* arr, ...)

    So this program does use pointers after all, they are just thinly veiled.

    The features mentioned above are essential for dealing with C-style arrays. C++ has alternatives to C-style arrays, namely std::array and std::vector, which are usually recommended in most cases. Note, in order to get the same behaviour as in your program one usually passes these containers by reference.