/**
* Merges two sorted arrays into one.
* Precondition: Two input arrays are sorted in ascending order and not null
* @param left sorted array
* @param right sorted array
* @return merged array where elements are sorted
*/
private static int[] merge(int[] left, int[] right) {
int[] merged = new int[left.length + right.length];
int indexLeft = 0, indexRight = 0, indexMerged = 0;
// Traverse and sort values into merged array from left or right
while (indexLeft < left.length && indexRight < right.length) {
if (left[indexLeft] < right[indexRight]) {
merged[indexMerged] = left[indexLeft];
indexLeft = indexLeft + 1;
} else {
merged[indexMerged] = right[indexRight];
indexRight = indexRight + 1;
}
indexMerged = indexMerged + 1;
}
// Not all the elements are copied over to merged array
if (indexLeft < left.length) {
for (int i = indexLeft; i < left.length; i++) {
merged[indexMerged] = left[i];
indexMerged = indexMerged + 1;
}
} else {
for (int i = indexRight; i < right.length; i++) {
merged[indexMerged] = right[i];
indexMerged = indexMerged + 1;
}
}
return merged;
}
/**
* Recursive merge sort.
* Creates new array where values are sorted in ascending order.
* @param unsorted array
* @return sorted array
*/
public static int[] mergeSort(int[] unsorted) {
// Base case
if (unsorted.length <= 1) {
return unsorted;
}
// Recursive case: divide into two halves
int mid = unsorted.length / 2;
int[] left = new int[mid];
System.arraycopy(unsorted, 0, left, 0, mid);
int[] right = new int[unsorted.length - mid];
System.arraycopy(unsorted, mid, right, 0, right.length);
// sort the left half using merge sort
left = mergeSort(left);
// sort the right half using merge sort
right = mergeSort(right);
// merge sorted halves into the final result
return merge(left, right);
}
Recurrence relation using substitution method:
T(n) = 1 if n <= 1
T(n) = 2T(n/2) + n if n > 1
2 * T(n/2) + n
=> 4 * T(n/4) + 2n
=> 8 * T(n/8) + 3n
=> 16 * T(n/16) + 4n
...
=> 2^k * T(n/2^k) + k * n
=> n + log2{n} * n
n/2^k = 1
n = 2^k
k = log2{n}
/**
* Quick sort.
* @param unsorted an array to sort
*/
public static void quickSort(int[] unsorted) {
quickSort(unsorted, 0, unsorted.length - 1);
}
/**
* Private helper method for recursive quick sort.
* Sorts values of input array in ascending order.
* @param unsorted array
* @param left boundary index
* @param right boundary index
*/
private static void quickSort(int[] unsorted, int left, int right) {
// Base case
if (left >= right) {
return;
}
// Recursive case
int pivot = unsorted[right];
// Partition into left and right subgroups using the pivot value and get index of the pivot value in final position
int partition = partition(unsorted, left, right, pivot);
// call itself again to sort the left half
quickSort(unsorted, left, partition - 1);
// call itself again to sort the right half
quickSort(unsorted, partition + 1, right);
}
/**
* Partitions the input array into two parts using the pivot value.
* @param array to partition
* @param left index (inclusive)
* @param right index (exclusive)
* @param pivot value (not index)
* @return index of the pivot value after inserted into final position
*/
private static int partition(int[] arr, int left, int right, int pivot) {
int leftPointer = left - 1;
int rightPointer = right;
while (true) {
// Scanning for out-of-place values
while (arr[++leftPointer] < pivot);
while (rightPointer > left && arr[--rightPointer] > pivot);
if (leftPointer >= rightPointer) {
break; // Nothing to swap
}
// Swap out-of-place values
swap(arr, leftPointer, rightPointer);
}
// Put pivot value into the final location
swap(arr, leftPointer, right);
return leftPointer;
}
/**
* Helper method to swap two elements in the input array.
* @param data input array to update
* @param one one index
* @param two the other index
*/
private static void swap(int[] data, int one, int two) {
int tmp = data[one];
data[one] = data[two];
data[two] = tmp;
}
In the worst case:
Worst case runtime: $$\frac{n(n-1)}{2}$$
7654321
765432
76543
7654
765
76
7
In Java 7: