Merge Sort
A sorting algorithm that follows the divide-and-conquer approach
Introduction
Merge sort is a sorting algorithm that follows the divide-and-conquer approach. It works by recursively dividing the input array into smaller subarrays and sorting those subarrays, then merging them back together to obtain the sorted array.
So, the process of merge sort is to divide the array into two halves, sort each half, and then merge the sorted halves back together. This process is repeated until the entire array is sorted.
Algorithm
Here’s a step-by-step explanation of how merge sort works:
Divide: Recursively split the list or array into two halves until they cannot be divided further.
Conquer: Sort each subarray individually using the merge sort algorithm.
Merge: Combine the sorted subarrays back together in order. Continue this process until all elements from both subarrays are merged.
Example
1
2
Input: 48 38 27 43 10 30
Output: 10 27 30 38 43 48
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
#define scan(n) scanf("%d", &n)
#define print(n) printf("%d", n);
#define space() printf(" ");
#define newLine() printf("\n");
#define FOR(i, a, b) for (int i = a; i <= b; i++)
void merge(vector<int> &nums, int left, int mid, int right)
{
// decare left and right subarray indices
int const leftSubArraySize = mid - left + 1;
int const rightSubArraySize = right - mid;
// declare and initialize left and right subarrays
auto *leftSubArray = new int[leftSubArraySize],
*rightSubArray = new int[rightSubArraySize];
// copy data to left subarray
FOR(i, 0, leftSubArraySize - 1)
{
leftSubArray[i] = nums[left + i];
}
// copy data to right subarray
FOR(i, 0, rightSubArraySize - 1)
{
rightSubArray[i] = nums[mid + 1 + i];
}
int currIndexOfRightSubArray = 0;
int currIndexOfMergeArray = left;
// Merge the two subarrays into the original array
FOR(i, 0, leftSubArraySize - 1)
{
if (currIndexOfRightSubArray >= rightSubArraySize)
{
nums[currIndexOfMergeArray++] = leftSubArray[i];
}
else
{
while (
currIndexOfRightSubArray < rightSubArraySize && rightSubArray[currIndexOfRightSubArray] <= leftSubArray[i])
{
nums[currIndexOfMergeArray++] = rightSubArray[currIndexOfRightSubArray++];
}
nums[currIndexOfMergeArray++] = leftSubArray[i];
}
}
// Deallocate memory
delete[] leftSubArray;
delete[] rightSubArray;
return;
}
void mergeSort(vector<int> &nums, int begin, int end)
{
if (begin < end)
{
// get the middle of the partition
int mid = begin + (end - begin) / 2;
// Sort both halves recursively
mergeSort(nums, begin, mid);
mergeSort(nums, mid + 1, end);
// Merge the sorted halves into the original array
merge(nums, begin, mid, end);
}
return;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("IO/input.txt", "r", stdin);
freopen("IO/output.txt", "w", stdout);
#endif // ONLINE_JUDGE
int n, totalCase;
vector<int> nums(100005);
scan(totalCase);
FOR(cs, 1, totalCase)
{
scan(n);
FOR(i, 0, n - 1)
{
scan(nums[i]);
}
mergeSort(nums, 0, n - 1);
FOR(i, 0, n - 1)
{
print(nums[i]);
space();
}
newLine();
}
return 0;
}
Complexity Analysis
Time Complexity
- Best Case:
Ω(nlogn)
, When the array is already sorted or nearly sorted. - Average Case:
θ(nlogn)
, When the array is randomly ordered. - Worst Case:
O(nlogn)
, When the array is sorted in reverse order.
Space Complexity
O(n)
, Additional space is required for the temporary array used during merging.
Advantages of Merge Sort
- Stability: Merge sort is a stable sorting algorithm, meaning it preserves the relative order of equal elements in the input array.
- Guaranteed Worst-Case Performance: Merge sort has a worst-case time complexity of
O(nlogn)
, ensuring good performance even on large datasets. - Simple to Implement: The divide-and-conquer approach used in merge sort is straightforward and easy to implement.
Disadvantages of Merge Sort
- Space Complexity: Merge sort requires additional memory to store the merged sub-arrays during the sorting process.
- Not In-Place: Merge sort is not an in-place sorting algorithm, meaning it needs extra memory to store the sorted data. This can be a disadvantage in applications where memory usage is a concern.