7.2 Recursive Definitions of Mathematical Formulas

Slides:



Advertisements
Similar presentations
Lecture Objectives  Learn how to think recursively  Trace a recursive method  Prove a recursive method is correct  Write recursive algorithms and methods.
Advertisements

Recursion Chapter 7.
ITEC200 – Week07 Recursion. 2 Learning Objectives – Week07 Recursion (Ch 07) Students can: Design recursive algorithms to solve.
Recursion Chapter 5.
Recursion Chapter 7. Spring 2010CS 2252 Chapter Objectives To understand how to think recursively To learn how to trace a recursive method To learn how.
Scott Grissom, copyright 2004 Chapter 5 Slide 1 Analysis of Algorithms (Ch 5) Chapter 5 focuses on: algorithm analysis searching algorithms sorting algorithms.
Recursion. Objectives At the conclusion of this lesson, students should be able to Explain what recursion is Design and write functions that use recursion.
Fall 2007CS 2251 Recursion Chapter 7. Fall 2007CS 2252 Chapter Objectives To understand how to think recursively To learn how to trace a recursive method.
Recursive Algorithms Nelson Padua-Perez Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
Recursion Chapter 7.
Recursion Chapter 7. Chapter 7: Recursion2 Chapter Objectives To understand how to think recursively To learn how to trace a recursive method To learn.
Recursion Chapter 7. Chapter 7: Recursion2 Chapter Objectives To understand how to think recursively To learn how to trace a recursive method To learn.
Recursion Chapter 5.
Recursion Chapter Nature of Recursion t Problems that lend themselves to a recursive solution have the following characteristics: –One or more.
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Chapter 12: Recursion Problem Solving, Abstraction, and Design using C++
A Computer Science Tapestry 1 Recursion (Tapestry 10.1, 10.3) l Recursion is an indispensable technique in a programming language ä Allows many complex.
Chapter 13 Recursion. Topics Simple Recursion Recursion with a Return Value Recursion with Two Base Cases Binary Search Revisited Animation Using Recursion.
RECURSION Chapter 5. Chapter Objectives  To understand how to think recursively  To learn how to trace a recursive method  To learn how to write recursive.
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.  A recursive function contains a call to itself Example: the factorial n!=n*(n-1)! for n>1 n!=1 for n=1 int factorial (int n) { if (n == 0)
Programming Principles II Lecture Notes 5 Recursion Andreas Savva.
Week 5 - Monday.  What did we talk about last time?  Linked list implementations  Stacks  Queues.
Chapter 12 Recursion, Complexity, and Searching and Sorting
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.
CP104 Introduction to Programming Recursion 2 Lecture 29 __ 1 Recursive Function for gcd Recursive formula for the greatest common divisor of m and n,
Chapter 13 Recursion. Learning Objectives Recursive void Functions – Tracing recursive calls – Infinite recursion, overflows Recursive Functions that.
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. Objectives At the conclusion of this lesson, students should be able to Explain what recursion is Design and write functions that use recursion.
Maitrayee Mukerji. Factorial For any positive integer n, its factorial is n! is: n! = 1 * 2 * 3 * 4* ….* (n-1) * n 0! = 1 1 ! = 1 2! = 1 * 2 = 2 5! =
CS 116 Object Oriented Programming II Lecture 13 Acknowledgement: Contains materials provided by George Koutsogiannakis and Matt Bauer.
1 Dr. Chow-Sing LinRecursion - CH 10 Problem Solving and Program Design in C Chapter 9 Recursion Chow-Sing Lin.
Chapter 9 Recursion. Copyright ©2004 Pearson Addison-Wesley. All rights reserved.10-2 Recursive Function recursive functionThe recursive function is –a.
Ms N Nashandi Dr SH Nggada Week 08 – Recursion. Outline We shall be covering the following What is a recursion? Iteration versus Recursion. Recursion.
LECTURE 9 CS203. Execution Time Suppose two algorithms perform the same task such as search (linear search vs. binary search) and sorting (selection sort.
Chapter 13 Recursion Copyright © 2016 Pearson, Inc. All rights reserved.
Chapter Topics Chapter 16 discusses the following main topics:
Chapter 19: Recursion.
Recursion CSE 2320 – Algorithms and Data Structures
Recursion Version 1.0.
Recursion The programs discussed so far have been structured as functions that invoke one another in a disciplined manner For some problems it is useful.
Recursion Topic 5.
Topic 6 Recursion.
Chapter 15 Recursion.
Chapter 10 Recursion Instructor: Yuksel / Demirer.
Recursion DRILL: Please take out your notes on Recursion
OBJECT ORIENTED PROGRAMMING II LECTURE 23 GEORGE KOUTSOGIANNAKIS
Recursion: The Mirrors
RECURSION.
Recursion Chapter 12.
Chapter 15 Recursion.
Java 4/4/2017 Recursion.
Recursion CSE 2320 – Algorithms and Data Structures
Recursion Chapter 10.
Recursion Chapter 5.
Programming with Recursion
Chapter 6 – Queues and Deques
7.2 Recursive Definitions of Mathematical Formulas
Announcements Final Exam on August 17th Wednesday at 16:00.
Recursion "To understand recursion, one must first understand recursion." -Stephen Hawking.
Applied Algorithms (Lecture 17) Recursion Fall-23
Algorithm design and Analysis
Chapter 14: Recursion Starting Out with C++ Early Objects
Recursion Data Structures.
Announcements Final Exam on August 19th Saturday at 16:00.
Programming with Recursion
Chapter 13 Recursion Copyright © 2010 Pearson Addison-Wesley. All rights reserved.
Presentation transcript:

7.2 Recursive Definitions of Mathematical Formulas 7.1 Recursive Thinking 7.2 Recursive Definitions of Mathematical Formulas 7.3 Recursive Search Chapter 7 – Recursion

Attendance Quiz #21 Recursion

Attendance Quiz #22 Recursion

Tip #23: Class or Function? Queues / Deques Its not about class or function - its about being able to write more efficient and reusable code in developing powerful apps what would be too complicated to write without classes. OOP is generally about tying together state and behavior. Classes group attributes (state) and behavior (methods) and stating that only the methods (encapsulation) can act on the state. In OOP, the methods are responsible for implementing the behavior of the class. The methods participate in the encapsulation of state (freeing clients from the implementation detail) and in the preservation of the class invariants (statements about the class state that hold true from its birth to its death). Classes support polymorphism – the essence of OOP. Using OO over functions or older styles in a larger program is for portability. Easier, quicker, and more securer to pull out the information from a class. For a beginner it may seem you don't need classes for the little things, maybe… But even fairly simple programs could be vastly improved with classes - serious projects almost can't happen without them.

7.1, pgs. 404-411 7.1 Recursive Thinking Steps to Design a Recursive Algorithm Proving That a Recursive Function Is Correct Tracing a Recursive Function The Stack and Activation Frames 7.1, pgs. 404-411

The Stack and Activation Frames Recursion C++ maintains a stack on which it saves new information in the form of an activation frame. The activation frame contains storage for the return address of the calling function. function arguments. local variables (if any). Whenever a new function is called (recursive or otherwise), C++ pushes a new activation frame onto the stack.

Tracing a Recursive Function Recursion The process of returning from recursive calls and computing the partial results is called unwinding the recursion. #include <iostream> using namespace std; int size(string str) { if (str == "") return 0; return 1 + size(str.substr(1)); } int main() cout << size("ace"); return 0; cout << size("ace"); 3 return 1 + size("ce") 2 return 1 + size("e") 1 return 1 + size("")

Run-Time Stack - Activation Frames Recursion int main() { cout << size("ace"); return 0; } int size(string str) { if (str == "") return 0; return size(str.substr(1)); }

7.2, pgs. 412-419 7.2 Recursive Definitions of Mathematical Formulas Recursion Versus Iteration Tail Recursion or Last-Line Recursion Efficiency of Recursion 7.2, pgs. 412-419

Recursive Mathematical Formulas Recursion Mathematicians often use recursive definitions of formulas that lead naturally to recursive algorithms Examples include: factorials powers greatest common divisors sorts x = factorial(4) 24 return 4 * factorial(3) 6 return 3 * factorial(2) int factorial(int n) { if (n <= 1) return 1; return (n * factorial(n – 1)); } 2 return 2 * factorial(1) 1

Calculating xn Recursion You can raise a number to a power that is greater than 0 by repeatedly multiplying the number by itself. Recursive definition: xn = x  xn-1 Base case: x0 = 1 x = power(2.0, -3) /** Recursive power function @param x: The number @param n: The exponent @return x raised to the power n */ double power(double x, int n) { if (n == 0) return 1.0; if (n > 0) return x * power(x, n – 1); else return 1.0 / power(x, -n); } 0.125 return 1.0 / power(2.0, 3) 8.0 return 2.0 * power(2.0, 2) 4.0 return 2.0 * power(2.0, 1) 2.0 return 2.0 * power(2.0, 0) 1.0

Trace the call stack of the following recursive Greatest-Common-Divisor function for gcd(30, 77). @param m The larger number (m > 0) @param n The smaller number (n > 0) @return gcd of m and n */ int gcd(int m, int n) { if (m % n == 0) return n; if (m < n) return gcd(n, m); else return gcd(n, m % n); } x = gcd(30, 77) return m n gcd( , )

Calculating GCD Correct? Recursion How do we verify that our algorithm is correct? Base case correct? The base case is “n is a divisor of m” The solution is n (n is the greatest common divisor), which is correct Does recursion make progress to base case? Both arguments in each recursive call are smaller than in the previous call and The new second argument is always smaller than the new first argument (m % n must be less than n) Eventually a divisor will be found or the second argument will become 1 (which is a base case because it divides every integer)

Recursion Downside Recursion downside Recursion vs Iteration Base case never reached. Factorial with a negative argument - throw an invalid_argument exception if n is negative. You will eventually get a run-time error when there is no more memory available for your program to execute more function calls. Error deep in recursion stack. Recursion vs Iteration There are similarities between recursion and iteration. In iteration, a loop repetition condition determines whether to repeat the loop body or exit from the loop. In recursion, the condition usually tests for a base case. There is always an iterative solution to a problem that is solvable by recursion. A recursive algorithm may be simpler than an iterative algorithm and thus easier to design, code, debug, and maintain.

Tail Recursion Recursion Most of the recursive algorithms and functions so far are examples of tail recursion or last-line recursion. In these algorithms, there is a single recursive call and it is the last line of the function, such as in the factorial function. Straightforward process to turn a recursion function with a tail into an iterative solution: /** Recursive factorial function */ int factorial(int n) { if (n <= 1) return 1; return n * factorial(n – 1); } /** Iterative factorial function */ int factorial_iter(int n) { int result = 1; for (int k = 1; k <= n; k++) result = result * k; return result; }

Fibonacci Numbers f(n) = f(n-1) + f(n-2) f(0) = 1 f(1) = 1 Recursion f(n) = f(n-1) + f(n-2) f(0) = 1 f(1) = 1 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987… int Fibonacci(int n) { if (n < 2) return 1; /* base case */ return (Fibonacci(n-1) + Fibonacci(n-2)); }

Call Tree for Fibonacci Recursion main() Fibonacci(4) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) Fibonacci(3) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) Fibonacci(3) Fibonacci(2) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) Fibonacci(3) Fibonacci(2) Fibonacci(1) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) Fibonacci(3) Fibonacci(2) 1 Fibonacci(1) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) Fibonacci(3) Fibonacci(2) 1 Fibonacci(1) Fibonacci(0) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) Fibonacci(3) Fibonacci(2) 1 1 Fibonacci(1) Fibonacci(0) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) Fibonacci(3) Fibonacci(2) + 1 1 Fibonacci(1) Fibonacci(0) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) Fibonacci(3) 2 Fibonacci(2) + 1 1 Fibonacci(1) Fibonacci(0) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) Fibonacci(3) 2 Fibonacci(2) Fibonacci(1) + 1 1 Fibonacci(1) Fibonacci(0) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) Fibonacci(3) 2 1 Fibonacci(2) Fibonacci(1) + 1 1 Fibonacci(1) Fibonacci(0) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) Fibonacci(3) + 2 1 Fibonacci(2) Fibonacci(1) + 1 1 Fibonacci(1) Fibonacci(0) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) 3 Fibonacci(3) + 2 1 Fibonacci(2) Fibonacci(1) + 1 1 Fibonacci(1) Fibonacci(0) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) 3 Fibonacci(3) Fibonacci(2) + 2 1 Fibonacci(2) Fibonacci(1) + 1 1 Fibonacci(1) Fibonacci(0) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) 3 Fibonacci(3) Fibonacci(2) + 2 1 Fibonacci(2) Fibonacci(1) Fibonacci(1) + 1 1 Fibonacci(1) Fibonacci(0) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) 3 Fibonacci(3) Fibonacci(2) + 2 1 1 Fibonacci(2) Fibonacci(1) Fibonacci(1) + 1 1 Fibonacci(1) Fibonacci(0) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) 3 Fibonacci(3) Fibonacci(2) + 2 1 1 Fibonacci(2) Fibonacci(1) Fibonacci(1) Fibonacci(0) + 1 1 Fibonacci(1) Fibonacci(0) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) 3 Fibonacci(3) Fibonacci(2) + 2 1 1 1 Fibonacci(2) Fibonacci(1) Fibonacci(1) Fibonacci(0) + 1 1 Fibonacci(1) Fibonacci(0) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) 3 Fibonacci(3) Fibonacci(2) + + 2 1 1 1 Fibonacci(2) Fibonacci(1) Fibonacci(1) Fibonacci(0) + 1 1 Fibonacci(1) Fibonacci(0) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) 3 2 Fibonacci(3) Fibonacci(2) + + 2 1 1 1 Fibonacci(2) Fibonacci(1) Fibonacci(1) Fibonacci(0) + 1 1 Fibonacci(1) Fibonacci(0) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() Fibonacci(4) + 3 2 Fibonacci(3) Fibonacci(2) + + 2 1 1 1 Fibonacci(2) Fibonacci(1) Fibonacci(1) Fibonacci(0) + 1 1 Fibonacci(1) Fibonacci(0) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Call Tree for Fibonacci Recursion main() 5 Fibonacci(4) + 3 2 Fibonacci(3) Fibonacci(2) + + 2 1 1 1 Fibonacci(2) Fibonacci(1) Fibonacci(1) Fibonacci(0) + 1 1 Fibonacci(1) Fibonacci(0) int Fibonacci(int n) { if (n < 2) return 1; return (Fibonacci(n-1) + Fibonacci(n-2)); } int main() cout << "Fibonacci(4) = " << Fibonacci(4);

