introduction to computer science recursive array programming recursive sorting algorithms unit 16

49
Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

Post on 22-Dec-2015

252 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

Introduction to Computer Science

• Recursive Array Programming

• Recursive Sorting Algorithms

Unit 16Unit 16

Page 2: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 2

Recursive Array Programming

Recursive function definitions assume that a function works for a smaller value.

With arrays, "a smaller value" means a shorter array, i.e., a subarray, contiguous elements from the original array

We'll define a recursive function over an array by using the same function over a subarray, and a base case

Subscripts will mark the lower and upper bounds of the subarrays

Page 3: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 3

Subarrays

myArray

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

Base case

1 through 92 through 9

3 through 94 through 9

5 through 9

6 through 9

7 through 98 through 9

9 through 9

Page 4: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 4

Example: Recursively find sum of array elements, A[lo] to A[hi]

• Assume sum( ) properly returns sum of elements for a smaller array of doubles

• Then we could write:

double sum (double[ ] A, int lo, int hi) {return ( A[lo] + sum(A, lo + 1, hi) );

}

• But we're not done; what's the base case?

Page 5: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 5

Base Case is when Subarray is Empty, hi is less than lo

double sum (double[ ] A, int lo, int hi) {if (hi < lo)

return 0.0;else

return ( A[lo] + sum(A, lo + 1, hi) );}

• Yes, we could have defined this using(hi == lo) as the base case…

Page 6: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 6

Recursive Sorting Algorithms

• We can use this same idea of recursive functions over subarrays to rewrite our sorting algorithms

• Let's see how this works for selection sort, insertion sort, and then some new sorting algorithms

Page 7: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 7

Selection Sort (REVIEW)

18 2235 97 84 55 61 10 47

starting order:

18223597 84 55 61 10 47

search through array, find largest value, exchange withfirst array value:

1822 3597 84 55 61 10 47

search through rest of array, find second-largest value,exchange with second array value:

Page 8: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 8

Selection Sort Pseudocode (REVIEW)

for every “first” component in the arrayfind the largest component in the array;exchange it with the “first” component

18 223597 84 5561 10 47

18 223597 84 5561 10 47

18 22 3597 84 5561 1047

18223597 84 5561 1047

18223597 84 5561 1047

18223597 84 5561 1047

Page 9: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 9

The Selection Sort Java Code (REVIEW)

void select (int[ ] data) { // Uses selection sort to order an array of integers. int first, current, largest, temp;

for (first = 0; first < data.length - 1; first++) {largest = first;for (current = first + 1; current < data.length; current+

+) { if ( data[current] > data[largest] ) largest =

current;}// Postcondition: largest is index of largest item

// from first..end of arrayif (largest != first) { // We have to make a swap

temp = data[largest];data[largest] = data[first]; // Make the swapdata[first] = temp;

}}

} // select

Page 10: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 10

Recursive Selection Sort

• Let's say we want to sort an array A from index "lo" to index "hi", largest to smallest

• We place the largest element in A[lo]

• Then recursively sort the rest of the array from A[lo + 1] to A[hi]

• The base case is the one-element subarray when lo equals hi

Page 11: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 11

The Recursive Selection Sort Java Code

void selectionSort(int[ ] data, int lo, int hi) {// data[0]…data[lo-1] contain the largest values in data, // in descending order

if (lo < hi) { //subarray has more than one elementswap(data, lo, findMaximum(data, lo, hi));selectionSort(data, lo+1, hi);

}}

int findMaximum(int[ ] data, int lo, int hi) {if (lo == hi) return lo;else { int locationOfMax = findMaximum(data, lo+1, hi); if (data[lo] > data[locationOfMax]) return lo; else return locationOfMax;}

}

Page 12: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 12

Code for swap( )

• The above version of selectionSort( ) is much less efficient than the iterative version; we show it just as an example of recursive array programming

void swap(int[ ] data, int first, int second) { int temp;

temp = data[first];data[first] = data[second];data[second] = temp;

}

Page 13: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 13

What Does the Outside World See?

• We can use overloading, and provide a one-argument version of selectionSort( ) for outside use. No one needs to know whether it was implemented using recursion or iteration:

void selectionSort(int[ ] data) {selectionSort(data, 0, data.length - 1);

}

• The internal version should be private

Page 14: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 14

Insertion Sort

18 2235 97 84 55 61 10 47

starting order:

