Recursion. What is recursion? smaller version Sometimes, the best way to solve a problem is by solving a smaller version of the exact same problem first.

Slides:



Advertisements
Similar presentations
Introduction to Recursion and Recursive Algorithms
Advertisements

Factorial Recursion stack Binary Search Towers of Hanoi
Lesson 19 Recursion CS1 -- John Cole1. Recursion 1. (n) The act of cursing again. 2. see recursion 3. The concept of functions which can call themselves.
Recursion Rosen 5 th ed., § Recursion Sometimes, defining an object explicitly might be difficult.Sometimes, defining an object explicitly might.
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.
Unit 181 Recursion Definition Recursive Methods Example 1 How does Recursion work? Example 2 Problems with Recursion Infinite Recursion Exercises.
Programming with Recursion
Recursion.
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.
Starting Out with C++: Early Objects 5/e © 2006 Pearson Education. All Rights Reserved Starting Out with C++: Early Objects 5 th Edition Chapter 14 Recursion.
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.
Prof. S.M. Lee Department of Computer Science. Answer:
Chapter 3: Recursive Algorithms
Recursion CS Goals Discuss recursion as another form of repetition Do the following tasks, given a recursive routine Determine whether the routine.
Copyright © 2009 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Chapter 19: Recursion.
1 C++ Plus Data Structures Nell Dale Chapter 7 Programming with Recursion Slides by Sylvia Sorkin, Community College of Baltimore County - Essex Campus.
Nirmalya Roy School of Electrical Engineering and Computer Science Washington State University Cpt S 122 – Data Structures Recursion Review.
Copyright © 2014, 2008 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Starting Out with C++ Early Objects Eighth Edition by Tony Gaddis,
Chapter 14: Recursion Starting Out with C++ Early Objects
Recursion. Basic problem solving technique is to divide a problem into smaller subproblems These subproblems may also be divided into smaller subproblems.
CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem.
Prof. S.M. Lee Department of Computer Science.
1 Decrease-and-Conquer Approach Lecture 06 ITS033 – Programming & Algorithms Asst. Prof. Dr. Bunyarit Uyyanonvara IT Program, Image and Vision Computing.
12-CRS-0106 REVISED 8 FEB 2013 KUG1C3 Dasar Algoritma dan Pemrograman.
CS 1704 Introduction to Data Structures and Software Engineering.
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.
Chapter 9: Recursion1 CHAPTER 9 RECURSION. Recursion  Concept of recursion  A recursive: Benefit and Cost  Comparison : Iterative and recursive functions.
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.
Recursion CS 3358 – Data Structures. Big Picture Our objective is to write a recursive program and convince ourselves it is correct with the minimum amount.
Stephen P. Carl - CS 2421 Recursion Reading : Chapter 4.
1 Programming with Recursion Slides by Sylvia Sorkin, Community College of Baltimore County - Essex Campus and Robert Moyer, Montgomery County Community.
CIS 068 Welcome to CIS 068 ! Stacks and Recursion.
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++
Recursion CS 302 – Data Structures Chapter 7. What is recursion? smaller A technique that solves problem by solving smaller versions of the same problem!
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.
Recursion. What is recursion? Rules of recursion Mathematical induction The Fibonacci sequence Summary Outline.
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.
Recursion.
1 Lecture 3 Part 2 Storage Classes, Scope, and Recursion.
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.
Lecture #3 Analysis of Recursive Algorithms
12-CRS-0106 REVISED 8 FEB 2013 KUG1C3 Dasar Algoritma dan Pemrograman.
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.
Recursion Powerful Tool
Programming with Recursion
Chapter Topics Chapter 16 discusses the following main topics:
Chapter 19: Recursion.
Chapter 15 Recursion.
RECURSION.
Decrease-and-Conquer Approach
Chapter 15 Recursion.
Java 4/4/2017 Recursion.
Programming with Recursion
Recursion "To understand recursion, one must first understand recursion." -Stephen Hawking.
Applied Algorithms (Lecture 17) Recursion Fall-23
Recursion Data Structures.
Module 1-10: Recursion.
Yan Shi CS/SE 2630 Lecture Notes
Recursion.
Presentation transcript:

Recursion

What is recursion? smaller version Sometimes, the best way to solve a problem is by solving a smaller version of the exact same problem first smaller problem Recursion is a technique that solves a problem by solving a smaller problem of the same type

Recursion More than programming technique: a way of describing, defining, or specifying things. a way of designing solutions to problems (divide and conquer).

Basic Recursion 1. Base cases: Always have at least one case that can be solved without using recursion. 2. Make progress: Any recursive call must make progress toward a base case.

