1 Introduction to Recursion Please fasten your seat belts.

Slides:



Advertisements
Similar presentations
Recursive methods. Recursion A recursive method is a method that contains a call to itself Often used as an alternative to iteration when iteration is.
Advertisements

Recursion. Binary search example postponed to end of lecture.
Recursion CS 308 – Data Structures. What is recursion? smaller version Sometimes, the best way to solve a problem is by solving a smaller version of the.
Programming with Recursion
Chapter 2 Recursion: The Mirrors. © 2005 Pearson Addison-Wesley. All rights reserved2-2 Recursive Solutions Recursion is an extremely powerful problem-solving.
Chapter 10 Recursion. Copyright © 2005 Pearson Addison-Wesley. All rights reserved Chapter Objectives Explain the underlying concepts of recursion.
1 Chapter 18 Recursion Dale/Weems/Headington. 2 Chapter 18 Topics l Meaning of Recursion l Base Case and General Case in Recursive Function Definitions.
Recursion.
Recursion. Recursive Solutions Recursion breaks a problem into smaller identical problems – mirror images so to speak. By continuing to do this, eventually.
© 2006 Pearson Addison-Wesley. All rights reserved3-1 Chapter 3 Recursion: The Mirrors.
1 Chapter 7 Recursion. 2 What Is Recursion? l Recursive call A method call in which the method being called is the same as the one making the call l Direct.
Recursion A recursive function is a function that calls itself either directly or indirectly through another function. The problems that can be solved.
Recursion Chapter 7. Chapter 7: Recursion2 Chapter Objectives To understand how to think recursively To learn how to trace a recursive method To learn.
Chapter 2 Recursion: The Mirrors. © 2005 Pearson Addison-Wesley. All rights reserved2-2 Recursive Solutions Recursion is an extremely powerful problem-
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.
CENG 7071 Recursion. CENG 7072 Recursion Recursion is a technique that solves a problem by solving a smaller problem of the same type. A recursive function.
Recursion CS Goals Discuss recursion as another form of repetition Do the following tasks, given a recursive routine Determine whether the routine.
1 C++ Plus Data Structures Nell Dale Chapter 7 Programming with Recursion Slides by Sylvia Sorkin, Community College of Baltimore County - Essex Campus.
1 Recursion Dr. Bernard Chen Ph.D. University of Central Arkansas.
Chapter 2 Recursion: The Mirrors CS Data Structures Mehmet H Gunes Modified from authors’ slides.
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Chapter 12: Recursion Problem Solving, Abstraction, and Design using C++
Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.
1 Storage Classes, Scope, and Recursion Lecture 6.
CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem.
Recursion Chapter 7. Chapter Objectives  To understand how to think recursively  To learn how to trace a recursive method  To learn how to write recursive.
Recursion l Powerful Tool l Useful in simplifying a problem (hides details of a problem) l The ability of a function to call itself l A recursive call.
1 Programming with Recursion. 2 Recursive Function Call A recursive call is a function call in which the called function is the same as the one making.
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley. Ver Chapter 2: Recursion: The Mirrors.
1 Programming with Recursion Slides by Sylvia Sorkin, Community College of Baltimore County - Essex Campus and Robert Moyer, Montgomery County Community.
1 Lecture 14 Chapter 18 - Recursion. 2 Chapter 18 Topics l Meaning of Recursion l Base Case and General Case in Recursive Function Definitions l Writing.
1 Chapter 13 Recursion. 2 Chapter 13 Topics l Meaning of Recursion l Base Case and General Case in Recursive Function Definitions l Writing Recursive.
1 Recursion. 2 Chapter 15 Topics  Meaning of Recursion  Base Case and General Case in Recursive Function Definitions  Writing Recursive Functions with.
10/14/2015cosc237/recursion1 Recursion A method of defining a concept which refers to the concept itself A method of solving a problem by reducing it to.
1 C++ Plus Data Structures Nell Dale Chapter 7 Programming with Recursion Modified from the slides by Sylvia Sorkin, Community College of Baltimore County.
Recursion Textbook chapter Recursive Function Call a recursive call is a function call in which the called function is the same as the one making.
Computer Science and Software Engineering University of Wisconsin - Platteville 9. Recursion Yan Shi CS/SE 2630 Lecture Notes Partially adopted from C++
1 Joe Meehean.  call themselves directly  or indirectly void f(){... f();... } void g(){... h();... } void h(){... g();... }
1 C++ Plus Data Structures Nell Dale Chapter 7 Programming with Recursion Slides by Sylvia Sorkin, Community College of Baltimore County - Essex Campus.
224 3/30/98 CSE 143 Recursion [Sections 6.1, ]
Computer Science Department Data Structure & Algorithms Lecture 8 Recursion.
Review Introduction to Searching External and Internal Searching Types of Searching Linear or sequential search Binary Search Algorithms for Linear Search.
CSC 221: Recursion. Recursion: Definition Function that solves a problem by relying on itself to compute the correct solution for a smaller version of.
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.
1 Recursion. 2 Chapter 15 Topics  Meaning of Recursion  Base Case and General Case in Recursive Function Definitions  Writing Recursive Functions with.
Tail Recursion l The case in which a function contains only a single recursive call and it is the last statement to be executed in the function. l Tail.
Chapter 7 Programming with Recursion. What Is Recursion? Recursive call A method call in which the method being called is the same as the one.
Chapter 6 Lists Plus Lecture 12. What is a Circular Linked List? A circular linked list is a list in which every node has a successor; the “last” element.
Pei Zheng, Michigan State University 1 Chapter 8 Recursion.
1 Chapter 8 Recursion. 2 Recursive Function Call a recursion function is a function that either directly or indirectly makes a call to itself. but we.
CS 116 Object Oriented Programming II Lecture 13 Acknowledgement: Contains materials provided by George Koutsogiannakis and Matt Bauer.
Data Structures I (CPCS-204) Week # 5: Recursion Dr. Omar Batarfi Dr. Yahya Dahab Dr. Imtiaz Khan.
CSC 143 P 1 CSC 143 Recursion [Chapter 5]. CSC 143 P 2 Recursion  A recursive definition is one which is defined in terms of itself  Example:  Compound.
递归算法的效率分析. When a function is called... A transfer of control occurs from the calling block to the code of the function --It is necessary that there be.
Chapter 2 Recursion: The Mirrors. © 2005 Pearson Addison-Wesley. All rights reserved2-2 Recursive Solutions Recursion is an extremely powerful problem-solving.
Recursion Powerful Tool
Programming with Recursion
Recursion.
Recursion.
Recursion CENG 707.
Chapter 15 Recursion.
Recursion DRILL: Please take out your notes on Recursion
Recursion: The Mirrors
Programming with Recursion
Recursion "To understand recursion, one must first understand recursion." -Stephen Hawking.
Chapter 18-3 Recursion Dale/Weems.
When a function is called...
Yan Shi CS/SE 2630 Lecture Notes
Chapter 18 Recursion.
Chapter 3 :Recursion © 2011 Pearson Addison-Wesley. All rights reserved.
Recursion: The Mirrors
Presentation transcript:

1 Introduction to Recursion Please fasten your seat belts.

2 Recursion is difficult to master Recursion yield elegant, concise code Yet, it is difficult to debug. Minor mistakes can be disastrous for the program Infinite recursion is the most common problem Infinite recursion is more complicated than infinite loop because it consume all the memory when stacking the current status of the function. For the inexperienced programmer, the program may sometimes report a error which has no immediate relation to the recursive function

3 Recursion When “something” is defined in terms of itself! Recursive methods: A method that calls itself Recursive classes: A class that contains an instance of itself

4 Recursion Is the "art" of defining a concept using the concept itself They are the computer science equivalent of mathematical induction In computer science terms we talk about recursive functions: functions that invoke itself Not allowed in some languages When allowed they are very powerful  They express repetition without loops  They simplify code which would otherwise be confusing and unclear. It is an important tool supporting data abstraction

5 Recursive Definitions Any recursive definition has to have two parts : Basis of recursion: This is a non-recursive statement establishing definition for a fixed number of objects. The bases is the condition that makes the recursion stop Recursion: It is a condition that is written in such a way that after repeated executions of this code it will reduce to the basis. // Definition of function (x raised to y) // Where y is positive BASE : x raised to 0 is 1 RECURSION: x raised to y is equal x times x raised to y-1 // Definition of function (x raised to y) // Where y is positive BASE : x raised to 0 is 1 RECURSION: x raised to y is equal x times x raised to y-1

6 Recurrence Relations It is an relation describing the recursive function in terms of its values on smaller inputs It will be widely used when we get to analysis of algorithms There are three methods to solve recurrences Substitution method: based on mathematical induction Iteration method: converts the recurrence into a summation. Master method: Provides bounds for recurrences of the form: T(n) = aT(n/b) + f(n)  where a >= 1, b > 1 and f(n) is a given function  Requires memorization of a few cases Recurrence will be used quite frequently when describing sorting and tree algorithms Since a few of these algorithms are recursive

7 BNF (Backus-Naur Form) Most Programming languages use the BNF notation to describe its syntax It is less ambiguous than English It is a generator technique. It defined how to construct, or generate, all possible syntactically valid strings of a language. It is a recursive technique ::= | ::= 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 ::= | ::= 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0

8 Understanding Recursion To understand recursion we need to understand stacks Each time a function A calls a function B the status of A is stored in the run-time stack. When the function B returns the status of A is popped from the top of the stack. Let's consider this program void whatIsThis() { char inChar; cin.get(inChar); if (inChar == '\n') cout << '\n'; else { whatIsThis(); cout << inChar; } void whatIsThis() { char inChar; cin.get(inChar); if (inChar == '\n') cout << '\n'; else { whatIsThis(); cout << inChar; }

