Recursion Chapter 8. What is recursion? How can a function call itself? How can a function call itself? contains a reference to itself.

Similar documents
Recursion Chapter 8. What is recursion? How can a function call itself? How can a function call itself?

What is recursion? Recursion. How can a function call itself? Recursive message() modified. contains a reference to itself. Week 7. Gaddis:

What is recursion? Recursion. How can a function call itself? Recursive message() modified. Week 10. contains a reference to itself.

What is recursion? Recursion. How can a function call itself? Recursive message() modified. Week 10. contains a reference to itself. Gaddis:

What is recursion? Recursion. Recursive message() modified. How can a function call itself? contains a reference to itself. Week 10. Gaddis:

Two Approaches to Algorithms An Example (1) Iteration (2) Recursion

Recursion. ! When the initial copy finishes executing, it returns to the part of the program that made the initial call to the function.

Standard Version of Starting Out with C++, 4th Edition. Chapter 19 Recursion. Copyright 2003 Scott/Jones Publishing

Chapter 15: Recursion

Ch 8. Searching and Sorting Arrays Part 1. Definitions of Search and Sort

! Search: find a given item in a list, return the. ! Sort: rearrange the items in a list into some. ! list could be: array, linked list, string, etc.

! Search: find a given item in a list, return the. ! Sort: rearrange the items in a list into some. ! list could be: array, linked list, string, etc.

! Search: find a given item in a list, return the. ! Sort: rearrange the items in a list into some. ! list could be: array, linked list, string, etc.

CS 310 Advanced Data Structures and Algorithms

Lecture 10: Recursion vs Iteration

11/2/2017 RECURSION. Chapter 5. Recursive Thinking. Section 5.1

Data Structures Lecture 3 Order Notation and Recursion

CSE 143. Complexity Analysis. Program Efficiency. Constant Time Statements. Big Oh notation. Analyzing Loops. Constant Time Statements (2) CSE 143 1

Wentworth Institute of Technology COMP1050 Computer Science II Spring 2017 Derbinsky. Recursion. Lecture 13. Recursion

CSCI-1200 Data Structures Spring 2018 Lecture 7 Order Notation & Basic Recursion

Reduction & Recursion Overview

What is Recursion? ! Each problem is a smaller instance of itself. ! Implemented via functions. ! Very powerful solving technique.

2.3 Recursion. Overview. Mathematical Induction. What is recursion? When one function calls itself directly or indirectly.

Recursion. Chapter 5

C/C++ Programming Lecture 18 Name:

OVERVIEW. Recursion is an algorithmic technique where a function calls itself directly or indirectly. Why learn recursion?

8/5/10 TODAY'S OUTLINE. Recursion COMP 10 EXPLORING COMPUTER SCIENCE. Revisit search and sorting using recursion. Recursion WHAT DOES THIS CODE DO?

1.7 Recursion. Department of CSE

Functions. CS10001: Programming & Data Structures. Sudeshna Sarkar Professor, Dept. of Computer Sc. & Engg., Indian Institute of Technology Kharagpur

Identify recursive algorithms Write simple recursive algorithms Understand recursive function calling

Objectives. Recursion. One Possible Way. How do you look up a name in the phone book? Recursive Methods Must Eventually Terminate.

CS116 - Module 5 - Accumulative Recursion

Recursive Methods and Problem Solving. Chris Kiekintveld CS 2401 (Fall 2010) Elementary Data Structures and Algorithms

Programming with Recursion. What Is Recursion?

Recursion. Example R1

Algorithm Analysis. Jordi Cortadella and Jordi Petit Department of Computer Science

34. Recursion. Java. Summer 2008 Instructor: Dr. Masoud Yaghini

Recursion CSCI 136: Fundamentals of Computer Science II Keith Vertanen Copyright 2011

COMP-202: Foundations of Programming. Lecture 13: Recursion Sandeep Manjanna, Summer 2015

Recursive Functions. Biostatistics 615 Lecture 5

CS 206 Introduction to Computer Science II

Overview. What is recursion? When one function calls itself directly or indirectly.

To explain growth rates and why constants and nondominating terms can be ignored in the estimation

Recursion. Overview. Mathematical induction. Hello recursion. Recursion. Example applications. Goal: Compute factorial N! = 1 * 2 * 3...

Complexity of Algorithms

Lecture 7 CS2110 Fall 2014 RECURSION

Module 05: Types of recursion

Lecture Notes 4 More C++ and recursion CSS 501 Data Structures and Object-Oriented Programming Professor Clark F. Olson

The power of logarithmic computations. Recursive x y. Calculate x y. Can we reduce the number of multiplications?