18 2235 97 84 55 61 10 47

move through the array, keeping the left side ordered;when we find the 35, we have to slide the 18 over to make room:

182235 97 84 55 61 10 47

continue moving through the array, always keeping the leftside ordered, and sliding values over as necessary to do so:

18 slid over

18 slid over

Page 15: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 15

Continue the Insertion Process

18223597 84 55 61 10 47

the left side of the array is always sorted, but may requireone or more components to be slid over to make room:

35, 22, and 18 slid over

18223597 84 55 61 10 4735, 22, and 18 slid over

18223597 84 55 61 10 4735, 22, and 18 slid over

Page 16: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 16

Continue the Insertion Process

18223597 84 5561 10 4755, 35, 22, and 18 slid over

18223597 84 5561 10 47nothing slides over

18223597 84 5561 104735, 22, 18, and 10 slid over

Page 17: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 17

The Insertion Sort Java Code(Review)

void insert (int[ ] data) { // Uses insertion sort to order an array of integers.int newest, current, newItem;boolean seeking;for (newest = 1; newest < data.length; newest++) {

seeking = true;current = newest;newItem = data[newest];while (seeking) { // seeking newItem's new position on left if (data[current - 1] < newItem) {

data[current] = data[current -1]; //slide value rightcurrent- -; seeking = (current > 0);

} else seeking = false;} // while// Postcondition: newItem belongs in data[current]data[current] = newItem;

} // newest for} // insert

Page 18: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 18

How Do We Do Insertion Sort Recursively?

• How can the ability to sort an array of length n-1 be used to sort an array of length n?

• Answer: sort the array of length n-1, then insert the nth element in the proper place

• That is: to sort subarray A[0]…A[hi], sort A[0]…A[hi-1], then insert A[hi] into that smaller subarray

• insertInOrder(A, hi, x) will be used to insert x into subarray A[0]…A[hi-1]

Page 19: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 19

Recursive Insertion Sort

void insertionSort(int[ ] data, int hi) {

// Sort data[0]…data[hi]

if (hi > 0) {

insertionSort(data, hi-1);

insertInOrder(data, hi, data[hi]);

}

}

Page 20: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 20

What About insertInOrder( )?

• We'll define it recursively

• To insert x into subarray A[0]…A[hi-1]:

– If x ≤A[hi-1], then put x into A[hi]

– If x > A[hi-1], then move A[hi-1] into A[hi]

and insert x into subarray A[0]…A[hi-2]

Page 21: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 21

Recursive insertInOrder( )

void insertInOrder(int[ ] data, int hi, int x) { // Insert x into data[0]…data[hi-1], filling // in data[hi] in the process.

// data[0]…data[hi-1] are sorted.if ( (hi == 0) || (data[hi-1] >= x) )

data[hi] = x;else {

data[hi] = data[hi-1];insertInOrder(data, hi-1, x);

}}

Page 22: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 22

What Does the Outside World See (again)?

• We can use overloading, and provide a one-argument version of insertionSort( ) for outside use. No one needs to know whether it was implemented using recursion or iteration:

public void insertionSort(int[ ] data) {insertionSort(data, data.length - 1);

}

• The internal version should be private

Page 23: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 23

More Recursive Sorting: Quicksort

• Quicksort is an O(n2) algorithm in the worst case, but its running time is usually proportional to n log2 (n); it is the method of choice for many sorting jobs

• We’ll first look at the intuition behind the algorithm: take an array

V O N I C AE Rarrange it so the small values are on the left half and all the big values are on the right half:

V O NI C AE R

Page 24: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 24

Quicksort Intuition

• Then, do it again:

VO NIC A E Rand again:

VO NICA E RThe divide-and-conquer strategy will, in general, take log2n steps to move the A into position. The intuition is that, doing this for n elements, the whole algorithm will take O(n log2 n) steps.

Page 25: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 25

What Quicksort is really doing

1. Partition array a into smaller elements and larger ones – smaller ones from a[0]…a[m-1] (not necessarily in order), larger ones in positions a[m+1]…a[length-1] (not necessarily in order), and the “middle” element in a[m]. So a:

5 3 11 7 1927 12 18might be partitioned (with m=4) as:

5 3 117 192712 18pivotsmaller than pivot larger than pivot

Page 26: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 26

quicksort(), next 2 steps

2. Recursively sort a[0]…a[m-1]. Our a becomes:

53 117 192712 18

3. Recursively sort a[m+1]…a[length-1]. Our a becomes:

53 117 19 271218

pivot

pivot

Page 27: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 27

quicksort( )

private void quicksort(double[] a, int lo, int hi) {int m;

if (hi > lo+1) { // there are at least 3 elements// so sort recursively

m = partition(a, lo, hi);quicksort(a, lo, m-1);quicksort(a, m+1, hi);

}else // the base case…

…}

Page 28: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 28

The base case…

• We have the base case in this recursion when the subarray a[lo]…a[hi] contains zero elements (lo==hi+1), one element (lo==hi), or two elements (lo==hi-1).

• With no elements, we ignore it

• With one element, it’s already sorted

• With two elements, we just swap them:// 0, 1, or 2 elements, so sort directlyif (hi == lo+1 && a[lo] > a[hi])

swap(a, lo, hi);

Page 29: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 29

quicksort( )

private void quicksort(double[] a, int lo, int hi) {int m;

if (hi > lo+1) { // there are at least 3 elements// so sort recursively

m = partition(a, lo, hi);quicksort(a, lo, m-1);quicksort(a, m+1, hi);

}else // 0, 1, or 2 elements, so sort directly

if (hi == lo+1 && a[lo] > a[hi])swap(a, lo, hi);

}

Page 30: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 30

The outside world’s version

• As usual, we overload quicksort( ) and provide a public version that “hides” the last two arguments:

public void quicksort(double[] a) {quicksort(a, 0, a.length-1);

}

Page 31: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 31

Now, all we need is partition( )

int partition(double[] a, int lo, int hi) {// Choose middle element among a[lo]…a[hi],// and move other elements so that a[lo]…a[m-1]// are all less than a[m] and a[m+1]…a[hi] are// all greater than a[m]//// m is returned to the caller

}

Page 32: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 32

Are you feeling lucky?

• Now, this would work great if we knew the median value in the array segment, and could choose it as the pivot (i.e., know which small values go left and which large values go right). But we can’t know the median value without actually sorting the array!

• So instead, we somehow pick a pivot and hope that it is near median.

• If the pivot is the worst choice (each time), the algorithm becomes O(n2). If we are roughly dividing the subarrays in half each time, we get an O(nlog2n) algorithm.

Page 33: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 33

How to pick the median value

• There are many techniques for doing this. In practice, one good way of choosing the pivot is to take the median of three elements, specifically a[lo+1], a[(lo+hi)/2], and a[hi]

• We’ll choose their median using the method medianLocation( )

Page 34: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 34

medianLocation( )

int medianLocation(double[] a,int i, int j, int k)

{if (a[i] <= a[j])

if (a[j] <= a[k])return j;

else if (a[i] <= a[k])return k;

else return i;else // a[j] < a[i]

if (a[i] <= a[k])return i;

else if (a[j] <= a[k])return k;

else return j;}

Page 35: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 35

The partitioning process

• From the three red elements, we choose the median, a[hi]

8 1 2 6 34 9 10 5 7lo+1 hi(lo+hi)/2

• We swap the median with a[lo], and start the partitioning process on the rest:

7 1 2 6 34 9 10 5 8lo+1 hi(lo+hi)/2

Page 36: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 36

The partitioning process

• We shuffle around elements from a[lo+1] to a[hi] so that all elements less than the pivot (a[lo]) appear to all the elements greater than the pivot

• Until we are done, we have no way of knowing how many elements are less and how many elements are greater

7 1 2 6 104 5 3 8 9lo+1 hi(lo+hi)/2 m

Page 37: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 37

The partitioning process

• m is the largest subscript that contains a value less than the pivot

• We have discovered (in our example) that m = 6

• We then swap a[m] with a[lo], placing the pivot in its rightful position, in a[m], then continue to sort the left and right subarrays recursively

7 1 2 6 104 5 3 8 9lo+1 hi(lo+hi)/2 m

6 1 2 7 104 5 3 8 9lo+1 hi(lo+hi)/2 mlo

pivot

Page 38: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 38

How partition( ) works

• We will use a 3-argument version:int partition(double[ ] a, int lo, int hi)

and a 4-argument version:int partition(double[ ] a, int lo, int hi, double pivot)

• The 3-argument version moves the pivot element into a[lo], calls the 4-argument partition to shuffle the elements in the subarray a[lo+1]…a[hi], then swaps a[lo] into a[m] and returns m