Mathematical Examples Fibonacci Sequence: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, … Fibonacci Function: Fib(0) = 1 // base case Fib(1) = 1 // base case Fib(n) = Fib(n-1) + Fib(n-2) // recursive call, n>1 Unlike most recursive algorithms:  two base cases, not just one  two recursive calls, not just one

Euclid's Algorithm In about 300 BC, Euclid wrote an algorithm to calculate the greatest common divisor (GCD) of two numbers x and y where (x < y). This can be stated as: 1. Divide y by x with remainder r. 2. Replace y by x, and x with r. 3. Repeat step 1 until r is zero. When this algorithm terminates, y is the highest common factor.

GCD(34017, 16966) Euclid's algorithm works as follows: 34,017/16,966 produces a remainder 85 16,966/85 produces a remainder 51 85/51 produces a remainder 34 51/34 produces a remainder 17 34/17 produces a remainder 0 The highest common divisor of 34,017 and 16,966 is 17.

Key Elements of Euclid's Algorithm : Simple arithmetic operations (calculating the remainder after division) Comparison of a number against 0 (test) Ability to repeatedly execute the same set of instructions (loop) Any computer programming language has these basic elements.

Factorial Sequence Factorial Function factorial(0) = 1 factorial(n) = n * factorial(n-1) [for n>0] Compute factorial(3).

Factorial Sequence Factorial Function factorial(0) = 1 factorial(n) = n * factorial(n-1) [for n>0] Compute factorial(3). factorial(3) = 3 * factorial(2) = 3 * ( 2 * factorial(1) ) = 3 * ( 2 * ( 1 * factorial(0) ) = 3 * ( 2 * ( 1 * 1 ) )) = 6