Fibonacci Numbers O(n) Recursion Because of the redundant function calls, the time required to calculate fibonacci(n) increases exponentially with n. If n is 100, there are approximately 2100 activation frames (1030). If you could process one million activation frames per second, it would still take 1024 seconds (3  1016 years) to compute fibonacci(100). /** Recursive O(n) function to calculate Fibonacci numbers @param fib_current The current Fibonacci number @param fib_previous The previous Fibonacci number @param n The count of Fibonacci numbers left to calculate @return The value of the Fibonacci number calculated so far */ int fibo(int fib_current, int fib_previous, int n) { if (n == 1) return fib_current; return fibo(fib_current + fib_previous, fib_current, n – 1); }

Fibonacci Numbers O(n) Recursion /** Fibonacci sequence @param fib_current Current # @param fib_previous Previous # @param n # left to calculate @return Current Fibonacci value */ int fibo(int current, int previous, int n) { if (n < 2) return current; return fibo(current + previous, current, n - 1); } int fibonacci(int n) return fibo(1, 1, n); int main() cout << "Fibonacci(4) = " << fibonacci(4); fibonacci(4) 5 fibo(1, 1, 4) 5 fibo(2, 1, 3) 5 fibo(3, 2, 2) 5 fibo(5, 3, 1)

7.3 Recursive Search Design of a Recursive Linear Search Algorithm Implementation of Linear Search Design of Binary Search Algorithm Efficiency of Binary Search Implementation of Binary Search Testing Binary Search 7.3, pgs. 420-426

