A Question How many people here don’t like recursion? Why not? A Promise: By the end of this lecture, you will say: “Recursion Rocks My World!”

Slides:



Advertisements
Similar presentations
Exponential Functions Logarithmic Functions
Advertisements

Recursion yet another look To recurse is divine, to iterate is human.
Recursion –a programming strategy for solving large problems –Think “divide and conquer” –Solve large problem by splitting into smaller problems of same.
Fundamentals of Computer Science Lecture 14: Recursion Instructor: Evan Korth New York University.
© Janice Regan, CMPT 102, Sept CMPT 102 Introduction to Scientific Computer Programming Recursion.
Computer Science II Recursion Professor: Evan Korth New York University.
Recursion. Binary search example postponed to end of lecture.
Fundamentals of Computer Science Lecture 14: Recursion Instructor: Evan Korth New York University.
Introduction to Computers and Programming Lecture 4: Mathematical Operators New York University.
Unit 181 Recursion Definition Recursive Methods Example 1 How does Recursion work? Example 2 Problems with Recursion Infinite Recursion Exercises.
Slides prepared by Rose Williams, Binghamton University Chapter 11 Recursion.
Slides prepared by Rose Williams, Binghamton University Chapter 11 Recursion.
ICS103 Programming in C Lecture 11: Recursive Functions
Chapter 15 Recursive Algorithms. 2 Recursion Recursion is a programming technique in which a method can call itself to solve a problem A recursive definition.
CHAPTER 10 Recursion. 2 Recursive Thinking Recursion is a programming technique in which a method can call itself to solve a problem A recursive definition.
Exponent Rules Repeated Multiplication Remember: so and.
Lesson 4: Percentage of Amounts.
A quadratic equation is a second degree polynomial, usually written in general form: The a, b, and c terms are called the coefficients of the equation,
Arithmetic of Positive Integer Exponents © Math As A Second Language All Rights Reserved next #10 Taking the Fear out of Math 2 8 × 2 4.
Recursion. Basic problem solving technique is to divide a problem into smaller subproblems These subproblems may also be divided into smaller subproblems.
Lecture 8. How to Form Recursive relations 1. Recap Asymptotic analysis helps to highlight the order of growth of functions to compare algorithms Common.
Chapter 13 Recursion. Topics Simple Recursion Recursion with a Return Value Recursion with Two Base Cases Binary Search Revisited Animation Using Recursion.
Sound Check.
1 Decrease-and-Conquer Approach Lecture 06 ITS033 – Programming & Algorithms Asst. Prof. Dr. Bunyarit Uyyanonvara IT Program, Image and Vision Computing.
Unit 11, Part 2: Introduction To Logarithms. Logarithms were originally developed to simplify complex arithmetic calculations. They were designed to transform.
Lecture 10 Recursion CSE225: Data Structures. 2 A Look Back at Functions #include double distance(double x1, double y1, double x2, double y2) { double.
Week 5 - Monday.  What did we talk about last time?  Linked list implementations  Stacks  Queues.
Fall Week 3 CSCI-141 Scott C. Johnson.  Say we want to draw the following figure ◦ How would we go about doing this?
Analysis of Algorithms
Extending the Definition of Exponents © Math As A Second Language All Rights Reserved next #10 Taking the Fear out of Math 2 -8.
Hopefully this lesson will give you an inception of what recursion is.
Chapter 13 Recursion. Learning Objectives Recursive void Functions – Tracing recursive calls – Infinite recursion, overflows Recursive Functions that.
CSIS 123A Lecture 9 Recursion Glenn Stevenson CSIS 113A MSJC.
Week 6 - Monday.  What did we talk about last time?  Exam 1!  Before that:  Recursion.
Data Structures R e c u r s i o n. Recursive Thinking Recursion is a problem-solving approach that can be used to generate simple solutions to certain.
Recursion Review: A recursive function calls itself, but with a smaller problem – at least one of the parameters must decrease. The function uses the results.
IB Computer Science Unit 5 – Advanced Topics Recursion.
1 CS161 Introduction to Computer Science Topic #9.
Recursion A function that calls itself. Recursion A function which calls itself is said to be recursive. Recursion is a technique which will allow us.
Solving Linear Equations. Example 1 It’s obvious what the answer is. However, we need to start with the basics and work our way up because we need to.
© Janice Regan, CMPT 128, February CMPT 128: Introduction to Computing Science for Engineering Students Recursion.
A Different Solution  alternatively we can use the following algorithm: 1. if n == 0 done, otherwise I. print the string once II. print the string (n.
CSE 143 Lecture 13 Recursive Backtracking slides created by Ethan Apter
1 Recursion Recursive function: a function that calls itself (directly or indirectly). Recursion is often a good alternative to iteration (loops). Its.
CS 116 Object Oriented Programming II Lecture 13 Acknowledgement: Contains materials provided by George Koutsogiannakis and Matt Bauer.
Recursion by Ender Ozcan. Recursion in computing Recursion in computer programming defines a function in terms of itself. Recursion in computer programming.
CMSC201 Computer Science I for Majors Lecture 19 – Recursion (Continued) Prof. Katherine Gibson Prof. Jeremy Dixon Based on slides from UPenn’s.
Recursion ● Recursion or Iteration ● A Common Recursive Design Pattern ● Computing factorials ● Searching a filesystem tree ● Faster exponentiation ● Slow.
Chapter 13 Recursion Copyright © 2016 Pearson, Inc. All rights reserved.
CMSC201 Computer Science I for Majors Lecture 20 – Recursion (Continued) Prof. Katherine Gibson Based on slides from UPenn’s CIS 110, and from previous.
Introduction to Recursion
OBJECT ORIENTED PROGRAMMING II LECTURE 23 GEORGE KOUTSOGIANNAKIS
A Question How many people here don’t like recursion? Why not?
Lesson #6 Modular Programming and Functions.
Decrease-and-Conquer Approach
Lesson #6 Modular Programming and Functions.
Hassan Khosravi / Geoffrey Tien
Introduction to Computer Science - Alice
Lesson #6 Modular Programming and Functions.
Applied Algorithms (Lecture 17) Recursion Fall-23
Programming application CC213
Lesson #6 Modular Programming and Functions.
Recursion Taken from notes by Dr. Neil Moore
Recursion yet another look To recurse is divine, to iterate is human
Last Class We Covered Recursion Stacks Parts of a recursive function:
At the end of this session, learner will be able to:
ICS103 Programming in C Lecture 11: Recursive Functions
Chapter 13 Recursion Copyright © 2010 Pearson Addison-Wesley. All rights reserved.
Presentation transcript:

A Question How many people here don’t like recursion? Why not? A Promise: By the end of this lecture, you will say: “Recursion Rocks My World!”

Recursion Let’s say you place two rabbits in a hutch. What’s going to happen?

If it takes two months for rabbits to reach maturity, in two months you’ll have one productive pair and one (brand new) non-productive pair. (This assumes all rabbits live up to their reputation.) Two Months Later... original rabbits new rabbits

1 month old0 months old The next month, you get another pair... The rabbits keep at it.

Suppose What if: The rabbits always had two offspring, always male and female; Rabbits always reached maturity in two months; No rabbit dies. How many pairs of rabbits do you have in a year?

Hare Raising Story Start End Month 5 End Month 1 End Month 2 End Month 3 End Month 4 = one m/f pair KEY

Pairs of Rabbits MonthProductiveNon-ProductiveTotal See a pattern yet?

Let’s Take Another Example Instead of rabbits, let’s use geometry. Draw a square of size 1. Rotating 90 degrees, add to it a square of size 1. Rotating 90 degrees again, add a square of size 2. Again, rotate and add a square of size 3, and so on. Keep this up for the sequence we noted in the table: 1, 1, 2, 3, 5, 8, 13, 21,..., What do you see?

1

1

2

3

5

8

13

21

Does this look familiar?

It’s not just about rabbits.

The Truth is Out There

See the pattern? MonthProductiveNon-ProductiveTotal We used brute force to find the progression: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,..., It turns out this pattern is repeated in many places: sea shells, sun flowers, pine cones, the stock market, bee hives, etc. It’s the Fibonacci Sequence.

Writing the Formula Given: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,..., Can we write this as a formula for any number, n? This guy could: Jacques Binet ( ) nn Fib(n) = But let’s be honest. We’re not as smart as him. But that’s OK. We can code.

What If You Can’t Find the Formula? Suppose you didn’t know: nn Fib(n) = You could take a Math course or you could instead manage with: Fib(n) = Fib(n-1) + Fib(n-2), Fib(0) = 0; Fib(1) = 1; (The value at any given place is the sum of the two prior values.) Which one would your rather code and debug? For some problems, there might not exist a formula, and recursion is your only option.

Recursive Fibonacci Fib(n) = Fib(n-1) + Fib(n-2), Fib(0) = 0; Fib(1) = 1; We have our general rule: We can say a few things about it: It’s defined recursively (duh). It has a terminal condition (AHA!) It can be determined and calculated (addition)

Coding Fibonacci int fib (int num) { What do we know to start with? We know that we need a function that return the Fibonacci value for a number at a given position. This suggests a function that gives and gets an int

Coding Fibonacci int fib (int num) { if (num == 0) return 0; What’s the FIRST thing we do with a recursive method? We plan on how it will terminate! We know one special case for the Fibonacci sequence: F(0) = 0

Coding Fibonacci int fib (int num) { if (num == 0) return 0; else if (num == 1) return 1; We also know a second special case that could terminate our recursion: F(1) = 1.

Coding Fibonacci int fib (int num) { if (num == 0) return 0; else if (num == 1) return 1; else return fib(num-1) + fib(num-2); } The last part of our formula is merely: F(n) = F(n-1) + F(n-2)

Coding Fibonacci int fib (int num) { if (num == 0) return 0; else if (num == 1) return 1; else return fib(num-1) + fib(num-2); } Is this safe? What if someone passed in 0 to our method? What happens? What if they passed in 1?

Coding Fibonacci int fib (int num) { if (num == 0) return 0; else if (num == 1) return 1; else return fib(num-1) + fib(num-2); } void main(String[] args) { for (int i=0; i < 10; i++) printf(“fib(%d)=%d\n”,i,fib(i)); } It is our responsibility to write a main to test this method.

Coding Fibonacci int fib (int num) { if (num == 0) return 0; else if (num == 1) return 1; else return fib(num-1) + fib(num-2); } void main(String[] args) { for (int i=0; i < 10; i++) printf(“fib(%d)=%d\n”,i,fib(i)); } Are we done? What about negative numbers? More work is needed

Recursion Review So far, we’ve seen that for recursive behavior: 1) Recursion exists in all of nature. easier 2) It’s easier than memorizing a formula. Not every problem has a formula, but every problem can be expressed as a series of small, repeated steps. 3) Each step in a recursive process should be small, calculable, etc. 4) You absolutely need a terminating condition.

