Presentation is loading. Please wait.

Presentation is loading. Please wait.

21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 1 Class 15 - Recursive sorting methods r Processing arrays by recursion r Divide-and-conquer.

Similar presentations


Presentation on theme: "21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 1 Class 15 - Recursive sorting methods r Processing arrays by recursion r Divide-and-conquer."— Presentation transcript:

1 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 1 Class 15 - Recursive sorting methods r Processing arrays by recursion r Divide-and-conquer algorithm r Quicksort

2 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 2 Processing arrays by recursion r Follow usual principle: to define f(A), assume f(B) can be calculated for any array B smaller than A. r But, instead of actually passing in a smaller array, pass A together with arguments indicating which part of A to process. r Examples: void f (double[] A, int i, int j) { // process A[i]... A[j]... recursive call f(A, i+1, j)... }

3 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 3 Processing arrays by recursion (cont.) void f (double[] A, int i, int j) { // process A[i]... A[j]... recursive call f(A, i, j-1)... } void f (double[] A, int i) { // process A[i]... A[A.length-1]... recursive call f(A, i+1)... } void f (double[] A, int i) { // process A[0]... A[i]... recursive call f(A, i-1)... }

4 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 4 Processing arrays by recursion (cont.) r Base cases void f (double[] A, int i, int j) { // i = j - 1-element subarray // i > j - 0-element subarray void f (double[] A, int i) { // process A[i]... A[A.length-1] // i = A.length-1 - 1-element // i = A.length - 0-element

5 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 5 Divide-and-conquer methods r Greater efficiency sometimes obtained by dividing array in half, operating on each half recursively. void f (double[] A, int i, int j) { // process subarray A[i]... A[j]... process A[i]...A[j] in linear time... f(A, i, (i+j)/2); f(A, (i+j)/2+1, j);... process A[i]...A[j] in linear time... }

6 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 6 Divide-and-conquer methods pre- and post-processing: time cn time c(n/2) c(n/4) c(n/4)...... Total time cn cn * # of levels

7 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 7 Divide-and-conquer methods for sorting r Consider subarrays of the form A[i]...A[j]. Assuming can sort arbitrary subarrays - in particular, A[i]...A[(i+j)/2] and A[(i+j)/2+1]... A[j] - how can we define divide-and- conquer sorting method? r Two “obvious” methods:

8 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 8 Divide-and-conquer methods for sorting (cont.) ¬ “Post-process”: To sort A[i]...A[j]: m Sort A[i]...A[(i+j)/2] m Sort A[(i+j)/2+1]... A[j] m “Merge” sorted halves 179225416812 591722416812 591722481216 458912161722 sort merge

9 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 9 Divide-and-conquer methods for sorting (cont.) ­ “Pre-process”: To sort A[i]...A[j]: m Move smaller elements into left half and larger elements into right half (“partition”) m Sort A[i]... A[(i+j)/2] m Sort A[(i+j)/2+1]... A[j] 179225416812 498517162212 458917162212 4589 161722 partition sort

10 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 10 Divide-and-conquer methods for sorting (cont.) r Method 1 called merge sort m But need to write merge step r Method 2 called quicksort m But need to write partition step

11 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 11 Quicksort “Pre-process”: To sort A[i]...A[j]: m Move smaller elements into left half and larger elements into right half (“partition”) m Sort A[i]... A[(i+j)/2] m Sort A[(i+j)/2+1]... A[j] 179225416812 498517162212 458917162212 4589 161722 partition sort

12 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 12 Quicksort (cont.) void quickSort (double[] A, int i, int j) { // sort A[i]...A[j] if ( base case )... handle base case...; else { partition(A, i, j); int midpt = (i+j)/2; quickSort(A, i, midpt); quickSort(A, midpt+1, j); } (N.B. this is the right idea, but it doesn’t work in this form. We’ll fix it in a little while.)

13 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 13 Quicksort (cont.) r Only question is how to partition. r Can divide problem into two subproblems: m locating the “median” element in A[i..j], say it is A[m]. (This value is called the pivot.) m moving smaller elements than A[m] to left, larger elements to right. void partition (double[] A, int i, int j) { int pivotLoc = locOfMedian(A, i, j); swap(A,i,pivotLoc); partition1(A, i+1, j, A[i]); }

14 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 14 partition1, first version  partition1(double[] A, int i, int j, double pivot) - shuffle elements of A[i..j] so that all elements less than pivot appear to the left of all elements greater than pivot. r If pivot is the median of the elements of A[i..j], then this will split the subarray exactly in half, so that the “middle” will be (i+j)/2.

15 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 15 partition1, first version r Idea is simple: Suppose can partition A[i+1..j] or A[i..j-1] recursively. Two cases: m A[i] < x: Partition A[i+1..j]. m A[i] > x: Swap A[i] and A[j], then partition A[i..j-1] recursively.

16 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 16 partition1, first version void partition1 (double[] A, int i, int j, double pivot) { // Shuffle elements of A[i..j] so that elements // pivot if (A[i]<pivot) … … write this! }

17 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 17 Finding the median r Next problem: find median of A[i..j]. r Can easily do it in quadratic time, but how can it be done in linear time?

18 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 18 Guessing the median r Unfortunately, it can’t. Second best solution: guess the median and partition around the guess, hoping for the best. r Major point: Since we can’t be sure our guess will be correct, we don’t know where the “middle” will end up. Therefore, partition1 needs to return an integer giving the location of the dividing line between small and large values.

19 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 19 Quicksort again r Without the ability to divide the array exactly in half, need to change structure of quicksort somewhat: void quickSort (double[] A, int i, int j) { int m; if (i < j) { m = partition(A, i, j); quickSort(A, i, m-1); quickSort(A, m+1, j); }

20 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 20 Quicksort again (cont.) r Difference is that partition has to tell quicksort where it ended up splitting the array: int partition (double[] A, int i, int j) { // Guess median of A[i]... A[j], // and move other elements so that // A[i]... A[m-1] are all less than A[m] and // A[m+1]... A[j] are all greater than A[m] // m is returned to the caller swap(A, i, guessMedianLocation(A, i, j)); int m = partition1(A, i+1, j, A[i]); swap(A, i, m); return m; }

21 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 21 partition1 int partition1 (double[] A, int i, int j, double pivot) { // Shuffle elements of A[i..j] so that elements // pivot if ( base case )... if (A[i] <= pivot) // A[i] in correct half return partition1(A, i+1, j, pivot); else if (A[j] > pivot) // A[j] in correct half return partition1(A, i, j-1, pivot); else { // A[i] and A[j] in wrong half swap(A, i, j); return partition1(A, i, j-1, pivot); } r partition1 must return the “middle”.

22 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 22 partition1 (cont.) r Need to handle base cases. However, there is one key point to remember here: the index returned by partition1 must contain a value less than the pivot, because it will be swapped back into A[i]. Base case needs to guarantee this: // Base case for partition1: if (j == i) if (A[i] < pivot) return i; else return i-1;

23 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 23 Guessing the median r Making a good guess concerning the median is very important. r Here is a simple approach: int guessMedianLocation (double[] A, int i, int j) { return (i+j)/2; }

24 21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 24 Final words on quicksort r Quicksort runs in time n log n, but only if the partitions are (roughly) in half. r Worst case performance for quicksort is quadratic, but it is difficult to find examples where it is inefficient.


Download ppt "21/3/00SEM107- Kamin & ReddyClass 15 - Recursive Sorting - 1 Class 15 - Recursive sorting methods r Processing arrays by recursion r Divide-and-conquer."

Similar presentations


Ads by Google