Page 39: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 39

3-argument partition( )

int partition(double[] a, int lo, int hi) {// Choose middle element among a[lo]…a[hi],// and move other elements so that a[lo]…a[m-1]// are all less than a[m] and a[m+1]…a[hi] are// all greater than a[m]//// m is returned to the callerswap(a, lo, medianLocation(a, lo+1, hi, (lo+hi)/2));int m = partition(a, lo+1, hi, a[lo]);swap(a, lo, m);return m;

}

Page 40: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 40

How the 4-argument partition( ) works

• The 4-argument version does the main work, recursively calling itself on subarrays

• We of course assume partition( ) works on any smaller array…

• If the first element of the array is less than or equal to pivot, it’s already in the right place, just call partition( ) recursively on the rest:

if (a[lo] <= pivot) // a[lo] in correct halfreturn partition(a, lo+1, hi, pivot);

(this is the “current” lo, not the lo of the whole array)

Page 41: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 41

How the 4-argument partition( ) works

• If a[lo] > pivot, then a[lo] belongs in the upper half of the subarray, and we swap it with a[hi]

• We still don’t know where the new a[lo] value should go, so we partition recursively on the subarray that includes a[lo] but not a[hi]

if (a[lo] <= pivot) // a[lo] in correct halfreturn partition(a, lo+1, hi, pivot);

else { // a[lo] in wrong halfswap(a, lo, hi);return partition(a, lo, hi-1, pivot);

}

Page 42: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 42

How the 4-argument partition( ) works

• The base case is the one element subarray, when lo==hi. Is the one element “small” or “large”?

• If it is small (less than the pivot), then it is at the middle point m (and we can swap it with the pivot)

• Otherwise, it is just above the middle point (and we want the pivot swapped with the element just below it)

Page 43: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 43

4-argument partition( )

int partition(double[] a,int lo, int hi, double pivot) {

if (hi == lo)if (a[lo] < pivot)

return lo;else

return lo-1;else if (a[lo] <= pivot) // a[lo] in correct half

return partition(a, lo+1, hi, pivot);else { // a[lo] in wrong half

swap(a, lo, hi);return partition(a, lo, hi-1, pivot);

}}

Page 44: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 44

Example of partition

• The starting array:

4 2 15 3 6lo hi

• Choose the median from among:

4 2 15 3 6lo hi(lo+hi)/2lo+1

• Swap the median with a[lo]:

3 2 15 4 6pivot

Page 45: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 45

Example of partition

• Now, partition the subarray (not counting pivot); a is now the new subarray…

3 2 15 4 6lo hi

• a[lo] > pivot, so swap it with a[hi], and continue with the partition:

3 2 51 4 6lo hi

pivot

pivot

Page 46: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 46

Example of partition

• a[lo] is now less than pivot, so we leave it and continue with the partition:

3 2 51 4 6lo hi

• Now a[lo] is greater than pivot, so we swap it with a[hi] and continue with the partition:

3 2 51 6 4lo hi

pivot

pivot

Page 47: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 47

Example of partition

• a[lo] is again greater than pivot, so we swap it with a[hi] and continue with the partition:

3 6 51 2 4lo hipivot

• a[lo] is less than the pivot, so lo (i.e., index 2) is returned by the 4-argument partition( ); the 3-argument partition then swaps the pivot and the middle element

3 6 512 4pivot

Now we’re ready to recursively quicksort the left and right subarrays

Page 48: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 48

quicksort( )

private void quicksort(double[] a, int lo, int hi) {int m;

if (hi > lo+1) { // there are at least 3 elements// so sort recursively

m = partition(a, lo, hi);quicksort(a, lo, m-1);quicksort(a, m+1, hi);

}else // 0, 1, or 2 elements, so sort directly

if (hi == lo+1 && A[lo] > A[hi])swap(a, lo, hi);

}

Page 49: Introduction to Computer Science Recursive Array Programming Recursive Sorting Algorithms Unit 16

16- 49

Performance Comparison

• Quicksort:

– Best case: O(nlog2n)

– Worst case: O(n2) – when the pivot is always the second-largest or second-smallest element (since medianLocation won’t let us choose the smallest or largest)

– Average case over all possible arrangements of n array elements: O(nlog2n)

• Selection Sort and Insertion Sort

– Average case: O(n2)