34
An Introduction to Programming though C++ Abhiram G. Ranade Ch. 10: Recursive functions

An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

Page 1: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

An Introduction to Programming though C++

Abhiram G. Ranade

Ch. 10: Recursive functions

Page 2: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Recursion

• Many physical and abstract objects have the following property:– The object has parts which are similar to the object itself.– Such an object is said to be recursive, or possess recursive structure.

• Computation may also possess recursive structure:– While computing the GCD of m, n, we find the GCD of n, m%n.– So it might seem that a function that finds GCD of m, n should call

itself with arguments n, m%n.– This idea works beautifully, and such recursive functions are vey

useful.– Recursive functions are also useful for processing recursive objects.

• We see all this next!

Page 3: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Euclid’s theorem on GCD

THEOREM: If m % n == 0, then GCD(m, n) = n, else GCD(m,n) = GCD(n, m % n).

The theorem looks like a program!

int gcd(int m, int n){ if (m % n == 0) return n; else return gcd(n, m % n);}

Will this work?

Page 4: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Execution

Activation frame of main

Activation frame of gcd(123,82)

Activation frame of gcd(82,41)

int gcd(int m, int n){ if(m % n == 0) return n; else return gcd(n, m%n);}

Activation frame of gcd(205,123)

main_program{ cout << gcd(205,123) << endl;}

4141

41Prints 41

Page 5: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Demo

recursiveGcd.cpp

Page 6: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Recursion

• Recursion = The phenomenon of a function calling itself– Seems like we are defining the function in terms of itself– But no circularity if the arguments to the new call are different

from the arguments in the original call.

• Each call executes in its own activation frame.• Some call must return without another recursive call– Otherwise infinite recursion (error!)

• In the body of gcd there was just one recursive call. We can have several calls if we wish. Examples soon.

Page 7: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Comparison of recursive and non-recursive gcd

int gcd(int m, int n){ if (m % n == 0) return n; else return gcd(n, m % n);}int gcd(int m, int n){ while(m % n != 0){

int r = m%n;m = n;n = r;

} return n;}

Recursive calls in gcd(205,123):• gcd(123,82)• gcd(82,41)

• Values of m,n in consecutive iterations of gcd(205,123):

• 205, 123• 123, 82,• 82, 41

• The two programs are ”really” doing the same calculations!

• But on the surface they look very different.

Page 8: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Remarks

• Recursion often produces compact, elegant programs.– Recursive programs might be slightly slower because they

need to create activation frames etc.

• Recursion is also a way to discover algorithms.Euclid quite possibly thought to himself: – “Instead of doing laborious computation to find the gcd of 205

and 123, can I find two smaller numbers whose gcd is the same as that of 205 and 123?”

– This is recursive thinking! It is common in mathematics.–We will see more examples soon.

Page 9: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Exercise

The factorial of n, written as n!, is defined as follows.• 0! = 1• For n > 0, n! = n * (n-1)!Example: 4! = 4*3! = 4*3*2! = 4*3*2*1! = 4*3*2*1*0! = 4*3*2*1 =24Write a recursive function that computes n! for any non-negative integer n.How many activation fames would a call factorial(5) create? Draw them out. Show the value returned by each.

Page 10: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

What we discussed

• Recursion = a function calling itself during execution.• A recursive function to find the GCD.• Comparison between recursive and non recursive gcd.– Recursive gcd is more compact and elegant, though both do

the same computation

• Next: Recursive objects

🎻

Page 11: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Outline

• Examples of recursive objects• Example of processing recursive objects

Page 12: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Organization tree(typically “grows” downwards)

President

VP

VP

Director Director Director Director

Manager Manager

Page 13: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Tree representing ((57*123)+329)*(358/32))

President

+ /

* 329 358 32

57 123

*

Page 14: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

An actual tree drawn using the turtle in simplecpp

Page 15: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Processing of recursive objects on a computer