9 "Exploding" the recursion Instead of imagining as stacks we could also see this as creation of new scopes at each iteration of the recursion void whatIsThis() { char inChar; cin.get(inChar); if (inChar == '\n') cout << '\n'; else { char inChar; { cin.get(inChar); if (inChar == '\n') cout << '\n'; else { cout << inChar; } cout << inChar; } void whatIsThis() { char inChar; cin.get(inChar); if (inChar == '\n') cout << '\n'; else { char inChar; { cin.get(inChar); if (inChar == '\n') cout << '\n'; else { cout << inChar; } cout << inChar; }

10 Stacks Is a “pile” or “collection” or “set” of items. Items can only be added to the top Items can only be taken off the top “Last-in-first-out” (”LIFO”) Thing 1 Thing 2 Thing 3 PushPop

11 What is a Stack? A data structure for storing items which are to be accessed in last-in first-out order (LIFO). A data structure for storing items which are to be accessed in last-in first-out order (LIFO).

12 Thing 1 PUSH A data structure for storing items which are to be accessed in last-in first-out order (LIFO). A data structure for storing items which are to be accessed in last-in first-out order (LIFO). What is a Stack?

13 Thing 1 Thing 2 PUSH What is a Stack? A data structure for storing items which are to be accessed in last-in first-out order (LIFO). A data structure for storing items which are to be accessed in last-in first-out order (LIFO).

14 Thing 1 pop What is a Stack? A data structure for storing items which are to be accessed in last-in first-out order (LIFO). A data structure for storing items which are to be accessed in last-in first-out order (LIFO).

15 Thing 1 Thing 2 PUSH What is a Stack? A data structure for storing items which are to be accessed in last-in first-out order (LIFO). A data structure for storing items which are to be accessed in last-in first-out order (LIFO).

16 Thing 1 Thing 2 Thing 3 PUSH What is a Stack? A data structure for storing items which are to be accessed in last-in first-out order (LIFO). A data structure for storing items which are to be accessed in last-in first-out order (LIFO).

17 Thing 1Thing 2 pop What is a Stack? A data structure for storing items which are to be accessed in last-in first-out order (LIFO). A data structure for storing items which are to be accessed in last-in first-out order (LIFO).

18 Thing 1 pop What is a Stack? A data structure for storing items which are to be accessed in last-in first-out order (LIFO). A data structure for storing items which are to be accessed in last-in first-out order (LIFO).

19 pop What is a Stack? A data structure for storing items which are to be accessed in last-in first-out order (LIFO). A data structure for storing items which are to be accessed in last-in first-out order (LIFO).

20 The Activation Stack The white box represents the computers memory. The algorithm gets the first frame at the bottom of the stack. Variables which are used within a module reside in that module’s stack frame. Algo var1 var2var3

21 Algo var1var2var3 Proc_1 this_varthat_var Adding Modules to the Stack When main calls a module, the module gets its own frame “pushed” on the stack. The module’s variables live in that new frame. ONLY ONLY the top frame is active. All frames underneath it are stopped.

22 Proc_1 this_varthat_var Algo var1var2var3 Removing modules from the stack When the module completes its instructions, it’s frame is “popped” off the stack and all of its data dies. To survive, they must actually be stored in a frame that still exists (passed back).

23 How In Parameters Work In formal parameters get a copy of the matching actual parameter. In the algorithm: Proc_One (this_var) In the module: procedure Proc_One(this_one in num)

24 Proc_One this_one 4 Algo 4 How In Parameters Work In formal parameters get a copy of the matching actual parameter. this_var that_var other_var 7 9 4

25 How In/Out Parameters Work In/out formal parameters act as a reference to the matching actual parameter. Reading and writing are allowed. In the algorithm: Proc_One (this_var) In the module: procedure Proc_One(this_one in/out num)

26 Algo 7 Proc_One this_one How In/Out Parameters Work In/out formal parameters act as a reference to the matching actual parameter. Reading and writing are allowed. R this_one <- 7 this_one < this_var that_var other_var Print(this_one) 1

27 How Out Parameters Work Out formal parameters act as a reference to the matching actual parameter. Writing is only allowed at first. After writing, reading is also allowed. In the algorithm: Proc_One (this_var) In the module: procedure Proc_One(this_one out num)

28 How Out Parameters Work Out formal parameters act as a reference to the matching actual parameter. Writing is only allowed at first. After writing, reading is also allowed. Proc_One this_one R this_one <- 8 8 Algo this_var that_var other_var

29 Stack Trace Example procedure juggle (x isoftype in num, y isoftype out num, z isoftype in/out num) y <- x + z print (x, y, z) x <- z + 4 z <- x + 2 endprocedure algorithm TraceExample a, b, c isoftype num a <- 1 b <- 2 c <- 3 print(a, b, c) juggle(c, a, b) print(a, b, c) endalgorithm

30 Procedure Juggle(x iot in Num, y iot out Num, z iot in/out Num) y <- x + z print(x,y,z) x <- z + 4 z <- x - 2 endprocedure Output Demo abc Juggle xyz Algorithm Demo a, b, c isoftype num a <- 1 b <- 2 c <- 3 print(a,b,c) juggle(c,a,b) print(a,b,c) endalgorithm R R 6 5 4

31 Recursive Functions Like mathematical definitions, functions can be recursive Direct recursion: Occurs when a function is called in its own body Indirect recursion: Occurs when one function initiates a sequence of function invocations that eventually invokes the original func A(int x) {. A(20);. } func A(int x) {. A(20);. } Direct Recursion func A(int x) {. B(20);. } func A(int x) {. B(20);. } func B(int x) {. A(20);. } func B(int x) {. A(20);. } Indirect Recursion

32 A Recursive Procedure Problem: Count from N to 10. procedure CountToTen (/* in */ int n) { if (count <= 10) then { print (count)// work CountToTen (count + 1)// recurse }//endif }//endprocedure CountToTen Call the procedure CountToTen (7)

33 Tracing The Recursion To keep track of recursive execution, do what a computer does: maintain information on an activation stack. Each stack frame contains : Module identifier and variables Any unfinished business ModuleID: Data values Unfinished business

34 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=7

35 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=7 7

36 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=7 7

37 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=7 7 CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen

38 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count= CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen

39 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count= CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen

40 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count= CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=9

41 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count= CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=9

42 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count= CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=9

43 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count= CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=9 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=10

44 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count= CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=9 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=10

45 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count= CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=9 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=10

46 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count= CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=9 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=10 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=11

47 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count= CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=9 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=10

48 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count= CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=9

49 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count= CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen

50 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=

Return to the algorithm.

52 Reversing the Work and Recursion Problem: Count from 10 to N. procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen Now the work will happen as the frames pop off the stack!

53 procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen CountToTen: count=7

54 procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen CountToTen: count=7

55 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=7 CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen

56 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=7 CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen

57 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=7 CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen CountToTen: count=9

58 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=7 CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen CountToTen: count=9

59 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=7 CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=9 procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen CountToTen: count=10

60 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=7 CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=9 procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen CountToTen: count=10

61 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=7 CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=9 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=10 procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen CountToTen: count=11

62 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=7 10 CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=9 procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen CountToTen: count=10

63 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=7 10 CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count=9 procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen CountToTen: count=10

64 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count= CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen CountToTen: count=9

65 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count= CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen CountToTen: count=9

66 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count= CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen

67 procedure CountToTen (count iot in Num) if (count <= 10) then print (count) // work CountToTen (count + 1) // recurse endif endprocedure //CountToTen CountToTen: count= CountToTen: count=8 procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen

68 procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen CountToTen: count=

69 procedure CountToTen (count iot in Num) if (count <= 10) then CountToTen (count + 1) // recurse print (count) // work endif endprocedure //CountToTen CountToTen: count=

Return to the algorithm.

71 What is Recursion? Recursion is when a function either directly or indirectly makes a call to itself. Recursion is a powerful problem solving tool. Many mathematical functions and algorithms are most easily expressed using recursion.

72 How does it work? Functions are implemented using an internal stack of activation records. The activation record for the currently active function is at the top of the stack. Each time a function is called a new activation record is pushed on the stack. When a function returns, the stack is popped and the activation record of the calling method is on top of the stack.

73 How does it work? The function being called, and whose activation record is being pushed on the stack, can be different from the calling function (e.g., when main calls a function). Or, the function being called can be a different instance of the calling subprogram. Each instance of the function has its own parameters and local variables.

74 Solving Recursive Problems See recursive solutions as two sections: Current Rest N! = N * (N-1)! 7! = 7 * 6! 7! = 7 * (6 * 5 * 4 * 3 * 2 * 1 * 1)

75 Example Many mathematical functions are defined recursively. For example, the factorial function: N!= N * (N-1)! for N>0 0! = 1 l We have defined factorial in terms of a smaller (or simpler) instance of itself. l We must also define a base case or stopping condition.

76 Recursive Function Call A recursive call is a function call in which the called function is the same as the one making the call. In other words, recursion occurs when a function calls itself! We must avoid making an infinite sequence of function calls (infinite recursion).

77 Finding a Recursive Solution Each successive recursive call should bring you closer to a situation in which the answer is known. A case for which the answer is known (and can be expressed without recursion) is called a base case. Each recursive algorithm must have at least one base case, as well as the general (recursive) case

78 General format for many recursive functions if (some condition for which answer is known) // base case solution statement else // general case recursive function call SOME EXAMPLES...

79 Writing a recursive function to find n factorial DISCUSSION The function call Factorial(4) should have value 24, because that is 4 * 3 * 2 * 1. For a situation in which the answer is known, the value of 0! is 1. So our base case could be along the lines of if ( number == 0 ) return 1;

80 Writing a recursive function to find Factorial(n) Now for the general case... The value of Factorial(n) can be written as n * the product of the numbers from (n - 1) to 1, that is, n * (n - 1) *... * 1 or, n * Factorial(n - 1) And notice that the recursive call Factorial(n - 1) gets us “closer” to the base case of Factorial(0).

81 Recursive Function Example: Factorial Problem: calculate n! (n factorial) n! = 1 if n = 0 n! = 1 * 2 * 3 *...* n if n > 0 Recursively: if n = 0, then n! = 1 if n > 0, then n! = n * (n-1)!

82 Factorial Function Int RecFactorial( /* in */ int n) // Calculates n factorial, n! // Precondition: n is a non-negative // integer { if (n <= 0) then return 1 else return n * RecFactorial(n-1) }

83 1 Int RecFactorial(/*in*/int n) 3 { 4 if (n <= 0) then 5 return 1; 6 else 7 return n * RecFactorial(n-1); 8 } main(...) { cout<<(fact(3)); return address n value 33 * fact(2)7 return address n value 22 * fact(1)7 return address n value 11 * fact(0)7 return address n value 01

84 20 return address n value 33 * fact(2) 7 return address n value 22 * fact(1) 7 return address n value 11 * fact(0) 7 return address n value 01 1 * 12 * 13 * 2 returns 6 to main() 1 Int RecFactorial(/*in*/int n) 3 { 4 if (n <= 0) then 5 return 1; 6 else 7 return n * RecFactorial(n-1); 8 } main(...) { cout<<(fact(3));...

85 if (0 = 0) then Fact returns 1 else Fact returns 1 endif endfunction //Fact if (0 = 0) then Fact returns 1 else Fact returns 1 endif endfunction //Fact if (1 = 0) then Fact returns 1 else Fact returns 1 * Fact(0) endif endfunction //Fact if (1 = 0) then Fact returns 1 else Fact returns 1 * Fact(0) endif endfunction //Fact if (2 = 0) then Fact returns 1 else Fact returns 2 * Fact(1) endif endfunction //Fact if (2 = 0) then Fact returns 1 else Fact returns 2 * Fact(1) endif endfunction //Fact if (3 = 0) then Fact returns 1 else Fact returns 3 * Fact(2) endif endfunction //Fact if (3 = 0) then Fact returns 1 else Fact returns 3 * Fact(2) endif endfunction //Fact algorithm Test ans <- Fact(3) endalgorithm algorithm Test ans <- Fact(3) endalgorithm

86 Tracing Details function RecFactorial (2) if (2 <= 0) then RecFactorial returns 1 else return 2 * RecFactorial(1) function RecFactorial (2) if (2 <= 0) then RecFactorial returns 1 else return 2 * RecFactorial(1) 1. Actual parameters stored on the stack 2. Recursive call to RecFactorial 4. Unfinished Business 3. Create a new Stack Frame 5. Return value and release stack frame

87 Activation Stack for Factorial Call the function: answer <- Fact(5) Main Algorithm: Unfinished: answer <- Fact (5)

88 Activation Stack for Factorial Main Algorithm: Unfinished: answer <- Fact (5) Fact. 1st: N=5, Unfinished: 5*Fact(4)

89 Activation Stack for Factorial Main Algorithm: Unfinished: answer <- Fact (5) Fact. 1st: N=5, Unfinished: 5*Fact(4) Fact. 2nd: N=4, Unfinished: 4*Fact(3)

90 Activation Stack for Factorial Main Algorithm: Unfinished: answer <- Fact (5) Fact. 1st: N=5, Unfinished: 5*Fact(4) Fact. 2nd: N=4, Unfinished: 4*Fact(3) Fact. 3rd: N=3, Unfinished: 3*Fact(2)

91 Activation Stack for Factorial Main Algorithm: Unfinished: answer <- Fact (5) Fact. 1st: N=5, Unfinished: 5*Fact(4) Fact. 2nd: N=4, Unfinished: 4*Fact(3) Fact. 3rd: N=3, Unfinished: 3*Fact(2) Fact. 4th: N=2, Unfinished: 2*Fact(1)

92 Activation Stack for Factorial Main Algorithm: Unfinished: answer <- Fact (5) Fact. 1st: N=5, Unfinished: 5*Fact(4) Fact. 2nd: N=4, Unfinished: 4*Fact(3) Fact. 3rd: N=3, Unfinished: 3*Fact(2) Fact. 4th: N=2, Unfinished: 2*Fact(1) Fact. 5th: N=1, Unfinished: 1*Fact(0)

93 Activation Stack for Factorial Main Algorithm: Unfinished: answer <- Fact (5) Fact. 1st: N=5, Unfinished: 5*Fact(4) Fact. 2nd: N=4, Unfinished: 4*Fact(3) Fact. 3rd: N=3, Unfinished: 3*Fact(2) Fact. 4th: N=2, Unfinished: 2*Fact(1) Fact. 5th: N=1, Unfinished: 1*Fact(0) Fact. 6th: N=0, Finished: returns 1

94 Activation Stack for Factorial Main Algorithm: Unfinished: answer <- Fact (5) Fact. 1st: N=5, Unfinished: 5*Fact(4) Fact. 2nd: N=4, Unfinished: 4*Fact(3) Fact. 3rd: N=3, Unfinished: 3*Fact(2) Fact. 4th: N=2, Unfinished: 2*Fact(1) Fact. 5th: N=1, Finished: returns 1*1

95 Activation Stack for Factorial Main Algorithm: Unfinished: answer <- Fact (5) Fact. 1st: N=5, Unfinished: 5*Fact(4) Fact. 2nd: N=4, Unfinished: 4*Fact(3) Fact. 3rd: N=3, Unfinished: 3*Fact(2) Fact. 4th: N=2, Finished: returns 2*1

96 Activation Stack for Factorial Main Algorithm: Unfinished: answer <- Fact (5) Fact. 1st: N=5, Unfinished: 5*Fact(4) Fact. 2nd: N=4, Unfinished: 4*Fact(3) Fact. 3rd: N=3, Finished: returns 3*2

97 Activation Stack for Factorial Main Algorithm: Unfinished: answer <- Fact (5) Fact. 1st: N=5, Unfinished: 5*Fact(4) Fact. 2nd: N=4, Finished: returns 4*6

98 Activation Stack for Factorial Main Algorithm: Unfinished: answer <- Fact (5) Fact. 1st: N=5, Finished: returns 5*24

99 Activation Stack for Factorial Main Algorithm: Finished: answer <- 120

100 Exponentiation base exponent e.g. 5 3 Could be written as a function Power(base, exp)

101 Can we write it recursively? b e = b * b (e-1) What’s the limiting case? When e = 0 we have b 0 which always equals? 1 LB

102 Another Recursive Function function Power returnsa Num(base, exp isoftype inNum) // Computes the value of Base Exp // Pre: exp is a non-negative integer if (exp = 0) then Power returns 1 else Power returns base * Power(base, exp-1) endif endfunction //Power Power x N = x * x N-1 for N>0 x 0 = 1

103 Function Power returnsa Num (base, exp isoftype in Num) //Computes the value of Base Exp //Preconditions: exp is a non-negative integer if(exp = 0 ) then Power returns 1 else Power returns (base * Power(base, exp – 1)) endif endfunction //Power Activations Stack Example Algo: total <- Power(3,4) Power base = 3 exp = 4 3 *Power(3,3)Power base = 3 exp = 3 3 *Power(3,2)Power base = 3 exp = 2 3 *Power(3,1)Power base = 3 exp = 1 3 *Power(3,0) 1 Power base = 3 exp = 0 Finished: 1 Total <

104 In the year 1202 a distinguished Italian mathematician, Leonardo of Pisa, also known as Fibonacci, published the following puzzle: The Man… The Man… ( )

105 The Puzzle A man has an infant male-female pair of rabbits in a hutch entirely surrounded by a wall. We wish to know how many rabbits can be bred from this pair in one year, if the nature of the rabbits is such that every month they breed one other male-female pair which begins to breed in the second month after their birth. Assume that no rabbits die during the year.

106 A Tree Diagram for Fibonacci’s Puzzle

107 Observations The number of rabbits at the beginning of any month equals the number of rabbits of the previous month plus the number of new pairs. The number of new pairs at the beginning of a month equals the number of pairs two months ago. One gets the sequence: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …233

108 snails nautilus other sea shells The Occurrence in Nature…

109 Fibonacci Numbers & Branching Plants

110 Fibonacci Fingers? 2 hands each of which has... 5 fingers, each of which has... 3 parts separated by... 2 knuckles

111 Fibonacci Numbers & Pine Cones 13 counterclockwise 8 clockwise

112 Fibonacci Numbers & Sunflowers 34 counterclockwise 55 clockwise

113 Fibonacci sequence Recursive definition f(0) = 1 f(1) = 1 f(n) = f(n-1) + f(n-2)

114 Fibonacci Number Sequence if n = 1, then Fib(n) = 1 if n = 2, then Fib(n) = 1 if n > 2, then Fib(n) = Fib(n-2) + Fib(n-1) Numbers in the series: 1, 1, 2, 3, 5, 8, 13, 21, 34,... A More Complex Recursive Function

115 Fibonacci Sequence Function function Fib returnsaNum (n iot inNum) // Calculates the nth Fibonacci number // Precondition: N is a positive integer if ((n = 1) OR (n = 2)) then Fib returns 1 else Fib returns Fib(n-2) + Fib(n-1) endif endfunction //Fibonacci

116 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5)

117 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5) Fib(5): Fib returns Fib(3) + Fib(4)

118 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5) Fib(5): Fib returns Fib(3) + Fib(4) Fib(3): Fib returns Fib(1) + Fib(2)

119 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5) Fib(5): Fib returns Fib(3) + Fib(4) Fib(3): Fib returns Fib(1) + Fib(2) Fib(1): Fib returns 1

120 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5) Fib(5): Fib returns Fib(3) + Fib(4) Fib(3): Fib returns 1 + Fib(2)

121 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5) Fib(5): Fib returns Fib(3) + Fib(4) Fib(3): Fib returns 1 + Fib(2) Fib(2): Fib returns 1

122 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5) Fib(5): Fib returns Fib(3) + Fib(4) Fib(3): Fib returns 1 + 1

123 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5) Fib(5): Fib returns 2 + Fib(4)