Honesty in Computer Science 1. To make life easy the typical examples given for recursion are factorial and the Fibonacci numbers. 2. Truth is the Fibonacci is a horror when calculated using “normal” recursion and there’s not really any big advantage for factorial. 3. So why all the fuss about recursion? 4. Recursion is absolutely great when used to write algorithms for recursively defined data structures like binary trees. Much easier than iteration! 5. Recursion is excellent for any divide & conquer algorithm like...

One More Example Suppose we wanted to create a method that solve: Pow(x, y) = x y In other words, the method returned the value of one number raised to the power of another: double pow(double value, int exponent);

Planning the Method Unlike the Fibonacci example, our mathematical formula is not the complete answer. Pow(x, y) = x y We’re missing some termination conditions. But we know: x 1 = x; x 0 = 1; So we could use these as our terminating condition.

Attempt #1 double pow(double value, int exponent){ if (exponent == 0) return 1D; Always, always start with some sort of terminating condition. We know any number raised to the zero power is one.

Attempt #1 double pow(double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value;... and any number raised to the power of one is itself.

Attempt #1 double pow(double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else return value * pow (value, exponent--); } For all other values, we can return the number times the recursive call, using our exponent as a counter. Thus, we calculate: 2 6 = 2*2*2*2*2*2

Attempt #1 double pow(double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else return value * pow (value, exponent--); } When we run this, however, bad things happen. The program crashes, having caused a stack overflow. How can we solve this?

