Article Directory
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.
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.
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.
我们已经到达任何阵列的末端了吗?
否:
比较两个数组的当前元素
将较小的元素复制到排序的数组中
移动包含较小元素的元素的指针
是:
复制非空数组的所有剩余元素
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:
- Create a copy of the sub-arrays L ← A[p…q] and M ← A[q+1…r].
- 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]. - 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]
- 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.
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]
Step 2: Maintain the current index of the sub-array and the main array
int i, j, k;
i = 0;
j = 0;
k = p;
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++;
}
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++;
}
// We exited the earlier loop because i < n1 doesn't hold
while (j < n2)
{
arr[k] = M[j];
j++;
k++;
}
}
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.