FASTER SORTING using RECURSION : QUICKSORT COMP 103.

14
FASTER SORTING using RECURSION : QUICKSORT COMP 103

Transcript of FASTER SORTING using RECURSION : QUICKSORT COMP 103.

Page 1: FASTER SORTING using RECURSION : QUICKSORT COMP 103.

FASTER SORTING using RECURSION :

QUICKSORT

CO

MP 1

03

Page 2: FASTER SORTING using RECURSION : QUICKSORT COMP 103.

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!

Page 3: FASTER SORTING using RECURSION : QUICKSORT COMP 103.

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

Page 4: FASTER SORTING using RECURSION : QUICKSORT COMP 103.

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

Page 5: FASTER SORTING using RECURSION : QUICKSORT COMP 103.

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

Page 6: FASTER SORTING using RECURSION : QUICKSORT COMP 103.

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

Page 7: FASTER SORTING using RECURSION : QUICKSORT COMP 103.

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);

Page 8: FASTER SORTING using RECURSION : QUICKSORT COMP 103.

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 ]

Page 9: FASTER SORTING using RECURSION : QUICKSORT COMP 103.

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 ]

Page 10: FASTER SORTING using RECURSION : QUICKSORT COMP 103.

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

Page 11: FASTER SORTING using RECURSION : QUICKSORT COMP 103.

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

Page 12: FASTER SORTING using RECURSION : QUICKSORT COMP 103.

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

Page 13: FASTER SORTING using RECURSION : QUICKSORT COMP 103.

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)

Page 14: FASTER SORTING using RECURSION : QUICKSORT COMP 103.

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…