Introduction to Recursion CSCI 3333 Data Structures.

31
Introduction to Recursion CSCI 3333 Data Structures

Transcript of Introduction to Recursion CSCI 3333 Data Structures.

Page 1: Introduction to Recursion CSCI 3333 Data Structures.

Introduction to Recursion

CSCI 3333 Data Structures

Page 2: Introduction to Recursion CSCI 3333 Data Structures.

Acknowledgement

Dr. Bun Yue Mr. Charles Moen Dr. Wei Ding Ms. Krishani Abeysekera Dr. Michael Goodrich Dr. Behrouz A. Forouzan Dr. Richard F. Gilberg

Page 3: Introduction to Recursion CSCI 3333 Data Structures.

Recursion

Recursion is defining a function that calls itself as a subroutine.

Recursion is a way to combat complexity and solve problems.

Solving a problem by: Solving the problem for ‘trivial’ cases,

and Solving the same problem, but with

smaller sizes.

Page 4: Introduction to Recursion CSCI 3333 Data Structures.

Recursive Definition

A recursive definition: a definition in terms of itself.

Example: 0 is a natural number. If x is a natural number, then x+1 is

a natural number. (or x is a natural number if x-1 is a natural number).

Page 5: Introduction to Recursion CSCI 3333 Data Structures.

Recursive Methods

A recursive method may calls itself.Example: factorial.Iterative definition:n! = n . (n-1) . (n-2) … 3 . 2 . 1

Recursive definition:

elsenfn

