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.