124 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5) Fib(5): Fib returns 2 + Fib(4) Fib(4): Fib returns Fib(2) + Fib(3)

125 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5) Fib(5): Fib returns 2 + Fib(4) Fib(4): Fib returns Fib(2) + Fib(3) Fib(2): Fib returns 1

126 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5) Fib(5): Fib returns 2 + Fib(4) Fib(4): Fib returns 1 + Fib(3)

127 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5) Fib(5): Fib returns 2 + Fib(4) Fib(4): Fib returns 1 + Fib(3) Fib(3): Fib returns Fib(1) + Fib(2)

128 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5) Fib(5): Fib returns 2 + Fib(4) Fib(4): Fib returns 1 + Fib(3) Fib(3): Fib returns Fib(1) + Fib(2) Fib(1): Fib returns 1

129 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5) Fib(5): Fib returns 2 + Fib(4) Fib(4): Fib returns 1 + Fib(3) Fib(3): Fib returns 1 + Fib(2)

130 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5) Fib(5): Fib returns 2 + Fib(4) Fib(4): Fib returns 1 + Fib(3) Fib(3): Fib returns 1 + Fib(2) Fib(2): Fib returns 1

131 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5) Fib(5): Fib returns 2 + Fib(4) Fib(4): Fib returns 1 + Fib(3) Fib(3): Fib returns 1 + 1

