Explanation: Although merge sort runs in Ω(nlgn) and insertion sort runs in Ω(n^2), the constant factors in insertion sort can make it faster in implementation for small problem sizes. This sorting implementation should still be stable.
Recursive Merge sort subroutine method:
private static void recursiveMergeSort(double[] arr, int lowerBound, int upperBound) {
if (lowerBound < upperBound) {
// Split the sub array into halves
int mid = lowerBound + (upperBound - lowerBound) / 2;
recursiveMergeSort(arr, lowerBound, mid);
recursiveMergeSort(arr, mid + 1, upperBound);
merge(arr, lowerBound, mid, upperBound);
}
}
Merge method: *note- I would like to replace the while loop with for and if-else statements.
private static void merge(double[] arr, int left, int mid, int right) {
int i = 0, j = 0, k = left;
//System.out.println("used merge");
// Sizes of the temporary arrays to be copied
int n1 = (mid - left) + 1;
int n2 = (right - mid);
// Create temporary arrays and copy data
double[] leftTemp = Arrays.copyOfRange(arr, left, mid + 1);
double[] rightTemp = Arrays.copyOfRange(arr, mid + 1, right + 1);
// Merge the temp arrays back into arr[left...right]
while (i < n1 && j < n2) {
if (leftTemp[i] <= rightTemp[j]) {
arr[k++] = leftTemp[i++];
} else {
arr[k++] = rightTemp[j++];
}
}
// Copy remaining elements, if any
while (i < n1) {
arr[k++] = leftTemp[i++];
}
while (j < n2) {
arr[k++] = rightTemp[j++];
}
}
Insertion sort subroutine method:
private static void insertionSort(double[] arr, int left, int right){
for (int i = left + 1; i <= right; i++) {
double key = arr[i];
int j = i - 1;
while (j >= left && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
}
Hybrid merge/insertion sorting method:
Optimized is a value that is best set between [25,100]
private static void insertionRecursiveMergeSort(double[] arr, int left, int right) {
// If <= OPTIMIZED use insertion sort subroutine
if (right <= left + OPTIMIZED - 1) {
insertionSort(arr, left, right);
} else {
int mid = left + (right - left) / 2;
insertionRecursiveMergeSort(arr, left, mid);
insertionRecursiveMergeSort(arr, mid + 1, right);
merge(arr, left, mid, right);
}
}
For test runs, I used array sizes 1M, 2M, 3M, and 5M with optimized set to 25, 50, 100, and 125.