Understand the merge sort algorithm

    In this tutorial, you will learn the merge sort algorithm. In addition, you will find examples of merge sort in C language.
    Merge sort is one of the most popular sorting algorithms based on the principle of divide and conquer algorithm.
    Here, a problem is divided into multiple sub-problems. Each sub-problem is solved individually. Finally, combine the sub-problems to form the final solution.
Insert picture description here

Divide and conquer strategy

    Using divide and conquer technology, we divide the problem into sub-problems. When the solution to each sub-problem is ready, we "combine" the results of the sub-problems to solve the main problem.
    Suppose we have to sort the array A. The sub-problem is to sort a subsection of this array, starting from index p and ending with index r, which is expressed as A[p...r].
    Split
    If q is the midpoint between p and r, then we can divide the subarray A[p...r] into two arrays A[p...q] and A[q+1,r].
    Processing
    In the processing step, we try to sort the sub-arrays A[p...q] and A[q+1,r]. If we have not yet divided into the basic level, we divide the two sub-arrays again and try to sort them.     After the
    combination
of processing steps, we get two sorted sub-arrays A[p...q] and A[q+1,r]. After combining these two arrays, we get a sorted array A[p...r].

Merge sort algorithm

    The merge sort function repeatedly divides the array in half until we reach a stage in which we try to perform merge sort on a sub-array of size 1, that is, p==r.
    After that, the merge function comes into play and merges the sorted array into a larger array until the entire array is merged.

MergeSort(A, p, r):
    if p > r 
        return
    q = (p+r)/2
    mergeSort(A, p, q)
    mergeSort(A, q+1, r)
    merge(A, p, q, r)

    To sort the entire array, you need to call MergeSort(A, 0, length(A)-1).
    As shown in the figure below, the merge sort algorithm recursively divides the array in half until we get the basic situation of an array containing 1 element. After that, the merge function will select the sorted sub-arrays and merge them to gradually sort the entire array.
Insert picture description here

Merging steps of merge sort

    Every recursive algorithm relies on a basic situation and the ability to combine the results of the basic situation. The same is true for merge sort. The most important part of the merge sort algorithm is the merge step.
    The merge step solves the simple problem of merging two sorted lists (arrays) into one large sorted list (array).
    The algorithm maintains three pointers, one for each of the two arrays, and the other for maintaining the current index of the final sorted array.

我们已经到达任何阵列的末端了吗?
否:
  比较两个数组的当前元素
  将较小的元素复制到排序的数组中
  移动包含较小元素的元素的指针
是:
  复制非空数组的所有剩余元素

Insert picture description here

Write the code for the merge algorithm

    One obvious difference between the merge step described above and the merge step used for merge sort is that we only perform the merge function on consecutive sub-arrays.
    This is why we only need the array, the first position, the last index of the first sub-array (we can calculate the first index of the second sub-array) and the last index of the second sub-array.
    Our task is to merge two sub-arrays A[p...q] and A[q+1...r] to create a sorted array A[p...r]. So the input of the function is A, p, q and r.
    The working principle of the merge function is as follows:

  1. Create a copy of the sub-arrays L ← A[p…q] and M ← A[q+1…r].
  2. Create three pointers i, j and k
    a. Starting from 1, i keeps the current index as L
    b. Starting from 1, j keeps the current index as M
    c. Starting from p, k keeps the current index as A[p …Q].
  3. Before reaching the end of L or M, select the larger elements from L and M and place them in the correct position of A[p...q]
  4. When the elements in L or M are used up, select the remaining elements and put them in A[p...q]

    In the code, this looks like:

// Merge two subarrays L and M into arr
void merge(int arr[], int p, int q, int r) {
    
    

    // Create L ← A[p..q] and M ← A[q+1..r]
    int n1 = q - p + 1;
    int n2 = r - q;

    int L[n1], M[n2];

    for (int i = 0; i < n1; i++)
        L[i] = arr[p + i];
    for (int j = 0; j < n2; j++)
        M[j] = arr[q + 1 + j];

    // Maintain current index of sub-arrays and main array
    int i, j, k;
    i = 0;
    j = 0;
    k = p;

    // Until we reach either end of either L or M, pick larger among
    // elements L and M and place them in the correct position at A[p..r]
    while (i < n1 && j < n2) {
    
    
        if (L[i] <= M[j]) {
    
    
            arr[k] = L[i];
            i++;
        } else {
    
    
            arr[k] = M[j];
            j++;
        }
        k++;
    }

    // When we run out of elements in either L or M,
    // pick up the remaining elements and put in A[p..r]
    while (i < n1) {
    
    
        arr[k] = L[i];
        i++;
        k++;
    }

    while (j < n2) {
    
    
        arr[k] = M[j];
        j++;
        k++;
    }
}
Merge() function explained step by step

    A lot of things happen to this function, so let's take an example to see how it works.
