FASTER SORTING using RECURSION : QUICKSORT COMP 103.
-
Upload
rebecca-lynch -
Category
Documents
-
view
217 -
download
0
Transcript of FASTER SORTING using RECURSION : QUICKSORT COMP 103.
FASTER SORTING using RECURSION :
QUICKSORT
CO
MP 1
03
2
RECAP-TODAYTODAY MergeSort analysis (How do you analyse recursive algorithms?)
QuickSort
The Mid-term Test on Monday 30th of April at 11am (during normal lecture slot) THE ROOMS ARE ANNOUNCED ON THE WEB SITE!!!
please bring Student ID card, sit in alternate rows & alternate seats
practice on previous tests (via “previous tests & exams” on sidebar)
any material up to this point (end of today) could be tested
GOOD LUCK!
3
Divide and Conquer SortsTo Sort:
Split Sort each part
(recursive) Combine
Where does thework happen?
MergeSort: split is trivial combine does all the work
QuickSort: split does all the work combine is trivial
Array
Sorted Array
Split
Combine
SubArray SubArray
SortedSubArray SortedSubArray
Sort Sort
Split
Combine
SubArray SubArray
Sort Sort
SortedSubArraySortedSubArray
Split
Combine
SubArray SubArray
Sort Sort
SortedSubArraySortedSubArray
4
QuickSort uses Divide and Conquer, but does its work in the
“split” step
split the array into parts, by choosing a “pivot” item, and making sure that:
all items < pivot are in the left part all items > pivot are in the right part
Then (recursively) sort each part
Here's how we start it off:
public static <E> void quickSort( E[] data, int size, Comparator<E> comp) { quickSort (data, 0, size, comp);
}
“wrapper” version starts it off
recursive version carries it on (and on...)
note: it won’t usually be an
equal split
5
QuickSort – the recursion
public static <E> void quickSort(E[ ] data, int low, int high, Comparator<E> comp){
if (high-low < 2) // only one item to sort.
return;if (high - low < 4) // only two or three items to sort.
sort3(data, low, high, comp);else { // split into two parts, mid = index of boundary
int mid = partition(data, low, high, comp);
quickSort(data, low, mid, comp);
quickSort(data, mid, high, comp);}
}
6 7 8 9 10 110 1 2 3 4 5
6
QuickSort: Partition Choose a pivot:
6 7 8 9 10 110 1 2 3 4 5
pivot
6 7 8 9 10 110 1 2 3 4 5pivot
Use it to partition the array:
low highleft(gets returned)
not yet sorted not yet sorted
7
QuickSort: Partition/** Partition into small items (low..mid-1) and large
items (mid..high-1)private static <E> int partition(E[] data, int low, int high,
Comparator<E> comp){
E pivot =int left = low-1;int right = high;
while( left <= right ){do { left++; // just skip over items on the left < pivot} while (left<high &&comp.compare(data[left], pivot)< 0);do { right--; // just skip over items on the right > pivot} while (right>=low && comp.compare(data[right], pivot)> 0);if (left < right) swap(data, left, right);
}return left;
}
6 7 8 9 10 110 1 2 3 4 5
data[low]; // simple but poor choice!median(data[low], data[high-1], data[(low+high)/2], comp);
8
QuickSortdata array : [p a1 r f e q2 w q1 t z2 x c v b z1 a2 ] indexes : [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ]
do 0..16 : [p a1 r f e q2 w q1 t z2 x c v b z1 a2 ]part@p ->6 : [a2 a1 b f e c w q1 t z2 x q2 v r z1 p ]do 0..6 : [a2 a1 b f e c ]part@c ->4 : [a2 a1 b c e f ]do 0..4 : [a2 a1 b c ]part@b ->3 : [a2 a1 b c ]do 0..3 : [a2 a1 b ]done 0..3 : [a2 a1 b ]do 3..4 : [ c ]done 0..4 : [a2 a1 b c ]do 4..6 : [ e f ]done 4..6 : [ e f ]done 0..6 : [a2 a1 b c e f ]do 6..16 : [ w q1 t z2 x q2 v r z1 p ]part@q2->8 : [ p q2 t z2 x q1 v r z1 w ]do 6..8 : [ p q2 ]done 6..8 : [ p q2 ]
9
Quick Sortdo 6..16 : [ w q1 t z2 x q2 v r z1 p ]part@q2->8 : [ p q2 t z2 x q1 v r z1 w ]do 6..8 : [ p q2 ]done 6..8 : [ p q2 ]do 8..16 : [ t z2 x q1 v r z1 w ]part@v ->12: [ t r v q1 x z2 z1 w ]do 8..12 : [ t r v q1 ]part@t ->10: [ q1 r v t ]do 8..10 : [ q1 r ]done 8..10 : [ q1 r ]do 10..12: [ v t ]done 10..12: [ t v ]done 8..12 : [ q1 r t v ]do 12..16: [ x z2 z1 w ]part@x ->13: [ w z2 z1 x ]do 12..13: [ w ]do 13..16: [ z2 z1 x ]done 13..16: [ x z2 z1 ]done 12..16: [ w x z2 z1 ]done 8..16 : [ q1 r t v w x z2 z1 ]done 6..16 : [ p q2 q1 r t v w x z2 z1 ]done 0..16 : [a2 a1 b c e f p q2 q1 r t v w x z2 z1 ]
10
QuickSortpublic static <E> void quickSort (E[ ] data, int low, int high,
Comparator<E> comp) { if (high > low +2) { int mid = partition(data, low, high, comp); quickSort(data, low, mid, comp); quickSort(data, mid, high, comp); }
}
Cost of Quick Sort: three steps:
partition: has to compare (high-low) pairs first recursive call second recursive call
11
QuickSort Cost: If Quicksort divides the array exactly in half, then:
C(n) = n + 2 C(n/2) n log(n) comparisons
= O(n log(n)) (best case)
If Quicksort divides the array into 1 and n-1: C(n) = n + (n-1) + (n-2) + (n-3) + … + 2 + 1 = n(n-1)/2 comparisons
= O(n2) (worst case)
Average case? very hard to analyse. still O(n log(n)), and very good.
Quicksort is “in place”, MergeSort is not
12
Stable or Unstable? Faster if almost-sorted?
MergeSort: Stable: doesn’t jump any item over an unsorted region
⇒ two equal items preserve their order
Same cost on all input “natural merge” variant doesn’t sort already sorted
regions⇒ will be very fast: O(n) on almost sorted lists
QuickSort: Unstable: Partition “jumps” items to the other end
⇒ two equal items likely to reverse their order
Cost depends on choice of pivot. simplest choice is very slow: O(n2) even on almost sorted
lists better choice (median of three) ⇒ O(n log(n)) on almost
sorted lists
13
Some Big-O costs revisitedImplementing Collections:
ArrayList: O(n) to add/remove, except at end
Stack: O(1)
ArraySet: O(n) (cost of searching)
SortedArraySet O( log(n) ) to search (with binary
search)
O(n) to add/remove (cost of moving
up/down)
O( n2 ) to add n itemsO( n log(n) ) to initialise with n items. (with fast sorting)
14
Quick Review of Topics (for Test)
Using Collections (List, Set, Map, Bag, Stack, Queue….) Interfaces, AbstractsClasses, Classes (extends and
implements) Iterator, Iterable, Comparator, Comparable
Implementing Collections (ArrayList, SortedArrayBag, ArraySet…)
Recursion
Sorting (Selection, Insertion, MergeSort, QuickSort….)
Cost analysis (“Big-O” notation and calculation…