Natural strategy:• Processing entire object = Processing all parts.• Processing parts: – Use a recursive call if the part is similar to the entire object.

If you want to process organizations, or mathematical expressions, you must understand recursion!Next:• Drawing a recursive object on the screen• This will require us to employ the “natural strategy”.

Page 16: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

What we will draw: A very stylized tree

Page 17: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Stylized tree = 2 small stylized trees + V

Parts:• Root• Left branch, Left subtree• Right branch, Right subtree

• Number of levels: number of times the tree has branched going from the root to any leaf.

• Number of levels in our tree = 5

Page 18: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Drawing the tree using coordinate based graphics

To draw an L level tree:if L > 0{ Draw the left branch, Draw a Level L-1 tree on top of it. Draw the right branch, Draw a Level L-1 tree on top of it.}• We need coordinates ...

– Say root is to be drawn at (rx,ry)– Total height of drawing is H.– Total width of drawing is W.

• We should then figure out where the roots of the subtrees will be, and their width and height.

Page 19: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

(rx,ry)

W

H

H/L

(rx-W/4,ry-H/L) (rx+W/4,ry-H/L)

Height of subtree

=H-H/L

Width of subtree

=W/2

Page 20: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

void tree(int L, double rx, double ry, double H, double W){// L levels, Root at (rx,ry), Height H, Width W if(L>0){ Line left(rx, ry, rx-W/4, ry-H/L); Line right(rx, ry, rx+W/4, ry-H/L); right.imprint(); left.imprint(); tree(L-1, rx-W/4, ry-H/L, H-H/L, W/2); tree(L-1, rx+W/4, ry-H/L, H-H/L, W/2); }}main_program{ initCanvas(); tree(5, 250, 300, 300,500);}

Page 21: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Demo

• Tree.cpp

Page 22: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Exercise

Draw the botanical tree using the turtle.• Break it up into parts, i.e. trunk, left subtree, right subtree.• Use the turtle to first draw the trunk.• On top of it draw the left subtree.– After the drawing is finished, the turtle should come back to the

original position and be facing in the same direction.

• The left and right subtrees are not exactly the same.• You will need to play around a bit to get this. Start by

trying to draw trees with few levels first.

Page 23: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

What we discussed

• Recursive objects have parts similar to themselves.• Many interesting objects have recursive structure.• Processing recursive objects requires recursive

functions.• Drawing recursive objects is a good example of how you

might “process” recursive objects.Next: How to think about recursion. Conclusion

🎻

Page 24: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

How to think about recursion

• A recursive program seems very complex.• As it executes, multiple calls might be in progress

at the same time.• How do we reason about all these?• Isnt it very hard just to visualize the execution?Key point: We do not attempt to visualize all this.

Page 25: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

High level ideas

Designing a recursive algorithm:• Attempt to solve the given problem instance by constructing and

solving smaller instances of the same type.– GCD: (m,n) GCD(n,m%n), Drawing: (L,...) (L-1,...)

• Solve the simplest instances directly.– GCD: m%n = 0, Drawing: L=0

Understanding recursive algorithms:• Is there a “problem size” that reduces in the recursive calls?– GCD: Argument 2. Drawing: Argument 1.

• Will we eventually get to problems that are solved without recursion?

Page 26: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Some terminology

Top level recursive call:The call made from the main program, or the first call made to the recursive function.• gcd: the call gcd(m,n) Drawing: the call tree(L,rx,ry,H,W)Level 1 recursive callsCalls made directly while executing the top level call.• gcd: gcd(n,m%n)• Drawing: tree(L-1, rx-W/4, ry-H/L, H-H/L, W/2) tree(L-1, rx+W/4, ry-H/L, H-H/L, W/2)Base cases:Input values for which the top level call returns without recursing.• gcd: m,n such that m%n == 0 Drawing: L = 0

Page 27: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

More Terminlogy

Preconditions: Valid values for inputsGCD: m,n > 0.Drawing: L≥0, rx,ry, H≥0, W≥0

Problem Size: Something indicative of the amount of work needed to find the solution.Needs to be chosen creativelyGCD: nDrawing: L

Page 28: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Understanding recursive functions 1: Base cases

Are there any base cases?• Base cases must exist, otherwise program will not

terminate.Does the function produce correct results for the base cases?• gcd: base cases: m,n such that m%n == 0.– Answer in such cases: n, which is correct.

• Drawing: base case: L = 0– Answer in this case: Nothing drawn. – Correct because tree is empty for L=0.

Page 29: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Understanding recursive functions 2: Valid level 1 recursive calls

Are the arguments in the level 1 calls valid, i.e. do they satisfy the preconditions of the functions?• gcd: level 1 call is gcd(n, m%n)–We require that arguments must be positive integers.– n > 0 because n is an argument to the top level call gcd(m,n), and we

assume that it satisfies preconditions– Level 1 call is made only if m%n > 0. So second argument is also positive.

• Drawing: Level 1 calls are:– tree(L-1, rx-W/4, ry-H/L, H-H/L, W/2)– tree(L-1, rx+W/4, ry-H/L, H-H/L, W/2)– Level 1 calls are made only if L>0, so L-1 ≥ 0.–We can also see that H – H/L, W/2 are ≥ 0.

Page 30: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Understanding recursive functions 3: Does the problem size reduce? Can it reduce indefinitely?

• gcd: level 1 call is gcd(n, m%n)– Second argument reduces. It must stay above 0.

• Drawing: Level 1 calls are:– tree(L-1, rx-W/4, ry-H/L, H-H/L, W/2)– tree(L-1, rx+W/4, ry-H/L, H-H/L, W/2)– First argument reduces. It cannot become negative.

Page 31: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Underst. Rec Functions. 4: Will the top level calls return the correct result if the level 1 calls do?

GCD: • Assume level 1 call, GCD(n,m%n) returns correct result.• Top level call returns what level 1 call returns.• Code examination: GCD of m,n = GCD of n, m%n. So top level

is correct.Drawing: • Suppose Level 1 calls (L-1,...), (L-1,...) draw the subtrees

correctly• Then top level call draws the branches in the right positions.• Overall drawing will be correct

Page 32: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Summary

To check if a recursive function is correct we should check1. There are base cases and

correct results are obtained for the base cases.

2. The level 1 recursive calls satisfy the preconditions.

3. The problem size reduces but cannot reduce indefinitely.

4. If the level 1 calls work correctly, the top level call will work correctly.

• We do not need to argue that the level 1 calls work correctly.

• We dont even need to think about calls made by level 1 calls.

• 1,2,3 ensure that the computation will terminate eventually.

• 4 ensures that the correct result will be returned.

Page 33: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Exercise

Consider the function below and its specification.int f(int n){ if(n == 0) return 1; return f(n-1) + f(n-2);}Precondition: n should be a non-negative integerPostcondition: f(n) should equal f(n-1) + f(n-2), with f(0) = 0State whether this function is correct.This is a trick question: you should also consider whether the post condition is specified fully. You should be able to do this by asking the questions discussed earlier.

Page 34: An Introduction to Programming though C++cs101/lectures/Lec9.pdf · Recursion • Many physical and abstract objects have the following property: – The object has parts which are

Concluding remarks

• Recursion allows many programs to be expressed very compactly.• The idea that the solution of a large problem can be obtained from

the solution of a similar problem of the same type, is very powerful.– Euclid probably used this idea to discover his GCD algorithm.– Recursion is very natural for objects having recursive definition, e.g. trees

• To understand if/why a recursive function works, we need to make a few simple checks.

• Some programs can be written recursively or iteratively (gcd, factorial), but some others are best written recursively (drawing trees).

🎻🎻