132 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5) Fib(5): Fib returns 2 + Fib(4) Fib(4): Fib returns 1 + 2

133 Tracing with Multiple Recursive Calls Main Algorithm: answer <- Fib(5) Fib(5): Fib returns 2 + 3

134 Tracing with Multiple Recursive Calls Main Algorithm: answer <- 5

135 Fib(5) Fib(3) Fib(4) Fib(3)Fib(2) Fib(1) Fib(0)Fib(1)Fib(0)Fib(2)Fib(1) Fib(0) 15 calls to Fib to find the 5th Fibonacci number!!!

136 Rules of Recursion First two fundamental rules of recursion: Base cases: Always have at least one case that can be solved without using recursion. Make progress: Any recursive call must make progress towards the base case.

137 Rules of Recursion Third fundamental rule of recursion: “You gotta believe”: Always assume that the recursive call works.

138 Rules of Recursion Fourth fundamental rule of recursion: Compound interest rule: Never duplicate work by solving the same instance of a problem in separate recursive calls.

139 Towers of Hanoi Many, many years ago, in a distant part of the Orient -- in the Vietnamese city of Hanoi -- the Emperor devised a puzzle, declaring that its solver could have the job of wise person. The puzzle consisted of N disks and three poles: A (the source), B (the destination), and C (the spare)

