Presentation is loading. Please wait.

Presentation is loading. Please wait.

Recursive Quicksort Data Structures in Java with JUnit ©Rick Mercer.

Similar presentations


Presentation on theme: "Recursive Quicksort Data Structures in Java with JUnit ©Rick Mercer."— Presentation transcript:

1 Recursive Quicksort Data Structures in Java with JUnit ©Rick Mercer

2 Quicksort: O(n log n) Sorting  Quicksort was discovered by Tony Hoare 1962  Here is an outline of his famous algorithm:  Pick one item from the array--call it the pivot  Partition the items in the array around the pivot so all elements to the left are  to the pivot and all elements to the right are greater than the pivot  Use recursion to sort the two partitions a snapshot pivot partition: items > pivot partition 1: items  pivot

3 Before and After  Let's sort integers  Pick the leftmost one (27) as the pivot value  The array before call to partition(a, 0, n-1)  Array looks like this after first partition is done 27 14 9 22 8 41 56 31 14 53 99 11 2 24 24 14 9 22 8 14 11 2 27 53 99 56 31 41 pivotitems < pivotitems > pivot

4 The partition method  p artition divvies up a around the split and returns the position of the split, an integer in the range of 0..n-1  The postcondition of partition: a[first]..a[split-1] <= a[split] && a[split+1]..a[last] > a[split]  Notes:  May be more than 1 element equal to the pivot  Put them in left partition could have been the right

5 Recursive call to sort smaller part of the array quickSort(a, split+1, last); // sort right  QuickSort the right. At some point  Pivot will be 53  Assume left portion is already sorted 24 14 9 22 8 14 11 2 27 53 99 56 31 41 2 8 9 11 14 14 22 24 27 31 41 53 99 56 pivot items < pivotitems > pivot left is already sorted, begin to sort part to the right of split

6 Complete the sort // sort left and right around new split // sort left and right around new split quickSort(a, first, split-1); quickSort(a, first, split-1); // sort right // sort right quickSort(a, split+1, last); quickSort(a, split+1, last); 2 8 9 11 14 14 22 24 27 31 41 53 99 56 2 8 9 11 14 14 22 24 27 31 41 53 56 99 Entire array is now sorted

7 Start Over (i ==1) Start Over (i ==1)  Now let's back up and start with empty partitions int partition(int a[], int first, int last) { int lastSmall = first; int lastSmall = first; int i = (first + 1); // Beginning of unknowns int i = (first + 1); // Beginning of unknowns  Compare all items from a[i]..a[last]  if a[i] > a[first] (the pivot), do nothing  if a[i] <= a[first], swap a[lastSmall+1] with a[i] 27 41 14 56 31 9 22 8 14 53 99 11 2 24 first lastSmall i unknown items (all are unknown--except first)

8 Result of the 1st loop iteration(i==2) 27 41 14 56 31 9 22 8 14 53 99 11 2 24 first lastSmall i unknown items partition 1: all items pivot  The following array shows no changes were made in the array since a[i] <= a[first] was false  So simply add 1 to i (i++)--create 2 partitions  Now partition 1 has one element (the pivot 27) and partition 2 has 1 element (41)

9 Result of the 2nd loop iteration(i==3) 27 14 41 56 31 9 22 8 14 53 99 11 2 24 first lastSmall i unknown items partition 1: all items pivot  The following array shows a swap was made in the array since a[i] <= a[first] was true (14 < 27)  a[i] (14) is swapped with a[lastSmall+1] (41)  lastSmall gets incremented to point to the last element in partition 1  i gets incremented to reference 56

10 Result of the 3rd loop iteration(i==4) 27 14 41 56 31 9 22 8 14 53 99 11 2 24 first lastSmall i unknown items partition 1: all items pivot  The following array shows no swap was made in the array since a[i] <= a[first] was false  lastSmall does NOT get incremented  i gets incremented to reference 31

11 Result of the 4th loop iteration(i==5) 27 14 41 56 31 9 22 8 14 53 99 11 2 24 first lastSmall i unknown items partition 1: all items pivot  The following array shows no swap was made in the array since a[i] <= a[first] was false  lastSmall does NOT get incremented  i gets incremented to reference 9

12 Result of the 5th loop iteration(i==6) 27 14 9 56 31 41 22 8 14 53 99 11 2 24 first lastSmall i unknown items partition 1: all items pivot  The following array shows a swap was made in the array since a[i] <= a[first] was true (9 < 27)  a[i] (9) is swapped with a[lastSmall+1] (41)  lastSmall gets incremented to point to the last element in partition 1  i++ points to the first unknown (22)

13 27 14 9 22 56 31 41 8 14 53 99 11 2 24 first lastSmall i unknown items partition 1: all items pivot i == 7

14 27 14 9 22 8 56 31 41 14 53 99 11 2 24 first lastSmall i unknown partition 1: all items pivot i == 8

15 27 14 9 22 8 14 56 31 41 53 99 11 2 24 first lastSmall i unknown partition 1: all items pivot i == 9

