Chapter 14 Recursion Lecture Slides to Accompany An Introduction to Computer Science Using Java (2nd...
-
Upload
alexis-sawyer -
Category
Documents
-
view
221 -
download
2
Transcript of Chapter 14 Recursion Lecture Slides to Accompany An Introduction to Computer Science Using Java (2nd...
Chapter 14
Recursion
Lecture Slides to Accompany
An Introduction to Computer Science Using Java (2nd Edition)
by
S.N. Kamin, D. Mickunas, , E. Reingold
Chapter Preview
In this chapter we will:• introduce recursion as a programming technique • show how recursion can be used to simplify the design
of complex algorithms • present several well known recursive algorithms
(e.g. quicksort, merge sort, Guaussian elmination)• introduce the linked list data structure and recursive
implementations for several of its methods• present programs for drawing two types of fractal
curves
Recursion
• Basic problem solving technique is to divide a problem into smaller subproblems
• These subproblems may also be divided into smaller subproblems
• When the subproblems are small enough to solve directly the process stops
• A recursive algorithm is a problem solution that has been expressed in terms of two or more easier to solve subproblems
Counting Digits
• Recursive definitiondigits(n) = 1 if (–9 <= n <= 9)
1 + digits(n/10) otherwise
• Exampledigits(321) =
1 + digits(321/10) = 1 +digits(32) =
1 + [1 + digits(32/10)] = 1 + [1 + digits(3)] =
1 + [1 + (1)] =
3
Counting Digits in Java
int numberofDigits(int n) {
if ((-10 < n) && (n < 10))
return 1
else
return 1 + numberofDigits(n/10);
}
Recursion
• If you want to compute f(x) but can’t compute it directly
• Assume you can compute f(y) for any value of y smaller than x
• Use f(y) to compute f(x)• For this to work, there has to be at least one
value of x for which f(x) can be computed directly (e.g. these are called base cases)
Evaluating Exponents Recurisivley
static int power(int k, int n) {
// raise k to the power n
if (n == 0)
return 1;
else
return k * power(k, n – 1);
}
Divide and Conquer
• Using this method each recursive subproblem is about one-half the size of the original problem
• If we could define power so that each subproblem was based on computing kn/2 instead of kn – 1 we could use the divide and conquer principle
• Recursive divide and conquer algorithms are often more efficient than iterative algorithms
Evaluating Exponents Using Divide and Conquer
static int power(int k, int n) { // raise k to the power n if (n == 0) return 1; else{ int t = power(k, n/2); if ((n % 2) == 0) return t * t; else return k * t * t;}
Selection Sort
private static void selectionSort
(double[] A, int lo, int hi) {
// A[0]..A[lo-1] contain smallest
// values in A, in ascending order
if (lo < hi) {
swap(A, lo, findMiniumum(A, lo, hi);
selectionSort(A, lo + 1, hi);
}
}
Find Minimumprivate static int findMinimum
(double[] A, int lo, int hi) {
if (lo == hi)
return lo;
else {
int locationOfMin = findMinimum(A, lo + 1, hi);
if (A[lo] < A[locationOfMin])
return lo;
else
return locationOfMin;
}
}
Selection Sort Helper Function
• Client programs should not need to know anything about how selectionSort was implemented
• A single argument helper function can be used to help clients make use of the new version
• Examplepublic static void selectionSort(double[] A) { selectionSort(A, 0, A.length – 1);}
Insertion Sort
private static void insertionSort
(double[] A, int hi) {
// Sort A[0] .. A[hi]
if (hi > 0) {
insertionSort(A, hi – 1);
insertInOrder(A, hi, A[hi));
}
}
Insert in Order
private static void insertInOrder (double[] A, int hi, double x) { // Insert x into A[0]..A[hi-1], // filling in A[hi} in the process. // A[0]..A[hi – 1] are sorted. if ((hi == 0) || (A[hi – 1] <= x)) A[hi] = x; else A[hi] = A[hi – 1]; insertInOrder(A, hi – 1, x); }}
Insertion Sort Helper Function
• Again we should provide potential clients with a single argument helper functon
public static void InsertionSort(double[] A) {
InsertionSort(A, A.length – 1);
}
Quicksort Overview
• Choose the middle element among A[lo]..A[hi]• Move other elements so that
– A[lo]..A[m – 1] are less than A[m]– A[m + 1]..A[hi] are greater than A[m]
• Return m to the caller
Quicksort
static void quickSort
(double[] A, int lo, int hi) {
int m;
if (hi > lo + 1) { // 3 or more subarray values
m = partition(A, lo, hi);
quickSort(A, lo, m – 1);
quickSort(A, m + 1, hi);
}
else // less than 3 subarray values
if ((hi == lo + 1) && (A[lo] > A[hi])
swap(A, lo, hi);
}
Partition
static int partition (double[] A, int lo, int hi) {
// choose middle element from A[lo}..A[hi]
// move elements so A[lo]..A[m-1] are all < A[m]
// move elements so A[m+1]..A[hi] are all > A[m]
swap(A, lo, medianLocationA, lo+1, hi, (lo+hi)/2));
int m = partition(A, lo+1, hi, A[lo]);
swap(A, lo, m);
return m;
}
Partition Helper
static 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 parition(A, lo, hi – 1, pivot); } }
Median Locationstatic int medianLocation (double[] A, int i, int j, int k) { if (A[i] <= A[j]) if (A[j] < A[k]) return j;0 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 (A9j] <= A[k]) return k; else return j;}
Linear Systems
a11x1 + a12x2 + … + a1nxn = b1
a11x1 + a12x2 + … + a1nxn = b1
… … … …
a11x1 + a12x2 + … + a1nxn = b1
Solving Linear Systems
solve (System E of n equations in n unkonwns) { if (n == 1) // system is ax = b return (b/a); else { eliminate last equation yielding system E’;
solve(E’), yielding x1, … ,xn-1;
xn = (bn – an,1x1 - … - a1,n-2xn-1)/ an,n
return (x1, … , xn-1, xn);
}}
Integer List Class
class IntList { private int value; private IntList tail; public IntList(int v, IntList next) { value = v; tail = next; } public int getValue () { return value; } public intList getTail (){ return Tail; }
Constructing a Linked List
• One approach would be:IntList list = new IntList(-14, null);list = new IntList(616, list);list = new IntList(10945, list);list = new IntList(17, list);
• Alternatively we could have written:IntList list = new IntList(17, new IntList(616, new IntList(10945, new IntList(17, null))));
Constructing a Linked List from Input
Intlist readReverseList () { int inputval; IntList front = null; Inputbox in = new IntputBox(); while (true){ inputval = in.readInt(); if (in.eoi)) break; front = new IntList(inputval, front); } return front;}
Printing Linked List
void print (IntList list) {
Output out new OutputBox();
while (list != null) {
out.print(list.getValue() + “ “);
list = list.getTail();
}
out.println();
}
Computing List Length
• This method would be added to IntListpublic int length() {
if (tail == null)
return 1;
else
return 1 + tail.length();
}
Converting List to String
• This method would be added to IntList
public String toString() {
String myValue = Integer.toString(value);
if (tail == null)
return myValue;
else
return myValue + “, “ + tail.toString();
}
Retrieving nth List Element
• This method would be added to IntList
public IntList nth(int n) {
if (n = 0)
return this;
else if (tail == null)
return null;
else
return tail.nth(n – 1);
}
Adding Element to End of List
• This method would be added to IntList
public void addToEndM(int n) {
if (tail != null)
// in the middle of the list
tail.addToEndM(n);
else
// at last cell
tail = new IntList(n, null);
}
Adding Element to List in Order
• This method would be added to IntListpublic IntList addInorderM(int n) { if (n < value) return new IntList(n, this); else if (n == value) return this; if (tail != null){ tail = new IntList(n, null); return this; } else{ tail = tail.addInorderM(n); return this; }}
MergeSort
public static IntList mergeSort (IntList L) {// Sort L by recursively splitting and merging if ((L == null) || (L.getTail() == null); // zero or one item return L; else { // two or more items // Split the list into two parts IntListPair p = L.split(); // Sort and merge the two parts return mergeSort(p.x).merge(mergeSort(p.y)); }}
IntListPair
class IntListPair {
public IntList x, y;
public IntListPair (IntList x, IntList y) {
this.x = x;
this.y = y;
}
}
Splitting the List
• This method would be added to IntListPair
public IntList split() {
if (tail != null)
return = new IntListPair(this, null);
else{
IntListPair p = tail.split();
return new
IntListPair(new IntList(value,p.y),p.y);
}
}
Merging the Lista
• This method would be added to IntListIntList merge(IntList L) {
if (L = null)
return this;
if (value < L.value)
if (tail == null)
return new IntList(value, L);
else
return new IntList(value, tail.merge(L));
return new
return new IntList(L.value,merge(L.tail));
}
}