Good
Good
• Small instance.
n <= 1 elements.
n <= 10 elements.
We’ll use n <= 1 for now.
• Large instance.
Divide into k >= 2 smaller instances.
k = 2, 3, 4, … ?
What does each smaller instance look like?
Sort smaller instances recursively.
How do you combine the sorted smaller instances?
Insertion Sort
a[0] a[n-
a[n-2] a[n-
a[n-1]
• k=2
• First n - 1 elements (a[0:n-2]) define one of the
smaller instances; last element (a[n-1]) defines
the second smaller instance.
• a[0:n-2] is sorted recursively.
• a[n-1] is a small instance.
Insertion Sort
a[0] a[n-
a[n-2] a[n-
a[n-1]
• k=2
• To divide a large instance into two smaller
instances, first find the largest element.
• The largest element defines one of the smaller
instances; the remaining n-1 elements define the
second smaller instance.
Selection Sort
a[0] a[n-
a[n-2] a[n-
a[n-1]
Bubble Sort
Merge Sort
• k=2
• First ceil(n/2) elements define one of the smaller
instances; remaining floor(n/2) elements define
the second smaller instance.
• Each of the two smaller instances is sorted
recursively.
• The sorted smaller instances are combined using
a process called merge.
• Complexity is O(n log n).
• Usually implemented nonrecursively.
Merge Sort
[8, 3] [13, 6] [2, 14] [5] [9, 10] [1] [7, 12] [4]
[8] [3] [13] [6] [2] [14] [9] [10] [7] [12]
Merge Sort
[3, 8] [6, 13] [2, 14] [5] [9, 10] [1] [7, 12] [4]
[8] [3] [13] [6] [2] [14] [9] [10] [7] [12]
Time Complexity
• Let t(n) be the time required to sort n elements.
• t(0) = t(1) = c, where c is a constant.
• When n > 1,
t(n) = t(ceil(n/2)) + t(floor(n/2)) + dn,
where d is a constant.
• To solve the recurrence, assume n is a power of 2
and use repeated substitution.
• t(n) = O(n log n).
Merge Sort
• Downward pass.
O(1) time at each node.
O(n) total time at all nodes.
• Upward pass.
O(n) time merging at each level that has a
nonleaf node.
Number of levels is O(log n).
Total time is O(n log n).
Nonrecursive Version
[8] [3] [13] [6] [2] [14] [5] [9] [10] [1] [7] [12] [4]
[3, 8] [6, 13] [2, 14] [5, 9] [1, 10] [7, 12] [4]
Quick Sort
• Small instance has n <= 1. Every small instance is a
sorted instance.
• To sort a large instance, select a pivot element from out
of the n elements.
• Partition the n elements into 3 groups left, middle and
right.
• The middle group contains only the pivot element.
• All elements in the left group are <= pivot.
• All elements in the right group are >= pivot.
• Sort left and right groups recursively.
• Answer is sorted left group, followed by middle group
followed by sorted right group.
Example
6 2 8 5 11 10 4 1 9 7 3
2 5 4 1 3 6 7 9 10 11 8
Choice Of Pivot
Choice Of Pivot
• Median-of-Three rule. From the leftmost, middle,
and rightmost elements of the list to be sorted,
select the one with median key as the pivot.
When sorting a[6:20], examine a[6], a[13] ((6+20)/2),
and a[20]. Select the element with median (i.e., middle)
key.
If a[6].key = 30, a[13].key = 2, and a[20].key = 10,
a[20] becomes the pivot.
If a[6].key = 3, a[13].key = 2, and a[20].key = 10, a[6]
becomes the pivot.
Choice Of Pivot
pivot
b 2 5 4 1 3 6 7 9 10 11 8
a 6 2 3 5 11 10 4 1 9 7 8
a 6 2 3 5 1 10 4 11 9 7 8
a 6 2 3 5 1 4 10
10 11 9 7 8
Complexity
• O(n) time to partition an array of n elements.
• Let t(n) be the time needed to sort n elements.
• t(0) = t(1) = c, where c is a constant.
• When t > 1,
t(n) = t(|left|) + t(|right|) + dn,
where d is a constant.
• t(n) is maximum when either |left| = 0 or |right| =
0 following each partitioning.
Complexity
• This happens, for example, when the pivot is
always the smallest element.
• For the worst-case time,
t(n) = t(n-1) + dn, n > 1
• Use repeated substitution to get t(n) = O(n2).
• The best case arises when |left| and |right| are
equal (or differ by 1) following each partitioning.
• For the best case, the recurrence is the same as
for merge sort.
java.util.arrays.sort