Attempt #1 double pow(double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else { return value * pow (value, exponent--); } Our debug statement tells us that the exponent is never being decreased. Evidently, the “exponent--” line is not being evaluated before the recursive call takes place. As it turns out, the post-decrement operator -- is the problem. DOH!

Attempt #1 double pow(double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else { exponent = exponent - 1; return value * pow (value, exponent); } We decide that typing one extra line takes less time than debugging such a subtle error. Things are working now.

“Do I Have to Use Recursion?” double pow(double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else { exponent = exponent - 1; return value * pow (value, exponent); } How many would have preferred to do this with a “for loop” structure or some other iterative solution? How many think we can make our recursive method even faster than iteration?

Nota Bene Our power function works through brute force recursion. 2 8 = 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 But we can rewrite this brute force solution into two equal halves: 2 8 = 2 4 * 2 4 and 2 4 = 2 2 * 2 2 and 2 2 = 2 1 * 2 1 and anything to the power 1 is itself!

And here's the cool part = 2 4 * 2 4 Since these are the same we don't have to calculate them both!

AHA! So the trick is knowing that 2 8 can be solved by dividing the problem in half and using the result twice! So only THREE multiplication operations have to take place: 2 8 = 2 4 * = 2 2 * = 2 1 * 2 1

"But wait," I hear you say! You picked an even power of 2. What about our friends the odd numbers? Okay we can do odds like this: 2 odd = 2 * 2 (odd-1)

"But wait," I hear you say! You picked a power of 2. That's a no brainer! Okay how about = 2 * 2 20 (The odd number trick) 2 20 = 2 10 * = 2 5 * = 2 * = 2 2 * = 2 1 * 2 1

"But wait," I hear you say! You picked a power of 2. That's a no brainer! Okay how about = 2 * 2 20 (The odd number trick) 2 20 = 2 10 * = 2 5 * = 2 * = 2 2 * = 2 1 * 2 1 That's 6 multiplications instead of 20 and it gets more dramatic as the exponent increases

The Recursive Insight If the exponent is even, we can divide and conquer so it can be solved in halves. If the exponent is odd, we can subtract one, remembering to multiply the end result one last time. We begin to develop a formula: Pow(x, e) = 1, where e == 0 Pow(x, e) = x, where e == 1 Pow(x, e) = Pow(x, e/2) * Pow(x,e/2), where e is even Pow(x, e) = x * Pow(x, e-1), where e > 1, and is odd

Solution #2 double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; } We have the same base termination conditions as before, right?

Solution #2 double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { } This little gem determines if a number is odd or even.

Solution #2 double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { } int isOdd(int num){ if (num==0) return 1; else return isEven(num-1); } int isEven(int num){ if (num==0) return 0; else return isOdd(num-1); } Don’t like the mod operator? Get used to it. The alternative is something mutually recursive and wacky, like this:

Solution #2 double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { } int isOdd(int num){ if (num==0) return 1; else return isEven(num-1); } int isEven(int num){ if (num==0) return 0; else return isOdd(num-1); } That mod operator is starting to look a lot better, eh? It merely tests if the number is evenly divided by two.

Solution #2 double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { exponent = exponent / 2; } We next divide the exponent in half.

Solution #2 double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { exponent = exponent / 2; double half = pow (value, exponent); } We recurse to find that half of the brute force multiplication.

Solution #2 double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { exponent = exponent / 2; double half = pow (value, exponent); return half * half; } And return the two halves of the equation multiplied by themselves

Solution #2 double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { exponent = exponent / 2; double half = pow (value, exponent); return half * half; } else { exponent = exponent - 1; } If the exponent is odd, we have to reduce it by one...

Solution #2 double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { exponent = exponent / 2; int half = pow (value, exponent); return half * half; } else { exponent = exponent - 1; double oneless = pow (value, exponent); } And now the exponent is even, so we can just recurse to solve that portion of the equation.

Solution #2 double pow (double value, int exponent){ if (exponent == 0) return 1D; else if (exponent == 1) return value; else if (exponent % 2 == 0) { exponent = exponent / 2; int half = pow (value, exponent); return half * half; } else { exponent = exponent - 1; double oneless = pow (value, exponent); return oneless * value; } We remember to multiply the value returned by the original value, since we reduced the exponent by one.

Recursion vs. Iteration: Those of you who voted for an iterative solution are likely going to produce: O(N) In a Dickensian world, you would be fired for this. While those of you who stuck it out with recursion are now looking at: O(log 2 n) For that, you deserve a raise.

STOP Absolutely CRITICAL point coming up

Questions?