Insert picture description here
    Array A [0…5] contains two sorted sub-arrays A [0…3] and A [4…5]. Let us see how the merge function merges two arrays.

void merge(int arr[], int p, int q, int r) {
    
    
// Here, p = 0, q = 4, r = 6 (size of array)

    Step 1: Create a copy of the sub-array to be sorted

    // Create L ← A[p..q] and M ← A[q+1..r]
    int n1 = q - p + 1 = 3 - 0 + 1 = 4;
    int n2 = r - q = 5 - 3 = 2;

    int L[4], M[2];

    for (int i = 0; i < 4; i++)
        L[i] = arr[p + i];
        // L[0,1,2,3] = A[0,1,2,3] = [1,5,10,12]

    for (int j = 0; j < 2; j++)
        M[j] = arr[q + 1 + j];
        // M[0,1,2,3] = A[4,5] = [6,9]

Insert picture description here
    Step 2: Maintain the current index of the sub-array and the main array

    int i, j, k;
    i = 0; 
    j = 0; 
    k = p; 

Insert picture description here
    Step 3: Before reaching the end of L or M, select the larger element from the elements L and M and place them in the correct position of A[p...r]

    while (i < n1 && j < n2) {
    
     
        if (L[i] <= M[j]) {
    
     
            arr[k] = L[i]; i++; 
        } 
        else {
    
     
            arr[k] = M[j]; 
            j++; 
        } 
        k++; 
    }

Insert picture description here
    Step 4: When the elements in L or M are used up, select the remaining elements and put in [p...r].

    // We exited the earlier loop because j < n2 doesn't hold
    while (i < n1)
    {
    
    
        arr[k] = L[i];
        i++;
        k++;
    }

Insert picture description here

    // We exited the earlier loop because i < n1 doesn't hold  
    while (j < n2)
    {
    
    
        arr[k] = M[j];
        j++;
        k++;
    }
}

Insert picture description here
    If the value of M is greater than L, this step is required.
    At the end of the merge function, the sub-array A[p...r] is sorted.

C example
// Merge sort in C

#include <stdio.h>

// Merge two subarrays L and M into arr
void merge(int arr[], int p, int q, int r) {
    
    

  // Create L ← A[p..q] and M ← A[q+1..r]
  int n1 = q - p + 1;
  int n2 = r - q;

  int L[n1], M[n2];

  for (int i = 0; i < n1; i++)
    L[i] = arr[p + i];
  for (int j = 0; j < n2; j++)
    M[j] = arr[q + 1 + j];

  // Maintain current index of sub-arrays and main array
  int i, j, k;
  i = 0;
  j = 0;
  k = p;

  // Until we reach either end of either L or M, pick larger among
  // elements L and M and place them in the correct position at A[p..r]
  while (i < n1 && j < n2) {
    
    
    if (L[i] <= M[j]) {
    
    
      arr[k] = L[i];
      i++;
    } else {
    
    
      arr[k] = M[j];
      j++;
    }
    k++;
  }

  // When we run out of elements in either L or M,
  // pick up the remaining elements and put in A[p..r]
  while (i < n1) {
    
    
    arr[k] = L[i];
    i++;
    k++;
  }

  while (j < n2) {
    
    
    arr[k] = M[j];
    j++;
    k++;
  }
}

// Divide the array into two subarrays, sort them and merge them
void mergeSort(int arr[], int l, int r) {
    
    
  if (l < r) {
    
    

    // m is the point where the array is divided into two subarrays
    int m = l + (r - l) / 2;

    mergeSort(arr, l, m);
    mergeSort(arr, m + 1, r);

    // Merge the sorted subarrays
    merge(arr, l, m, r);
  }
}

// Print the array
void printArray(int arr[], int size) {
    
    
  for (int i = 0; i < size; i++)
    printf("%d ", arr[i]);
  printf("\n");
}

// Driver program
int main() {
    
    
  int arr[] = {
    
    6, 5, 12, 10, 9, 1};
  int size = sizeof(arr) / sizeof(arr[0]);

  mergeSort(arr, 0, size - 1);

  printf("Sorted array: \n");
  printArray(arr, size);
}
Merge sort complexity

    Time complexity
    Best case complexity: O(n * log n)
    Worst case complexity: O(n * log n)
    Average case complexity: O(n * log n)
    Space complexity The space complexity of
    merge sort Is O(n).

Merge sort application
  • Countdown problem
  • External classification
  • E-commerce application
Reference documents

[1]Parewa Labs Pvt. Ltd.Merge Sort Algorithm[EB/OL].https://www.programiz.com/dsa/merge-sort,2020-01-01.

Guess you like

Origin blog.csdn.net/zsx0728/article/details/114823007