![]() |
VOOZH | about |
Implement Merge Sort i.e. standard implementation keeping the sorting algorithm as in-place.
In-place means it does not occupy extra memory for merge operation as in the standard case.
Examples:
Input: arr[] = {2, 3, 4, 1}
Output: 1 2 3 4Input: arr[] = {56, 2, 45}
Output: 2 45 56
Approach 1:
Below is the implementation of the above approach:
5 6 7 11 12 13
Note: Time Complexity of above approach is O(n2 * log(n)) because merge is O(n2). Time complexity of standard merge sort is less, O(n Log n).
Approach 2: The idea: We start comparing elements that are far from each other rather than adjacent. Basically we are using shell sorting to merge two sorted arrays with O(1) extra space.
mergeSort():
merge():
Input: 10, 30, 14, 11, 16, 7, 28
Note: Assume left and right subarrays has been sorted so we are merging sorted subarrays [10, 14, 30] and [7, 11, 16, 28]
Start with
gap = ceiling of n/2 = 7/2 = 4
[This gap is for whole merged array]
10, 14, 30, 7, 11, 16, 28
10, 14, 30, 7, 11, 16, 28
10, 14, 30, 7, 11, 16, 28
10, 14, 28, 7, 11, 16, 30
gap = ceiling of 4/2 = 2
10, 14, 28, 7, 11, 16, 30
10, 14, 28, 7, 11, 16, 30
10, 7, 28, 14, 11, 16, 30
10, 7, 11, 14, 28, 16, 30
10, 7, 11, 14, 28, 16, 30
gap = ceiling of 2/2 = 1
10, 7, 11, 14, 28, 16, 30
7, 10, 11, 14, 28, 16, 30
7, 10, 11, 14, 28, 16, 30
7, 10, 11, 14, 28, 16, 30
7, 10, 11, 14, 28, 16, 30
7, 10, 11, 14, 16, 28, 30
Output: 7, 10, 11, 14, 16, 28, 30
Below is the implementation of the above approach:
5 6 7 11 12 13
Time Complexity: O(log n*nlog n)
Note: mergeSort method makes log n recursive calls and each time merge is called which takes n log n time to merge 2 sorted sub-arrays
Approach 3: Here we use the below technique:
Suppose we have a number A and we want to convert it to a number B and there is also a constraint that we can recover number A any time without using other variable.To achieve this we choose a number N which is greater than both numbers and add B*N in A. so A --> A+B*N To get number B out of (A+B*N) we divide (A+B*N) by N (A+B*N)/N = B. To get number A out of (A+B*N) we take modulo with N (A+B*N)%N = A. -> In short by taking modulo we get old number back and taking divide we new number.
mergeSort():
merge():
Below is the implementation of the above approach:
5 6 7 11 12 13
Time Complexity: O(n log n)
Note: Time Complexity of above approach is O(n2) because merge is O(n). Time complexity of standard merge sort is O(n log n).
Approach 4: Here we use the following technique to perform an in-place merge
Given 2 adjacent sorted sub-arrays within an array (hereafter named A and B for convenience), appreciate that we can swap some of the last portion of A with an equal number of elements from the start of B, such that after the exchange, all of the elements in A are less than or equal to any element in B. After this exchange, this leaves with the A containing 2 sorted sub-arrays, being the first original portion of A, and the first original portion of B, and sub-array B now containing 2 sorted sub-arrays, being the final original portion of A followed by the final original portion of B We can now recursively call the merge operation with the 2 sub-arrays of A, followed by recursively calling the merge operation with the 2 sub-arrays of B We stop the recursion when either A or B are empty, or when either sub-array is small enough to efficiently merge into the other sub-array using insertion sort.
The above procedure naturally lends itself to the following implementation of an in-place merge sort.
merge():
merge_sort():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Time Complexity of merge(): Worst Case: O(n^2), Average: O(n log n), Best: O(1)
Time Complexity of merge_sort() function: Overall: O(log n) for the recursion alone, due to always evenly dividing the array in 2
Time Complexity of merge_sort() overall: Worst Case: O(n^2 log n), Average: O(n (log n)^2), Best: O(log n)
The worst-case occurs when every sub-array exchange within merge() results in just _INSERT_THRESH-1 elements being exchanged