3.3. Divide & Conquer Sort
Merge sort, quick sort, intro sort
Divide & Conquer
Divide the problem into sub-problems (recursively).
Conquer sub-problems, which effectively solve the super problem.
Complexity
MergeSort
TimSort
QuickSort
IntroSort
Best
Worst
Average
Why do people ever want to use QuickSort?
Merge Sort
Divide the input array into two sub-arrays.
Sort each of the sub-arrays and merge them into the back.
Let us create the MergeSort class inheriting AbstractSort:
public class MergeSort<T extends Comparable<T>> extends AbstractSort<T> {
private T[] temp;
public MergeSort() {
this(Comparator.naturalOrder());
}
public MergeSort(Comparator<T> comparator) {
super(comparator);
}
}L2: holds the copy of the input array.
Let us then override the sort() method that calls the helper method:
L4-5: increases the size of thetemparray if necessary.L5: unchecked typeObjecttoT[].
What is the advantage of declaring the member field
temp?
The helper method can be defined as follows:
L11: sorts the left sub-array.L12: sorts the right sub-array.L13: merges the left and right sub-arrays.
Finally, the merge() method can be defined as follows:
L10-11: copies the input array to the temporary array and counts the assignments.L14-15: no key left in the 1st half.L16-17: no key left in the 2nd half.L18-19: the 2nd key is greater than the 1st key.L20-21: the 1st key is greater than or equal to the 2nd key.
How many assignments are made for the number of keys by the above version of MergeSort?
Quick Sort
Pick a pivot key in the input array.
Exchange keys between the left and right partitions such that all keys in the left and right partitions are smaller or bigger than the pivot key, respectively.
Repeat this procedure in each partition, recursively.
Let us create the QuickSort class inheriting AbstractSort:
Let us then override the sort() method:
L3: stops when the pointers are crossed.L6: sorts the left partition.L7: sorts the right partition.
The partition() method can be defined as follows:
L5: finds the left pointer whereendIndex>fst>pivot.L6: finds the right pointer wherebeginIndex<snd<pivot.L7: the left and right pointers are crossed.L8: swaps between keys in the left and right partitions.L11: swaps the keys in thebeginIndexandpivot.
Intro Sort
Although Quick Sort is the fastest on average, the worst-case complexity is .
sorting algorithms that guarantee faster worst-case complexities than Quick Sort: Quick Sort for random cases and a different algorithm for the worst case.
How can we determine if Quick Sort is meeting the worse-case?
Let us define the IntroSoft class inheriting QuickSort:
L2: declares a sorting algorithm to handle the worst cases.L14: resets the counters for both the main and auxiliary sorting algorithms.
We then override the sort() method by passing the maximum depth to the auxiliary method:
L9: returns as the maximum depth.
Finally, the auxiliary method sort() can be defined as follows:
L4-5: switches to the other sorting algorithm if the depth of the partitioning exceeds the max depth.
Does the max-depth need to be set to ?
Benchmarks
The following shows runtime speeds, assignment costs, and comparison costs between several sorting algorithms for the random, best, and worst cases.
Last updated
Was this helpful?