16 27 14 9 22 8 14 56 31 41 53 99 11 2 24 first lastSmall i unknown partition 1: all items pivot i == 10

17 27 14 9 22 8 14 56 31 41 53 99 11 2 24 first lastSmall i unknown partition 1: all items pivot i == 11

18 27 14 9 22 8 14 11 56 31 41 53 99 2 24 first lastSmall i unknown partition 1: all items pivot i == 12

19 27 14 9 22 8 14 11 2 56 31 41 53 99 24 first lastSmall i unknown partition 1: all items pivot i == 13

20 Result of the 14th loop iteration(i==14) 27 14 9 22 8 14 11 2 24 53 99 56 31 41 first lastSmall i partition 1: all items pivot  The following array shows what happens after traversing the entire array with this loop (i>last): for (i = first + 1; i <= last; i++) { if(a[i] <= a[first] ) { if(a[i] <= a[first] ) { lastSmall++; lastSmall++; swapElements(a, lastSmall, i); swapElements(a, lastSmall, i); } }

21 Post Loop Detail  Now place the pivot into where we expect the pivot to be: in-between the two partitions swapElements( a, first, lastSmall ); swapElements( a, first, lastSmall );  Then we can return lastSmall for the next call return lastSmall; return lastSmall; 24 14 9 22 8 14 11 2 27 53 99 56 31 41 first lastSmall (pivot position) partition 1: all items pivot

22 quickSort is called like this: quickSort(a, 0, n-1) void quickSort(int a[], int first, int last) { void quickSort(int a[], int first, int last) { // precondition: a is an array to be sorted from // precondition: a is an array to be sorted from // a[first]..a[last] // a[first]..a[last] if(first >= last) if(first >= last) return; // Done: we have an empty array return; // Done: we have an empty array // The difficult algorithm is in partition // The difficult algorithm is in partition int split = partition ( a, first, last ); int split = partition ( a, first, last ); // Recursively Quicksort left, then right // Recursively Quicksort left, then right quickSort(a, first, split-1); // sort left quickSort(a, first, split-1); // sort left quickSort(a, split+1, last); // sort right quickSort(a, split+1, last); // sort right // post: the array a is sorted // post: the array a is sorted }

23 Analyzing Quicksort  The critical statement happens in the comparison of the for loop of the partition function if(a[i] <= a[first]) if(a[i] <= a[first])  So how many times is partition called?  And what are the values for first and last (# comparisons)?  If the pivot element is near the mode, we don't have many calls to QuickSort, it is O(log n)

24 The best of Quicksort, the worst of Quicksort  In the best case (1st element is always middle value) with 7 elements, call partition 3 times first == 0, last == 6 // 6 comparisons first == 0, last == 6 // 6 comparisons first == 0, last == 2 // 2 comparisons first == 0, last == 2 // 2 comparisons first == 4, last == 6 // 2 comparisons first == 4, last == 6 // 2 comparisons  In the worst case, (sorted array), with 7 elements, partition is called first == 0, last == 6 // 6 comparisons first == 0, last == 6 // 6 comparisons first == 1, last == 6 // 5 comparisons first == 1, last == 6 // 5 comparisons first == 2, last == 6 // 4 comparisons first == 2, last == 6 // 4 comparisons first == 3, last == 6 // 3 comparisons first == 3, last == 6 // 3 comparisons first == 4, last == 6 // 2 comparisons first == 4, last == 6 // 2 comparisons first == 5, last == 6 // 1 comparison first == 5, last == 6 // 1 comparison

25 Best Case: [ 4, 1, 3, 2, 6, 5, 7 ] [ 4, 1, 3, 2, 6, 5, 7 ] [ 2, 1, 3, 4, 6, 5, 7 ] [ 2, 1, 3, 4, 6, 5, 7 ] [ 2, 1, 3] [ 6, 5, 7 ] [ 2, 1, 3] [ 6, 5, 7 ] [ 1, 2, 3] [ 5, 6, 7 ] [ 1, 2, 3] [ 5, 6, 7 ] [1] [3] [5] [7] [1] [3] [5] [7]

26 Worst Case [ 1, 2, 3, 4, 5, 6, 7] [] [2, 3, 4, 5, 6, 7] [] [2, 3, 4, 5, 6, 7] [] [3, 4, 5, 6, 7] [] [3, 4, 5, 6, 7] [] [4, 5, 6, 7] [] [4, 5, 6, 7] [] [5, 6, 7] [] [5, 6, 7] [] [6, 7] [] [6, 7] [] [7] [] [7] [] [] [] []

27 The Best and Worst continued  So in the worst case, partition is called n-1 times: (n-1)+(n-2)+... + 1 comparisons = O(n 2 )  The worst case of Quicksort may be the same as Selection Sort, which is O(n 2 )  Quicksort is used because of its best and average cases


Download ppt "Recursive Quicksort Data Structures in Java with JUnit ©Rick Mercer."

Similar presentations


Ads by Google