Recursion. Fundamentals of Computer Science

Algorithm Analysis. Jordi Cortadella and Jordi Petit Department of Computer Science

UEE1302(1066) F12: Introduction to Computers and Programming Function (II) - Parameter

Recursion. Recursion is: Recursion splits a problem:

l Determine if a number is odd or even l Determine if a number/character is in a range - 1 to 10 (inclusive) - between a and z (inclusive)

Ch 6. Functions. Example: function calls function

SOFTWARE DEVELOPMENT 1. Recursion 2018W A. Ferscha (Institute of Pervasive Computing, JKU Linz)

CSCI 262 Data Structures. Recursive Function Analysis. Analyzing Power. Analyzing Power. Analyzing Power 3/31/2018

t 1 =2 t n =3t n 1 1,n 1

MPATE-GE 2618: C Programming for Music Technology. Unit 4.2

CS103L SPRING 2017 UNIT 8: RECURSION

Computer Science II Lecture 2 Strings, Vectors and Recursion

RECURSION. Data Structures & SWU Rachel Cardell- Oliver

COE428 Lecture Notes Week 1 (Week of January 9, 2017)

Loops / Repetition Statements

Types of recursion. Structural vs. general recursion. Pure structural recursion. Readings: none. In this module: learn to use accumulative recursion

Chapter 3. More Flow of Control. Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

I2204 ImperativeProgramming Semester: 1 Academic Year: 2018/2019 Credits: 5 Dr Antoun Yaacoub

CSCE 110 Dr. Amr Goneid Exercise Sheet (7): Exercises on Recursion

q To develop recursive methods for recursive mathematical functions ( ).

q To develop recursive methods for recursive mathematical functions ( ).

Types of Recursive Methods

Recursion. Lars-Henrik Eriksson. Functional Programming 1. Based on a presentation by Tjark Weber and notes by Sven-Olof Nyström

CSCI-1200 Data Structures Fall 2017 Lecture 7 Order Notation & Basic Recursion

! Addition! Multiplication! Bigger Example - RSA cryptography

Help File on C++ and Programming at CSUSM by Rika Yoshii

Recursion. Chapter 7

Algorithmics. Some information. Programming details: Ruby desuka?

! Search: find an item in an array, return the. ! Sort: rearrange the items in an array into some. ! There are various methods (algorithms) for

Recursion. CSCI 112: Programming in C

Types of recursion. Readings: none. In this module: a glimpse of non-structural recursion. CS 135 Winter : Types of recursion 1

CS11001/CS11002 Programming and Data Structures (PDS) (Theory: 3-0-0)

! Determine if a number is odd or even. ! Determine if a number/character is in a range. - 1 to 10 (inclusive) - between a and z (inclusive)

Lecture 6 CS2110 Spring 2013 RECURSION

Islamic University of Gaza Computer Engineering Dept. C++ Programming. For Industrial And Electrical Engineering By Instructor: Ruba A.

Problem solving paradigms

UNIT 5A Recursion: Basics. Recursion

Data structure and algorithm in Python

Recursive Definitions

Recursion. CSE 2320 Algorithms and Data Structures University of Texas at Arlington

CSC 222: Object-Oriented Programming. Spring 2012

Computer Programming. Basic Control Flow - Loops. Adapted from C++ for Everyone and Big C++ by Cay Horstmann, John Wiley & Sons

VTU NOTES QUESTION PAPERS NEWS RESULTS FORUMS

Department of Computer Science & Engineering Indian Institute of Technology Kharagpur. Practice Sheet #06

Programming II (CS300)

Chapter 4 Functions By C.K. Liang

CMSC 150 LECTURE 7 RECURSION

1. a) What #include statement do you put at the top of a program that does uses cin, cout or endl?

Chapter 6 Recursion. The Concept of Recursion

Anatomy of a static method, S&W, 2.1, figure page 188. Class.name or just name Scope, S&W, 2.1, figure page 189. Overloading

Recursion. Recursion in C

Transcription:

Recursion Chapter 8 CS 3358 Summer II 2013 Jill Seaman What is recursion?! Generally, when something contains a reference to itself! Math: defining a function in terms of itself! Computer science: when a function calls itself Sections 8.1-8.4, (8.5 if you can) 1 2 How can a function call itself?! What happens when this function is called? How can a function call itself?! Infinite Recursion: void message() { cout << \n ; message(); message(); 3... 4

Recursive message() modified! How about this one? void message(int n) { if (n > 0) { cout << \n ; message(n-1); message(5); 5 Tracing the calls! 6 nested calls to message: message(5): outputs This is a recursive function calls message(4): outputs This is a recursive function calls message(3): outputs This is a recursive function calls message(2): outputs This is a recursive function calls message(1): outputs This is a recursive function calls message(0): does nothing, just returns! depth of recursion (#times it calls itself) = 5. 6 Why use recursion?! It is true that recursion is never required to solve a problem - Any problem that can be solved with recursion can also be solved using iteration.! Recursion requires extra overhead: function call + return mechanism uses extra resources However:! Some repetitive problems are more easily and naturally solved with recursion - Iterative solution may be unreadable to humans 7 Why use recursion?! Recursion is the primary method of performing repetition in most functional languages. - Implementations of functional languages are designed to process recursion efficiently - Iterative constructs that are added to many functional languages often don t fit well in the functional context.! Once programmers adapt to solving problems using recursion, the code produced is generally shorter, more elegant, easier to read and debug. 8

How to write recursive functions! Branching is required (If or switch)! Find a base case - one (or more) values for which the result of the function is known (no repetition required to solve it) - no recursive call is allowed here! Develop the recursive case - For a given argument (say n), assume the function works for a smaller value (n-1). - Use the result of calling the function on n-1 to form a solution for n 9 factorial! Mathematical definition of n! (factorial of n) if n=0 then n! = 1 if n>0 then n! = 1 x 2 x 3 x... x (n-1) x n! What is the base case?! If we assume (n-1)! can be computed, how can we get n! from that? 10 factorial! Mathematical definition of n! (factorial of n) if n=0 then n! = 1 if n>0 then n! = 1 x 2 x 3 x... x n! What is the base case? - n=0 (result is 1)! If we assume (n-1)! can be computed, how can we get n! from that? - n! = n * (n-1)! 11 factorial int factorial(int n) { if (n==0) return 1; return n * factorial(n-1); int number; cout << Enter a number ; cin >> number; cout << The factorial of << number << is << factorial(number) << endl; 12

Tracing the calls Tracing the calls! Calls to factorial: factorial(4): return 4 * factorial(3); calls factorial(3): return 3 * factorial(2); calls factorial(2): return 2 * factorial(1); calls factorial(1): return 1 * factorial(0); calls factorial(0): return 1;! each return statement must wait for the result of the recursive call to compute its result 13! Calls to factorial: factorial(4): return 4 * factorial(3); =4 * 6 = 24 calls factorial(3): return 3 * factorial(2); =3 * 2 = 6 calls factorial(2): return 2 * factorial(1); =2 * 1 = 2 calls factorial(1): return 1 * factorial(0); =1 * 1 = 1 calls factorial(0): return 1;! Every call except the last makes a recursive call! Each call makes the argument smaller 14 Recursive functions over ints! Many recursive functions (over integers) look like this: type f(int n) { if (n==0) //do the base case //... f(n-1)... Recursive functions over lists! You can write recursive functions over lists using the length of the list instead of n - base case: length=0 ==> empty list - recursive case: assume f works for list of length n-1, what is the answer for a list with one more element?! We will do examples with: 15 - arrays - vectors - linked lists - strings 16

sum of the list! Recursive function to compute sum of a list of numbers! What is the base case? - length=0 (empty list) sum = 0! If we assume we can sum the first n-1 items in the list, how can we get the sum of the whole list from that? - sum (list) = sum (list[0..n-2]) + list[n-1] sum of a list: array int sum(int a[], int size) { //size is number of elems if (size==0) return sum(a,size-1) + a[size-1]; call sum on first n-1 elements For a list with size = 4: sum(a,4) The last element sum(a,3) + a[3] = sum(a,2) + a[2] + a[3] = sum(a,1) + a[1] + a[2] + a[3] = sum(a,0) + a[0] + a[1] + a[2] + a[3] = 0 + a[0] + a[1] + a[2] + a[3] Assume I am given the answer to this 17 18 sum of a list: vector int sum(vector<int> v) { if (v.size()==0) { int x = v.back(); v.pop_back(); return x + sum(v); v.back() returns the last element! v.pop_back() creates the shorter vector! Aren t we changing x each time (size = 0 at end)? - No (why not?) int main () { vector<int> x; x.push_back(10); x.push_back(20); x.push_back(30); cout << "sum "<< sum(x) << endl; cout << "size "<< x.size()<< endl; - But something bad is happening each time. 19 sum of a list: vector int sum(vector<int> v) { if (v.size()==0) { int x = v.back(); v.pop_back(); return x + sum(v);! Aren t we changing x each time (size = 0 at end)? - No (why not?) int main () { vector<int> x; x.push_back(10); x.push_back(20); x.push_back(30); cout << "sum "<< sum(x) << endl; cout << "size "<< x.size()<< endl; Pass by value ==> v is a copy of x, so x is unchanged - But something bad is happening each time. Pass by value ==> v makes a copy of x, for EACH recursive call 20

sum of a list: vector without copying int sumrec(vector<int> & v) { Use pass by reference if (v.size()==0) (it will change x) { int x = v.back(); v.pop_back(); return x + sumrec(v); int sum (const vector<int> & v) { vector<int> x (v); //make ONE copy only return sumrec(x);! Sometimes an auxiliary or driver function is needed to set things up before starting recursion. 21 sum of a list: linked list! Add a sum function to List_3358_LL.h // this is the public one int List_3358::sum() { return sumnodes(head); // this one is private int List_3358::sumNodes(Node *p) { if (p==null) { int x = p->value; return x + sumnodes(p->next); advances p to next Node, (makes the shorter list) sumnodes(p) will sum the Nodes starting with the one p points to until the end of the list (NULL) 22 Summary of the list examples! How to determine empty list, single element, and the shorter list to perform recursion on. Array Vector Linked list p points to first node Base case size==0 v.size()==0 p==null last(or first) element shorter list (recursive call) a[size-1] v.back() p->value use size-1 v.pop_back()* p->next count character occurrences in a string! Recursive function to count the number of times a specific character appears in a string! We will use the string member function substr to make a smaller string - str.substr (int pos, int length); - pos is the starting position in str - length is the number of characters in the result string x = hello there ; cout << s.substr(3,5); lo th *may need to copy original vector 23 24

count character occurrences in a string int numchars(char target, string str) { if (str.empty()) { { int result = numchars(search, str.substr(1,str.size())); if (str[0]==target) return 1+result; return result; string a = "hello"; cout << a << numchars('l',a) << endl; 25 Three required properties of recursive functions! A Base case - a non-recursive branch of the function body. - must return the correct result for the base case! Smaller caller - each recursive call must pass a smaller version of the current argument.! Recursive case - assuming the recursive call works correctly, the code must produce the correct answer for the current argument. 26 greatest common divisor! Greatest common divisor of two non-zero ints is the largest positive integer that divides the numbers without a remainder! This is a variant of Euclid s algorithm: gcd(x,y) = y if y divides x evenly, otherwise: gcd(x,y) = gcd(y,remainder of x/y), or gcd(y,x%y) in c++! Code: greatest common divisor int gcd(int x, int y) { cout << "gcd called with " << x << " and " << y << endl; if (x % y == 0) { return y; { return gcd(y, x % y);! It s a recursive definition! If x < y, then x%y is x (so gcd(x,y) = gcd(y,x))! This moves the larger number to the first position. 27 cout << "GCD(9,1): " << gcd(9,1) << endl; cout << "GCD(1,9): " << gcd(1,9) << endl; cout << "GCD(9,2): " << gcd(9,2) << endl; cout << "GCD(70,25): " << gcd(70,25) << endl; cout << "GCD(25,70): " << gcd(25,70) << endl; 28

! Output: greatest common divisor gcd called with 9 and 1 GCD(9,1): 1 gcd called with 1 and 9 gcd called with 9 and 1 GCD(1,9): 1 gcd called with 9 and 2 gcd called with 2 and 1 GCD(9,2): 1 gcd called with 70 and 25 gcd called with 25 and 20 gcd called with 20 and 5 GCD(70,25): 5 gcd called with 25 and 70 gcd called with 70 and 25 gcd called with 25 and 20 gcd called with 20 and 5 GCD(25,70): 5 29! Series of : 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,...! Starts with 0, 1. Then each number is the sum of the two previous numbers F0 = 0 F1 = 1 Fi = Fi-1 + Fi-2 (for i > 1)! It s a recursive definition 30! Code: int fib(int x) { if (x<=1) return x; return fib(x-1) + fib(x-2); cout << "The first 13 fibonacci numbers: " << endl; for (int i=0; i<13; i++) cout << fib(i) << " "; cout << endl; The first 13 fibonacci numbers: 0 1 1 2 3 5 8 13 21 34 55 89 144 31! Modified code to count the number of calls to fib: int fib(int x, int &count) { count++; if (x<=1) return x; return fib(x-1, count) + fib(x-2, count); cout << "The first 40 fibonacci numbers: " << endl; for (int i=0; i<40; i++) { int count = 0; int x = fib(i,count); cout << "fib (" << i << ")= " << x << " # of recursive calls to fib = " << count << endl; 32

! Counting calls to fib: output The first 40 fibonacci numbers: fib (0)= 0 # of recursive calls to fib = 1 fib (1)= 1 # of recursive calls to fib = 1 fib (2)= 1 # of recursive calls to fib = 3 fib (3)= 2 # of recursive calls to fib = 5 fib (4)= 3 # of recursive calls to fib = 9 fib (5)= 5 # of recursive calls to fib = 15 fib (6)= 8 # of recursive calls to fib = 25 fib (7)= 13 # of recursive calls to fib = 41 fib (8)= 21 # of recursive calls to fib = 67 fib (9)= 34 # of recursive calls to fib = 109 fib (10)= 55 # of recursive calls to fib = 177 fib (11)= 89 # of recursive calls to fib = 287 fib (12)= 144 # of recursive calls to fib = 465 fib (13)= 233 # of recursive calls to fib = 753... 33 fib (40)= 102,334,155 # of recursive calls to fib = 331,160,281! Why are there so many calls to fib? fib(n) calls fib(n-1) and fib(n-2)! Say it computes fib(n-2) first.! When it computes fib(n-1), it computes fib(n-2) again fib(n-1) calls fib((n-1)-1) and fib((n-1)-2) = fib(n-2) and fib (n-3)! It s not just double the work. It s double the work for each recursive call.! Each recursive call does more and more redundant 34 work! Trace of the recursive calls for fib(5) Fib(3) Fib(4) Fib(5) Fib(3) Fib(2) Fib(2) Fib(1) Fib(2) Fib(1) Fib(1) Fib(0) Fib(1) Fib(0) Fib(1) Fib(0)! The number of recursive calls is - larger than the Fibonacci number we are trying to compute - exponential, in terms of n! Never solve the same instance of a problem in separate recursive calls. - make sure f(m) is called only once for a given m 35 36

! Find an item in a list, return the index or -1! Works only for SORTED lists! Compare target value to middle element in list. - if equal, then return index Iterative version int binarysearch(const int array[], int size, int value) { int first = 0, last = size - 1, middle, position = -1; bool found = false; // First array element // Last array element // Mid point of search // Position of search value // Flag while (!found && first <= last) { middle = (first + last) / 2; // Calculate mid point - if less than middle elem, search in first half if (array[middle] == value) { // If value is found at mid found = true; - if greater than middle elem, search in last half position = middle;! If search list is narrowed down to 0 elements, if (array[middle] > value) // If value is in lower half return -1 last = middle - 1;! Divide and conquer style algorithm first = middle + 1; // If value is in upper half 37 38 return position; Example The target of your search is 42. Given the following list of integers, record the values of first, last, and middle during a binary search. Assume the following numbers are in an array.!1 7 8 14 20 42 55 67 78 101 112 122 170 179 190 Repeat!! the exercise with a target of 82 39 5 Recursive version! Convert the iterative version to recursive! What is the base case? - empty list: result = -1 (not found)! What is the recursive case? - split list into: middle value, first half, last half - if middle value equals target, then return its index - if less than middle elem, search in first half two base cases - if greater than middle elem, search in last half two recursive cases! Need to add parameters for first and last index of the current subpart of the list to search. 40

Recursive version Running time efficiency int binarysearchrec(const int array[], int first, int last, int value) { int middle; // Mid point of search if (first > last) //check for empty list return -1; middle = (first + last)/2; //compute middle index if (array[middle]==value) return middle; if (value < array[middle]) //recursion return binarysearchrec(array, first,middle-1, value); return binarysearchrec(array, middle+1,last, value);! What is the Big-O analysis of the running time?! N is the length of the list to search! Worst case: keep dividing N by 2 until it is less than 1.! This is equivalent to doubling 1 until it gets to N. 1*2 = 2 2*2 = 4 4*2 = 8 8*2 = 16 16*2 = 32 After 6 steps we have 2 6 int binarysearch(const int array[], int size, int value) { return binarysearchrec(array, 0, size-1, value); 32*2 = 64 After k steps we have 2 k 41 42 Running time efficiency! How many steps does it take to double 1 and get to N? 2 k = N! How do we solve that for k?! Definition of logarithm (see math textbook): logbn = k if B k = N! So solving for k: k = log2n The logarithm is the exponent Running time efficiency! How many steps does it take to repeatedly double 1 and get to N? log2n! How many steps does it take to repeatedly divide N by 2 and get to 1? log2n! Since (worst case) binary search repeatedly divides the length of the list by 2, until it gets down to one, its running time is 43 O(log N) 44