nnf

)1(

0 if1)(

Page 6: Introduction to Recursion CSCI 3333 Data Structures.

Recursive Factorial Algorithm

//By Forouzan

Page 7: Introduction to Recursion CSCI 3333 Data Structures.

Factorial Implementation: Fac-1

Found here in C++:

int factorial(int number) { int temp;

if (number <= 1) return 1; temp = number * factorial(number - 1); return temp;

}

What do you think?

Page 8: Introduction to Recursion CSCI 3333 Data Structures.

Another Implementation: Fac-2

int recursiveFactorial(int n) { if (n == 0)

return 1; // base case else

return n * recursiveFactorial(n- 1);

// recursive case /general case }

Page 9: Introduction to Recursion CSCI 3333 Data Structures.

Content of a Recursive Method

Base case(s): exit conditions Values of the input variables (exit conditions) for

which we perform no recursive calls are called base cases (there should be at least one base case).

Every possible chain of recursive calls must eventually reach a base case.

Recursive calls: recursive conditions Calls to the current method.

Each call must reduce the size of the problem and move it toward the base case; reduces the size of the problem. .

Page 10: Introduction to Recursion CSCI 3333 Data Structures.

Visualizing Recursion

Recursion trace A box for each

recursive call An arrow from each

caller to callee An arrow from each

callee to caller showing return value

Example recursion trace:

recursiveFactorial (4)

recursiveFactorial (3)

recursiveFactorial (2)

recursiveFactorial (1)

recursiveFactorial (0)

return 1

call

call

call

call

return 1*1 = 1

return 2*1 = 2

return 3*2 = 6

return 4*6 = 24 final answercall

Page 11: Introduction to Recursion CSCI 3333 Data Structures.

Tips on Recursive Analysis

Identify exit and recursive conditions.

Ensure that the conditions cover all input ranges.

Page 12: Introduction to Recursion CSCI 3333 Data Structures.

Input Range Analysis of Fac

Fac-1 and Fac-2: n (or number) has the type of int.

Fac-2 may be caught in circularity forever for negative numbers.

Page 13: Introduction to Recursion CSCI 3333 Data Structures.

Reversing an Array

Algorithm ReverseArray(A, i, j): Input: An array A and nonnegative

integer indices i and j Output: The reversal of the elements in

A starting at index i and ending at j if i < j then

Swap A[i] and A[ j]ReverseArray(A, i + 1, j - 1)

return

Page 14: Introduction to Recursion CSCI 3333 Data Structures.

Tips on Constructing Recursion

In creating recursive methods, it is important to define the methods in ways that facilitate recursion.

This sometimes requires we may define additional parameters that are passed to the method.

For example, we defined the array reversal method as ReverseArray(A, i, j), not ReverseArray(A).

Page 15: Introduction to Recursion CSCI 3333 Data Structures.

Computing Powers

The power function, p(x,n)=xn, can be defined recursively:

This leads to an power function that runs in linear time (for we make n recursive calls).

We can do better than this, however.

else)1,(

0 if1),(

nxpx

nnxp

Page 16: Introduction to Recursion CSCI 3333 Data Structures.

Recursive Squaring We can derive a more efficient linearly

recursive algorithm by using repeated squaring:

For example,24 = 2(4/2)2 = (24/2)2 = (22)2 = 42 = 1625 = 21+(4/2)2 = 2(24/2)2 = 2(22)2 = 2(42) = 3226 = 2(6/ 2)2 = (26/2)2 = (23)2 = 82 = 6427 = 21+(6/2)2 = 2(26/2)2 = 2(23)2 = 2(82) = 128.

Note: This definition leads to linear recursive algorithm that uses O(n)

even is 0 if

odd is 0 if

0 if

)2/,(

)2/)1(,(

1

),(2

2

x

x

x

nxp

nxpxnxp

Page 17: Introduction to Recursion CSCI 3333 Data Structures.

A Recursive Squaring Method

Algorithm Power(x, n): Input: A number x and integer n Output: The value xn

if n = 0 thenreturn 1

if n is odd theny = Power(x, (n - 1)/ 2)return x · y · y

elsey = Power(x, n/ 2)return y · y

Page 18: Introduction to Recursion CSCI 3333 Data Structures.

Analyzing the Recursive Squaring Method

Algorithm Power(x, n): Input: A number x and integer n Output: The value xn

if n = 0 thenreturn 1

if n is odd theny = Power(x, (n - 1)/ 2)return x · y · y

elsey = Power(x, n/ 2)return y · y It is important that we

used a variable twice here rather than calling the method twice.

Each time we make a recursive call we halve the value of n; hence, we make log n recursive calls. That is, this method runs in O(log n) time.

Page 19: Introduction to Recursion CSCI 3333 Data Structures.

Further Analysis

Need to limit the range of n, or. Add the recursive condition:

if n < 0 return 1 / Power(x, -n);

Page 20: Introduction to Recursion CSCI 3333 Data Structures.

Tail Recursion 1 Tail recursion occurs when a linearly

recursive method makes its recursive call as its last step.

The array reversal method is an example.

Such methods can be easily converted to non-recursive methods (which saves on some resources), often by the compiler and runtime system.

Page 21: Introduction to Recursion CSCI 3333 Data Structures.

Tail Recursion Example

Algorithm IterativeReverseArray(A, i, j ): Input: An array A and nonnegative integer

indices i and j Output: The reversal of the elements in A

starting at index i and ending at j while i < j do

Swap A[i ] and A[ j ]i = i + 1j = j - 1

return

Page 22: Introduction to Recursion CSCI 3333 Data Structures.

Tail Recursion 2

Tips: for linear recursion, write your method using tail recursion.

Example: Fac-1 does not use tail recursion. Fac-2 does.

Page 23: Introduction to Recursion CSCI 3333 Data Structures.

Binary Recursion Binary recursion occurs whenever there are

two recursive calls for each non-base case. Also known as Higher-Order Recursion. Example: Fibonacci number

0, 1, 1, 2, 3, 5, 8, 13, 21, 34

Page 24: Introduction to Recursion CSCI 3333 Data Structures.

Fibonacci Numbers

Fibonacci numbers are defined recursively:

F0 = 0

F1 = 1

Fi = Fi-1 + Fi-2 for i > 1.

Page 25: Introduction to Recursion CSCI 3333 Data Structures.

Binary Recursion

Binary Recursions are expensive. If possible, convert it to linear

recursion.

Page 26: Introduction to Recursion CSCI 3333 Data Structures.

Recursive Fibonacci Algorithm

Algorithm BinaryFib(k): Input: Nonnegative integer k

Output: The kth Fibonacci number Fk

if k = 1 thenreturn k

elsereturn BinaryFib(k - 1) + BinaryFib(k - 2)

Binary recursion from the text book. Any problem here?

Page 27: Introduction to Recursion CSCI 3333 Data Structures.

A C++ Implementation

long fib(unsigned long n) { if (n <= 1) { return n; } else { return fib(n-1)+fib(n-2); }}

Page 28: Introduction to Recursion CSCI 3333 Data Structures.

Analyzing the Binary Recursion Fibonacci Algorithm

Let nk denote number of recursive calls made by BinaryFib(k). Then n0 = 1 n1 = 1 n2 = n1 + n0 + 1 = 1 + 1 + 1 = 3 n3 = n2 + n1 + 1 = 3 + 1 + 1 = 5 n4 = n3 + n2 + 1 = 5 + 3 + 1 = 9 n5 = n4 + n3 + 1 = 9 + 5 + 1 = 15 n6 = n5 + n4 + 1 = 15 + 9 + 1 = 25 n7 = n6 + n5 + 1 = 25 + 15 + 1 = 41 n8 = n7 + n6 + 1 = 41 + 25 + 1 = 67.

Note that the value at least doubles for every other value of nk. That is, nk > 2k/2. It is exponential!

Page 29: Introduction to Recursion CSCI 3333 Data Structures.

Analyzing the Binary Recursion Fibonacci Algorithm

//By Forouzan

Page 30: Introduction to Recursion CSCI 3333 Data Structures.

A Better Fibonacci Algorithm

Use linear recursion instead:Algorithm LinearFibonacci(k): Input: A nonnegative integer k Output: Pair of Fibonacci numbers (Fk, Fk-1) if k = 1 then

return (k, 0) else

(i, j) = LinearFibonacci(k - 1)return (i +j, i)

Runs in O(k) time.

Page 31: Introduction to Recursion CSCI 3333 Data Structures.

Questions and Comments?