Recursive vector Search Recursion Searching a vector can be accomplished using recursion. The simplest way to search is a linear search: Examine one element at a time starting with the first element or the last element to see whether it matches the target. On average, approximately n/2 elements are examined to find the target in a linear search. If the target is not in the vector, all n elements are examined. Base cases for recursive search: Empty vector, target can not be found; result is -1. First element of the vector matches the target; result is the subscript of first element. The recursive step searches the rest of the vector, excluding the first element. What is the order of complexity? O(n).

Recursive vector Search Recursion /** Recursive linear search function @param items The vector being searched @param target The item being searched for @param first The position of the current first element @return The subscript of target if found; otherwise -1 */ template<typename T> int linear_search(const vector<T>& items, const T& target, size_t first) { if (first == items.size()) return -1; if (target == items[first]) return first; return linear_search(items, target, first + 1); } /** Wrapper for recursive linear search function */ template<typename T> int linear_search(const std::vector<T>& items, const T& target) { return linear_search(items, target, 0); }

Design of a Binary Search Algorithm Recursion A binary search can be performed only on an array or vector that has been sorted. Base cases: The range of the vector is empty. The element being examined matches the target. Rather than looking at the first element, a binary search compares the middle element for a match with the target. If the middle element does not match the target, a binary search excludes the half of the vector (within which the target would not be found.) What is the order of complexity? O(log n).

Binary Search Algorithm Recursion

Efficiency of Binary Search Recursion At each recursive call we eliminate half the vector elements from consideration, making a binary search O(log n). A vector of size 16 would search vectors of length 16, 8, 4, 2, and 1, making 5 probes in the worst case. 16 = 24 5 = log2 16 + 1 A doubled vector size would require only 6 probes in the worst case. 32 = 25 6 = log2 32 + 1 A vector with 32,768 elements requires only 16 probes! A vector of 65,536 elements increases the number of required probes to 17.

Recursive Binary Search Recursion template <typename T> int binary_search(const vector<T>& items, int first, int last, const T& target) { if (first > last) return -1; // (base case #1) size_t middle = (first + last) / 2; // next probe if (target == items[middle]) return middle; //success (base case #2) if (target < items[middle]) return binary_search(items, first, middle - 1, target); else return binary_search(items, middle + 1, last, target); } /** Wrapper for recursive binary search function */ template<typename T> int binary_search(const vector<T>& items, const T& target) { return binary_search(items, 0, items.size() - 1, target); }