Tải bản đầy đủ (.pdf) (37 trang)

Lecture An introduction to computer science using java (2nd Edition): Chapter 14 - S.N. Kamin, D. Mickunas, E. Reingold

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (206.26 KB, 37 trang )

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 definition
digits(n) = 1
1 + digits(n/10)

if (–9 <= n <= 9)
otherwise

• Example
digits(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
// raise
if (n ==
return
else
return
}

power(int k, int n) {
k to the power n
0)
1;
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 Minimum
private 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
• Example

public 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 Location
static 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;
}


×