Coding the factorial function Recursive Implementation int factorial(int n) { if (n==0) // base case return 1; else return n * factorial(n-1); }

Recursive Call Stack

Recursion vs. Iteration Recursion is based upon calling the same function over and over. Iteration simply `jumps back' to the beginning of the loop. A function call is often more expensive than a jump.

Recursion vs. Iteration Iteration can be used in place of recursion An iterative algorithm uses a looping construct A recursive algorithm uses a branching structure Recursive solutions are often less efficient, in terms of both time and space, than iterative solutions Recursion can simplify the solution of a problem, often resulting in shorter, more easily understood source code

Recursion to Iteration Conversion Most recursive algorithms can be translated by a fairly mechanical procedure into iterative algorithms. Sometimes this is very straightforward most compilers detect a special form of recursion, called tail recursion, and automatically translate into iteration automatically. Sometimes, the translation is more involved May require introducing an explicit stack with which to `fake' the effect of recursive calls.

Coding Factorial Function Iterative implementation int factorial(int n) { int fact = 1; for(int count = 2; count <= n; count++) fact = fact * count; return fact; }

Combinations: n choose k () Given n things, how many different sets of size k can be chosen? n n-1 n-1 = +, 1 < k < n(recursive solution) k k k-1 n n! =, 1 < k < n(closed-form solution) k k!(n-k)! with base cases: n = n (k = 1), = 1 (k = n) 1 n Pascal’s Triangle

int combinations(int n, int k) { if(k == 1) // base case 1 return n; else if (n == k) // base case 2 return 1; else return(combinations(n-1, k) + combinations(n-1, k-1)); } Combinations: n choose k

Combinations:

Writing a Recursive Function Determine the base case(s) (the one for which you know the answer) Determine the general case(s) (the one where the problem is expressed as a smaller version of itself) Verify the algorithm (use the "Three-Question-Method")

Three-Question Method The Base-Case Question: Is there a non-recursive way out of the function, and does the routine work correctly for this "base" case? The Smaller-Caller Question: Does each recursive call to the function involve a smaller case of the original problem, leading inescapably to the base case? The General-Case Question: Assuming that the recursive call(s) work correctly, does the whole function work correctly?

Euclid's Algorithm Recall: Find greatest common divisor (GCD) of two integers x and y where (x < y): 1. y / x, save remainder r. 2. Replace y by x, and x with r. 3. Repeat until r is zero. When this algorithm terminates, y is the highest common factor.

What is the base case(s)? (1) If first > last, return false (2) If item==info[midPoint], return true What is the general case? if item < info[midPoint] search the first half if item > info[midPoint], search the second half Recursive Binary Search

boolean binarySearch(Item info[], Item item, int first, int last) { int midPoint; if(first > last) // base case 1 return false; else { midPoint = (first + last)/2; if(item < info[midPoint]) return BinarySearch(info, item, first, midPoint-1); else if (item == info[midPoint]) { // base case 2 item = info[midPoint]; return true; } else return binarySearch(info, item, midPoint+1, last); } Recursive Binary Search

Implementing Recursion What happens when a function gets called? int b(int x) { int z,y; ……………… // other statements z = a(x) + y; return z; } int a(int w) { return w+w; }

When a Function is Called An activation record is stored into a stack (run-time or call stack) The computer has to stop executing function b and starts executing function a Since it needs to come back to function b later, it needs to store everything about function b that is going to need (x, y, z, and the place to start executing upon return) Then, x from a is bounded to w from b Control is transferred to function a

After function a is executed, the activation record is popped out of the run-time stack All the old values of the parameters and variables in function b are restored and the return value of function a replaces a(x) in the assignment statement When a Function is Called

When Recursive Function Called Except the fact that the calling and called functions have the same name, there is really no difference between recursive and non-recursive calls int f(int x) { int y; if(x==0) return 1; else { y = 2 * f(x-1); return y+1; }

=f(3) =f(2) =f(1) 2*f(2) 2*f(1) =f(0)

When to Use Recursion When the depth of recursive calls is relatively "shallow" The recursive version does about the same amount of work as the non- recursive version The recursive version is shorter and simpler than the non-recursive solution

Benefits of Recursion Recursive functions are clearer, simpler, shorter, and easier to understand than their non-recursive counterparts. The program directly reflects the abstract solution strategy (algorithm). From a practical software engineering point of view, greatly enhances the cost of maintaining the software.

Disadvantages of Recursion Makes it easier to write simple and elegant programs, but it also makes it easier to write inefficient ones. Use recursion to ensure correctness, not efficiency. My simple, elegant recursive algorithms are inherently inefficient.

Recursive InsertItem (Sorted List) location

What is the base case(s)? If the list is empty, insert item into the empty list If item < location.info, insert item as the first node in the current list What is the general case? Insert(location.next, item) Recursive InsertItem (Sorted List)

void insert(Node node, Item item) { if(node == NULL) || (item < node.getItem()) { // base cases NodeType temp = node; node = new NodeType ; location.setElement(item); location.setNext(temp); } else insert(node.getNext(), item); // general case } void insertItem(Item newItem) { insert(head, newItem); } Recursive InsertItem (Sorted List)

- No "predLoc" pointer is needed for insertion location

 Space: Every invocation of a function call requires:  space for parameters and local variables  space for return address Thus, a recursive algorithm needs space proportional to the number of nested calls to the same function. Recursion Overhead

 Time: The operations involved in calling a function  allocating, and later releasing, local memory  copying values into the local memory for the parameters  branching to/returning from the function All contribute to the time overhead.

Cumulative Affects  If a function has very large local memory requirements, it would be very costly to program it recursively.  Even if there is very little overhead in a single function call, recursive functions often call themselves many times, which can magnify a small individual overhead into a very large cumulative overhead.

Cumulative Affects - Factorial int factorial(int n) { if (n == 0) {return 1;} else {return n * factorial(n-1);} }  Little overhead  only one word of local memory for the parameter n.  However, when we try to compute factorial(20)  21 words of memory are allocated.

Cumulative Affects - Factorial (cont’d) factorial(20) -- allocate 1 word of memory, call factorial(19) -- allocate 1 word of memory, call factorial(18) -- allocate 1 word of memory,. call factorial(2) -- allocate 1 word of memory, call factorial(1) -- allocate 1 word of memory, call factorial(0) -- allocate 1 word of memory, At this point, 21 words of memory and 21 activation records have been allocated.

Recursive Functions int f(int x) { int y; if(x==0) return 1; else { y = 2 * f(x-1); return y+1; }

Iteration as a special case of recursion Iteration is a special case of recursion: void do_loop () { do {... } while (e); } is equivalent to: void do_loop () {... ; if (e) do_loop(); } A compiler can recognize instances of this form of recursion and turn them into loops or simple jumps.

Recursive DeleteItem (Sorted List) location

What is the size factor? The number of elements in the list What is the base case(s)? If item == location->info, delete node pointed by location What is the general case? Delete(location->next, item) Recursive DeleteItem (sorted list)

template void Delete(NodeType * &location, ItemType item) { if(item == location->info)) { NodeType * tempPtr = location; location = location->next; delete tempPtr; } else Delete(location->next, item); } template void SortedType ::DeleteItem(ItemType item) { Delete(listData, item); } Recursive DeleteItem (sorted list) (cont.)

Recursion can be very inefficient is some cases 15

We have seen one form of circularity already in our classes, with a For loop. Int x; For (x=0; x<=10; x++) { cout<<x; }

Problems solving used loops In a for loop, we have a set loop structure which controls the length of the repetition. Many problems solved using loops may be solved using a recursion. In recursion, problems are defined in terms of smaller versions of themselves.

Power function There are recursive definitions for many mathematical problems: The function Power (used to raise the number y to the xth power). Assume x is a non-negative integer: Y^x = 1 if x is 0; otherwise, Y*Y^(x-1)

Power Function 2^3 = 2*2^2 = 2 * 4 = 8 2^2 = 2*2^1 = 2 * 2 = 4 2^1 = 2*2^0= 2 * 1 = 2 2^0 = 1

Factorial Function The factorial function has a natural recursive definition: n!= 1, if n = 0 or if n = 1; otherwise, n! = n * (n - 1)!

For example: 5! = 5*4! = 5*24 4! = 4*3! = 4*6 3! = 3*2! = 3*2 2! = 2*1! = 2*1 1! = 1

Excessive Recursion When a program runs too deep: When a simple loop runs more efficiently: Fibonacci sequence:

Ackermann’s Function “…one of the fastest growing non- primitive recursive functions. Faster growing than any primitive recursive function.” It grows from 0 to 2^65546 in a few breaths.

Basis for Ackermann’s If A(0, n)=n+1, by definition If A(m, 0)=A(m-1, 1) else, A(m, n)=A(m-1, A(m, n-1))… …until A(0, A(1, A(…m-2, n-1)))…back to definition

Example A(2, 2)=A(1, A(2, 1))=A(0, A(1, A(2, 1))) …=A(1, A(2, 1))+1=A(0, A(1, A(2, 0)))+1 …=A(1, A(1, 1))+2=A(0, A(1, A(1, 0))) …=A(1, A(0, 1))+3=A(0, A(0, 0))+5=7!!!

Shortcuts: If A(0, n)=n+1 If A(1, n)=n+2 If A(2, n)=2n+3 If A(3, n)=2^n+3 If A(4, n)=2^(n+3)*2 If A(5, n)=TOO MUCH!!!!!

A(4, 1)=13 A(4, 2)=65533 A(4, 3)=2^ A(4, 4)=2^(2^(65536)-3)

“Ackermann’s function is a form of meta-multiplication.”Dr. Forb. a+b=adding the operand a*b=adding the operand “a” to itself b times a^b=multiplying the operand “a” by itself b times b b times

Recursion Recursion can be seen as building objects from objects that have set definitions. Recursion can also be seen in the opposite direction as objects that are defined from smaller and smaller parts. “Recursion is a different concept of circularity.”(Dr. Britt, Computing Concepts Magazine, March 97, pg.78)

Suppose that we have a series of functions for finding the power of a number x. pow0(x) = 1 pow1(x) = x = x * pow0(x) pow2(x) = x * x = x * pow1(x) pow3(x) = x * x * x = x * pow2(x) We can turn this into something more usable by creating a variable for the power and making the pattern explicit: pow(0,x) = 1 pow(n,x) = x * pow(n-1,x) Finding the powers of numbers

For instance: 2**3 = 2 * 2**2 = 2 * 4 = 8 2**2 = 2 * 2**1 = 2 * 2 = 4 2**1 = 2 * 2**0 = 2 * 1 = 2 2**0 = 1

Almost all programming languages allow recursive functions calls. That is they allow a function to call itself. And some languages allow recursive definitions of data structures. This means we can directly implement the recursive definitions and recursive algorithms that we have just been discussing. For example, the definition of the factorial function factorial(0) = 1 factorial(n) = n * factorial(n-1) [ for n > 0 ]. can be written in C without the slightest change: int factorial(int n) { if (n == 0) return 1 ; else return n * factorial(n-1) ; }

Basic Recursion What we see is that if we have a base case, and if our recursive calls make progress toward reaching the base case, then eventually we terminate. We thus have our first two fundamental rules of recursion:

Euclid's Algorithm Euclid's Algorithm determines the greatest common divisor of two natural numbers a, b. That is, the largest natural number d such that d | a and d | b. GCD(33,21)=3 33 = 1* = 1* = 1* = 3*3

The main thing to note here is that the variables that will hold the intermediate results, S1 and S2, have been declared as global variables. This is a mistake. Although the function looks just fine, its correctness crucially depends on having local variables for storing all the intermediate results. As shown, it will not correctly compute the fibonacci function for n=4 or larger. However, if we move the declaration of s1 and s2 inside the function, it works perfectly. This sort of bug is very hard to find, and bugs like this are almost certain to arise whenever you use global variables to storeintermediate results of a recursive function.

{Non-recursive version of Power function} FUNCTION PowerNR (Base : real; Exponent : integer) : real; {Preconditions: Exponent >= 0} {Accepts Base and exponent values} {Returns Base to the Exponent power} VAR Count : integer; {Counts number of times BAse is multiplied} Product : real; {Holds the answer as it is being calculated} BEGIN Product := 1; FOR Count := 1 TO Exponent DO Product := Product * Base; PowerNR := Product END; {PowerNR}

Consider the following program for computing the Fibonacci Sequence int fibonacci (int n) { if (n == 0) {return 1}; else if (n == 1) {return 1}; else {return fibonacci(n-1) + fibonacci(n- 2)}; }