Home | Projects | Notes > Data Structures & Algorithms > Merge Sort: T = O(n logn) , S = O(n)
Merge Sort is a divide-and-conquer sorting algorithm that:
Recursively divides the array into halves until single elements remain.
Then merges those halves back together in sorted order.
Merge sort is a stable, efficient sorting algorithm with a time complexity of O(n log n), making it well-suited for large datasets.
Technically:
The n log n term comes from dividing the array in half log n times and processing n elements at each level during merging.
The extra n term accounts for the total number of splits, but it’s non-dominant, so it's omitted in the final complexity.
Space complexity is O(n) because merge sort needs additional memory to hold temporary subarrays during merging.
merge_sort.cpp)x
123
4// merge two sorted halves into original array5void merge(std::vector<int> &arr, const std::vector<int> &left, const std::vector<int> &right)6{7 int i = 0; // index for origiinal array8 int l = 0; // index for left subarray9 int r = 0; // index for right subarray10
11 // merge elements of two subarrays12 while (l < left.size() && r < right.size())13 {14 if (left[l] <= right[r])15 {16 arr[i++] = left[l++];17 }18 else19 {20 arr[i++] = right[r++];21 }22 }23
24 // copy remaining elements (only one subarray may ahve leftovers)25 while (l < left.size())26 {27 arr[i++] = left[l++];28 }29 while (r < right.size())30 {31 arr[i++] = right[r++];32 }33}34
35// recursive merge sort36void merge_sort(std::vector<int> &arr)37{38 // base case39 if (arr.size() <= 1)40 {41 return;42 }43
44 int mid = arr.size() / 2;45
46 std::vector<int> left(arr.begin(), arr.begin() + mid); // [arr[0], arr[mid - 1]] 47 std::vector<int> right(arr.begin() + mid, arr.end()); // [arr[mid], arr[arr.size() - 1]]48
49 // recursive case50 merge_sort(left);51 merge_sort(right);52 merge(arr, left, right);53}54
55int main(int argc, char *argv[])56{57 std::vector<int> arr = {5, 2, 9, 1, 5, 6};58 merge_sort(arr);59 60 for (auto &elem : arr)61 {62 std::cout << elem << " ";63 }64 65 std::cout << std::endl;66 67 return 0;68}x
11 2 5 5 6 9
merge_sort.c)123
4// merge two sorted subarrays into the original array5void merge(int *arr, const int *left, const int l_size, const int *right, const int r_size)6{7 int i = 0; // index for original array 8 int l = 0; // index for left subarray 9 int r = 0; // index for right subarray 10
11 // merge elements of two subarrays12 while (l < l_size && r < r_size)13 {14 if (left[l] <= right[r])15 {16 arr[i++] = left[l++];17 }18 else19 {20 arr[i++] = right[r++];21 }22 }23
24 // copy remaining elements (only one subarray may ahve leftovers)25 while (l < l_size)26 {27 arr[i++] = left[l++];28 }29
30 while (r < r_size)31 {32 arr[i++] = right[r++];33 }34}35
36// recursive merge sort37void merge_sort(int *arr, int size)38{39 if (size <= 1)40 {41 return;42 }43
44 int mid = size / 2;45
46 // allocate and copy left and right halves47 int *left = (int *)malloc(mid * sizeof(int));48 int *right = (int *)malloc((size - mid) * sizeof(int));49
50 for (int l = 0; l < mid; ++l)51 {52 left[l] = arr[l];53 }54
55 for (int r = mid; r < size; ++r)56 {57 right[r - mid] = arr[r];58 }59
60 merge_sort(left, mid);61 merge_sort(left, size - mid);62 merge(arr, left, mid, right, size - mid);63
64 free(left);65 free(right);66}67
68int main(int argc, char *argv[])69{70 int arr[] = {5, 2, 9, 1, 5, 6};71 int size = sizeof(arr) / sizeof(arr[0]);72
73 merge_sort(arr, size);74
75 for (int i = 0; i < size; ++i)76 {77 printf("%d ", arr[i]);78 }79
80 puts("");81 82 return 0;83}111 2 5 5 6 9