[Instructions] [Search] [Current] [Changes] [Syllabus] [Handouts] [Outlines] [Labs] [Assignments] [Examples] [Bailey Docs] [SamR Docs] [Tutorial] [API]

**Held**: Friday, February 20, 1998

- Assignment 3 is due today.
- Don't forget that the exam is next Wednesday. I've prepared (or will prepare) a review sheet. You can also look at the exam I gave last semester, with some answers.

- In a typical algorithmic language there are many ways of expressing repetition.
- For many people (particularly for many mathematicians), a common
way of expressing repetition is
*recursion*. - A recursive function is a function that (sometimes) calls itself.
- In some ways, this is like the legendary dragon/worm that eats its own tail.
- However, it is a natural way to represent repetition.

- Consider the task of sorting a list (ordering the elements so that the
smallest element is first, the next smallest is second, and so on and
so forth). One way to do this is:
- Remove the smallest element from the list.
- Sort the rest of the list.
- Put the smallest element back at the front of the list.

- How do we sort the rest of the list? Using the same procedure.
- Remove the smallest element from the remaining elements.
- Sort the rest of the list.
- Put the smallest element back at the front of the list.

- How do we sort the list that is now two elements shorter? The same way.
- Eventually, we wind up with a zero-length list, which is sorted by definition.
- We might write this in pseudocode as
public List sort(List l) { if (l.empty()) { return new List(); } else { Object smallest = l.deleteSmallest(); List sorted = sort(l); sorted.prepend(smallest); return sorted; } } // sort(List)

- We can define the mathematical factorial function in a similar way.
- What is
`N!`

? It's`N * (N-1)!`

- What is
`(N-1)!`

? It's`(N-1) * (N-2)!`

- ...
- What is
`0!`

? It's`1`

.

- What is
- In pseudocode
public int factorial(int N) throws Exception { if (n < 0) { throw new Exception("Cannot take factorial of negative numbers."); } else if (n == 0) { return 1; } else { return n * factorial(n-1); } } // factorial

- Note that both of these functions had a common form.
- A
*base case*indicates what you do for simple inputs. - A
*recursive case*says what you do for more complex inputs and involves another call to the same function, but*with different parameters*. (Hopefully, a "smaller" parameter.)

- A
- In pseudocode
public

*returnType*recursiveAlgorithm(*someType*input) { if (baseCase(input)) { return baseComputation(input); } else { return computation(input, recursiveAlgorithm(simplify(input))); } } // recursiveAlgorithm(*someType*)

- How do we determine the running time of a recursive algorithm?
In a way similar to the way in which we determine the running time
of an iterative algorithm.
- Count the number of recursive calls.
- Count the time spent during each recursive call (except for the time spent in subsequent recursive calls).

- How do you count the number of recursive calls? Often, the "shrink" function gives you a sense of how many recursive calls you need to do (how many calls to "shrink" does it take to reduce the argument to the base case).
- It is also possible to use the concept of
*recurrence relations*to determine the running time of an algorithm. - For example, if a recursive algorithm takes c steps and reduces
the parameter by one, we might express the running time as a function,
`time(N)`

which represents the running time on input of N elements:`time(N) = c + time(N-1)`

`time(1) = c`

- This equation is relatively easy to solve "intuitively".
- time(N) = c + time(N-1)
- c + c + time(N-1)
- ...
- c + c + ... + time(1)
- c + c + ... + c (N times)
- c*N

- Other interesting recurrence relations:
- time(N) = N + time(N-1)
- time(N) = c + time(N/2)
- time(N) = N + time(N/2)
- time(N) = c * time(N-1)
- time(N) = c * time(N/2)

- Consider the problem of computing x^n for integers x and n (n should be non-negative).
- Here's a simple iterative solution
/** * Compute x^n for integers x and n * pre: n >= 0 * pre: x > 0 * pre: x^n < maxint (can't really check this, but ...) * post: returns x^n */ public int exp(int x, int n) { int result = 1; // The result, computed as we go for(int i = 0; i < n; ++i) { result *= x; } return result; } // exp(int, int)

- This has a running time of O(n).
- We could rewrite it recursively as
public int exp(int x, int n) { if (n == 0) return 1; else { return x * exp(x, n-1); } } // exp(int, int)

- However, writing it recursively might lead us to think about other
ways to take advantage of recursion. For example, we might note
that if the power is even, then we can split the power in half.
That is, x^(2k) = x^k * x^k.
public int exp(int x, int n) { // Temporary value, used for integer calculations int tmp; // Choose what to do based on the exponent if (n == 0) { // x^0 = 1 for x != 0 return 1; } // n is 0 else if (even(n)) { // x^(2k) = x^k * x^k tmp = exp(x, n/2); return tmp*tmp; } // n is even else { // n is odd // x^(k+1) = x * x^k tmp = exp(x, n-1); return x*tmp; } // n is odd } // exp

- This has running time O(log_2(n)).
- Can you figure out how to write this iteratively?
- Can you figure out how to write it tail-recursively?

On to Design

Back to Algorithm Analysis, Continued

Outlines:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Current position in syllabus

[Instructions] [Search] [Current] [Changes] [Syllabus] [Handouts] [Outlines] [Labs] [Assignments] [Examples] [Bailey Docs] [SamR Docs] [Tutorial] [API]

**Disclaimer** Often, these pages were created "on the fly" with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.

This page may be found at http://www.math.grin.edu/~rebelsky/Courses/CS152/98S/home/rebelsky/public_html/Courses/CS152/98S/Outlines/outline.20.html

Source text last modified Tue Jan 12 11:52:22 1999.

This page generated on Mon Jan 25 09:49:12 1999 by SiteWeaver. Validate this page.

Contact our webmaster at rebelsky@math.grin.edu