140 Towers of Hanoi BCA

141 Towers of Hanoi BCA

142 Towers of Hanoi BCA

143 Towers of Hanoi BCA

144 Towers of Hanoi BCA

145 Towers of Hanoi BCA

146 Towers of Hanoi BCA

147 Towers of Hanoi BCA

148 Towers of Hanoi A pseudocode description of the solution is: Towers(Count, Source, Dest, Spare) if (Count is 1) Move the disk directly from Source to Dest else { Solve Towers(Count-1, Source, Spare, Dest) Solve Towers(1, Source, Dest, Spare) Solve Towers(Count-1, Spare, Dest, Source) }

149 Towers of Hanoi void solveTowers( int count, char source, char dest, char spare){ if (count == 1) cout<<“Move disk from pole “ << source << " to pole " << destination <<endl; else { towers(count-1, source, spare, destination); towers(1, source, destination, spare); towers(count-1, spare, destination, source); }//end if }//end solveTowers

150 Pascal Triangle (Is this recursive?)

151 Pascal Triangle

152 Pascal Triangle The combinations of n items taken r at a time. For example: three items: a b c taken 2 at a time: ab ac bc Thus there are three combinations of 3 items taken 2 at a time. In General: C(n,r) = n!/(r!(n-r))! Obviously you can calculate C(n,r) using factorials.

153 Pascal Triangle Most of you know this leads to Pascals Triangle: n This can also be written: r n

154 Pascal Triangle C(n,r) occurs in many places in mathematics, statistics, chemistry, physics and business. Note from Pascal's Triangle that: C(n,r) = C(n-1, r-1) + C(n-1,r) This leads to the recurrence for nonnegative r and n, C(n,r) = | 1 if r = 0 or r = n, | 0 if r > n, | C(n-1, r-1) + C(n-1,r) otherwise.

155 Pascal Triangle This immediately leads to the recursive function for combinations: int C(int n, int r) { if((r == 0) || (r == n)) return 1; else if(r > n) return 0; else return C(n-1, r-1) + C(n-1, r); }

156 Recall that... Recursion occurs when a function calls itself (directly or indirectly). Recursion can be used in place of iteration (looping). Some functions can be written more easily using recursion.

157 What is the value of rose(25) ? int rose (int n) { if ( n == 1 ) // base case return 0; else // general case return ( 1 + rose ( n / 2 ) ); }

158 Finding the value of rose(25) rose(25) the original call = 1 + rose(12) first recursive call = 1 + ( 1 + rose(6) ) second recursive call = 1 + ( 1 + ( 1 + rose(3) ) ) third recursive call = 1 + ( 1 + ( 1 + (1 + rose(1) ) ) ) fourth recursive call = = 4

159 Writing recursive functions There must be at least one base case, and at least one general (recursive) case. The general case should bring you “closer” to the base case. The parameter(s) in the recursive call cannot all be the same as the formal parameters in the heading. Otherwise, infinite recursion would occur. In function rose( ), the base case occurred when (n == 1) was true. The general case brought us a step closer to the base case, because in the general case the call was to rose(n/2), and the argument n/2 was closer to 1 (than n was).

160 Recursion for Repetition while ( ) while ( ) void recWhile() { if ( ) recWhile(); } void recWhile() { if ( ) recWhile(); } void anotherRecWhile() { if ( ) AnotherRecWhile(); ; } void anotherRecWhile() { if ( ) AnotherRecWhile(); ; } An arbitrary while loop An equivalent recursive function …Infinite recursion

161 Three-Question Method of verifying recursive functions Base-Case Question: Is there a nonrecursive way out of the function? Smaller-Caller Question: Does each recursive function call involve a smaller case of the original problem leading to the base case? General-Case Question: Assuming each recursive call works correctly, does the whole function work correctly?

162 Guidelines for writing recursive functions 1. Get an exact definition of the problem to be solved. 2. Determine the size of the problem to be solved on this call to the function. On the initial call, the size of the whole problem is expressed by the actual parameter(s). 3. Identify and solve the base case(s) which have non- recursive solutions. 4. Identify and solve the general case(s) in terms of smaller (recursive) cases of the same problem.

163 struct ListType { int length ; // number of elements in the list int info[ MAX_ITEMS ] ; } ; ListType list ; struct ListType

164 Recursive function to determine if value is in list PROTOTYPE bool ValueInList( ListType list, int value, int startIndex ) ; Already searched Needs to be searched list[0] [1] [startIndex] [length -1] index of current element to examine

bool ValueInList ( ListType list, int value, int startIndex ) // Searches list for value between positions startIndex // and list.length-1 // Pre: list.info[ startIndex ].. list.info[ list.length - 1 ] // contain values to be searched // Post: Function value = // ( value exists in list.info[ startIndex ].. list.info[ list.length - 1 ] ) { if ( list.info[startIndex] == value )// one base case return true ; else if (startIndex == list.length -1 ) // another base case return false ; else // general case return ValueInList( list, value, startIndex + 1 ) ; } 165

166 “Why use recursion?” Many solutions could have been written without recursion, by using iteration instead. The iterative solution uses a loop, and the recursive solution uses an if statement. However, for certain problems the recursive solution is the most natural solution. This often occurs when pointer variables are used.

167 struct NodeType { int info ; NodeType* next ; } class SortedType { public :... // member function prototypes private : NodeType* listData ; } ; struct ListType

168 RevPrint(listData); A B C D E FIRST, print out this section of list, backwards THEN, print this element listData

169 Base Case and General Case A base case may be a solution in terms of a “smaller” list. Certainly for a list with 0 elements, there is no more processing to do. Our general case needs to bring us closer to the base case situation. That is, the number of list elements to be processed decreases by 1 with each recursive call. By printing one element in the general case, and also processing the smaller remaining list, we will eventually reach the situation where 0 list elements are left to be processed. In the general case, we will print the elements of the smaller remaining list in reverse order, and then print the current pointed to element.

170 Using recursion with a linked list void RevPrint ( NodeType* listPtr ) // Pre: listPtr points to an element of a list. // Post: all elements of list pointed to by listPtr have been printed // out in reverse order. { if ( listPtr != NULL )// general case { RevPrint ( listPtr-> next ) ; // process the rest cout info << endl ; // then print this element } // Base case : if the list is empty, do nothing } 170

171 Function BinarySearch( ) BinarySearch takes sorted array info, and two subscripts, fromLoc and toLoc, and item as arguments. It returns false if item is not found in the elements info[fromLoc…toLoc]. Otherwise, it returns true. BinarySearch can be written using iteration, or using recursion.

172 found = BinarySearch(info, 25, 0, 14 ); item fromLoc toLoc indexes info NOTE: denotes element examined

// Recursive definition bool BinarySearch ( ItemType info[ ], ItemType item, int fromLoc, int toLoc ) // Pre: info [ fromLoc.. toLoc ] sorted in ascending order // Post: Function value = ( item in info [ fromLoc.. toLoc] ) {int mid ; if ( fromLoc > toLoc ) // base case -- not found return false ; else { mid = ( fromLoc + toLoc ) / 2 ; if ( info [ mid ] == item ) // base case-- found at mid return true ; else if ( item < info [ mid ] ) // search lower half return BinarySearch ( info, item, fromLoc, mid-1 ) ; else // search upper half return BinarySearch( info, item, mid + 1, toLoc ) ; } } 173

174 When a function is called... A transfer of control occurs from the calling block to the code of the function. It is necessary that there be a return to the correct place in the calling block after the function code is executed. This correct place is called the return address. When any function is called, the run-time stack is used. On this stack is placed an activation record (stack frame) for the function call.

175 Stack Activation Frames The activation record stores the return address for this function call, and also the parameters, local variables, and the function’s return value, if non-void. The activation record for a particular function call is popped off the run-time stack when the final closing brace in the function code is reached, or when a return statement is reached in the function code. At this time the function’s return value, if non-void, is brought back to the calling block return address for use there.

// Another recursive function int Func ( int a, int b ) // Pre: a and b have been assigned values // Post: Function value = ?? { int result; if ( b == 0 ) // base case result = 0; else if ( b > 0 ) // first general case result = a + Func ( a, b - 1 ) ) ; // instruction 50 else // second general case result = Func ( - a, - b ) ; // instruction 70 return result; } 176

177 FCTVAL ? result ? b 2 a 5 Return Address 100 Run-Time Stack Activation Records x = Func(5, 2); // original call is instruction 100 original call at instruction 100 pushes on this record for Func(5,2)

178 FCTVAL ? result ? b 1 a 5 Return Address 50 FCTVAL ? result 5+Func(5,1) = ? b 2 a 5 Return Address 100 record for Func(5,2) call in Func(5,2) code at instruction 50 pushes on this record for Func(5,1) Run-Time Stack Activation Records x = Func(5, 2); // original call at instruction 100

179 FCTVAL ? result ? b 0 a 5 Return Address 50 FCTVAL ? result 5+Func(5,0) = ? b 1 a 5 Return Address 50 FCTVAL ? result 5+Func(5,1) = ? b 2 a 5 Return Address 100 record for Func(5,2)record for Func(5,1) call in Func(5,1) code at instruction 50 pushes on this record for Func(5,0) Run-Time Stack Activation Records x = Func(5, 2); // original call at instruction 100

180 FCTVAL 0 result 0 b 0 a 5 Return Address 50 FCTVAL ? result 5+Func(5,0) = ? b 1 a 5 Return Address 50 FCTVAL ? result 5+Func(5,1) = ? b 2 a 5 Return Address 100 record for Func(5,2) record for Func(5,1) record for Func(5,0) is popped first with its FCTVAL Run-Time Stack Activation Records x = Func(5, 2); // original call at instruction 100

181 FCTVAL 5 result 5+Func(5,0) = 5+ 0 b 1 a 5 Return Address 50 FCTVAL ? result 5+Func(5,1) = ? b 2 a 5 Return Address 100 record for Func(5,2)record for Func(5,1) is popped next with its FCTVAL Run-Time Stack Activation Records x = Func(5, 2); // original call at instruction 100

182 FCTVAL 10 result 5+Func(5,1) = 5+5 b 2 a 5 Return Address 100 Run-Time Stack Activation Records x = Func(5, 2); // original call at line 100 record for Func(5,2) is popped last with its FCTVAL

183 Show Activation Records for these calls x = Func( - 5, - 3 ); x = Func( 5, - 3 ); What operation does Func(a, b) simulate?

184 Tail Recursion The case in which a function contains only a single recursive call and it is the last statement to be executed in the function. Tail recursion can be replaced by iteration to remove recursion from the solution as in the next example.

// USES TAIL RECURSION bool ValueInList ( ListType list, int value, int startIndex ) // Searches list for value between positions startIndex // and list.length-1 // Pre: list.info[ startIndex ].. list.info[ list.length - 1 ] // contain values to be searched // Post: Function value = // ( value exists in list.info[ startIndex ].. list.info[ list.length - 1 ] ) { if ( list.info[startIndex] == value )// one base case return true ; else if (startIndex == list.length -1 ) // another base case return false ; else // general case return ValueInList( list, value, startIndex + 1 ) ; } 185

// ITERATIVE SOLUTION bool ValueInList ( ListType list, int value, int startIndex ) // Searches list for value between positions startIndex // and list.length-1 // Pre: list.info[ startIndex ].. list.info[ list.length - 1 ] // contain values to be searched // Post: Function value = // ( value exists in list.info[ startIndex ].. list.info[ list.length - 1 ] ) { bool found = false ; while ( !found && startIndex < list.length ) { if ( value == list.info[ startIndex ] ) found = true ; elsestartIndex++ ; } return found ; } 186

187 When to Use Recursion If the problem is recursive in nature therefore it is likely the a recursive algorithm will be preferable and will be less complex If both recursive and non-recursive algorithm have the same complexity it is likely that a non-recursive version will perform better and therefore should be preferred A third alternative in some problems is to use table- driven techniques  Sometimes we know that we will not use the only a few values of a particular function  If this is the case an implementation using a table would probably suffice and the performance will be better int factorial[8] = {1, 1, 2, 6, 24, 120, 720, 5040};

188 Use a recursive solution when: The depth of recursive calls is relatively “shallow” compared to the size of the problem. The recursive version does about the same amount of work as the nonrecursive version. The recursive version is shorter and simpler than the nonrecursive solution. SHALLOW DEPTH EFFICIENCY CLARITY