0 Up votes0 Down votes

2 views119 pagesRecursion -Data Structure Lecture

Oct 30, 2018

© © All Rights Reserved

PDF, TXT or read online from Scribd

Recursion -Data Structure Lecture

© All Rights Reserved

2 views

Recursion -Data Structure Lecture

© All Rights Reserved

- BIRTHDAY PARADOX – A SIMULATION OF SHARED BIRTHDAY EXPERIMENTS
- Data Structures and Algorithms 2009-4-3 0
- 10.Recursion
- Chapter 05
- Fortran 90 Course Notes
- SAP_LSMW_CONV_00000009
- B3908-90002
- VHDL
- Performance analysis of Algorithms
- ABAP Keywords
- TDL Reference Manual 2
- Plan Versions
- Tb40laan Sort
- Chapter6 Func SimpleRecursion
- Assignment 7
- Computer Programming C-01
- Gaurav Sawadekar FYMCA
- Graphics lab assignment
- Model Subiecte Examen
- 55326265-Commodore-64-Subroutine-Cookbook.pdf

You are on page 1of 119

Objectives

• become familiar with the idea of recursion

• learn to use recursion as a programming tool

• become familiar with the binary search

algorithm as an example of recursion

• become familiar with the merge sort algorithm

as an example of recursion

How do you look up a name in

the phone book?

One Possible Way

Search:

middle page = (first page + last page)/2

Go to middle page;

If (name is on middle page)

done; //this is the base case

else if (name is alphabetically before middle page)

last page = middle page //redefine search area to front half

Search //same process on reduced number of pages

else //name must be after middle page

first page = middle page //redefine search area to back half

Search //same process on reduced number of pages

Overview

Recursion: a definition in terms of itself.

Recursion in algorithms:

• Natural approach to some (not all) problems

• A recursive algorithm uses itself to solve one or more

smaller identical problems

Recursion in C/C++:

• Recursive functions implement recursive algorithms

• A recursive function includes a call to itself

Recursive Functions

Must Eventually Terminate

A recursive function must have

at least one base, or stopping, case.

– stops the recursion

version of itself”

– an argument that describes a smaller problem

– a base case is eventually reached

Key Components of a Recursive

Algorithm Design

1. What is a smaller identical problem(s)?

Decomposition

form the answer to the larger problem?

Composition

(without further decomposition)?

Base/stopping case

Examples in Recursion

• Usually quite confusing the first time

– recursive algorithms might not be best

– harder to implement otherwise

Factorial (N!)

• N! = (N-1)! * N [for N > 1]

• 1! = 1

• 3!

= 2! * 3

= (1! * 2) * 3

=1*2*3

• Recursive design:

– Decomposition: (N-1)!

– Composition: * N

– Base case: 1!

factorial Method

int factorial(int n)

{

int fact;

if (n > 1) // recursive case (decomposition)

fact = factorial(n – 1) * n; // composition

else // base case

fact = 1;

return fact;

}

int factorial(int 3)

{

int fact;

if (n > 1)

fact = factorial(2) * 3;

else

fact = 1;

return fact;

}

public static int factorial(int 3)

{

int fact;

if (n > 1)

fact = factorial(2) * 3;

else

fact = 1;

return fact;

}

int factorial(int 2)

{

int fact;

if (n > 1)

fact = factorial(1) * 2;

else

fact = 1;

return fact;

}

public static int factorial(int 3)

{

int fact;

if (n > 1)

fact = factorial(2) * 3;

else

fact = 1;

return fact;

}

{

int fact;

if (n > 1)

fact = factorial(1) * 2;

else

fact = 1;

return fact;

}

int factorial(int 1)

{

int fact;

if (n > 1)

fact = factorial(n - 1) * n;

else

fact = 1;

return fact;

}

int factorial(int 3)

{

int fact;

if (n > 1)

fact = factorial(2) * 3;

else

fact = 1;

return fact;

}

int factorial(int 2)

{

int fact;

if (n > 1)

fact = factorial(1) * 2;

else

fact = 1;

return fact;

}

int factorial(int 1)

{

int fact;

if (n > 1)

fact = factorial(n - 1) * n;

else

fact = 1;

return 1;

}

int factorial(int 3)

{

int fact;

if (n > 1)

fact = factorial(2) * 3;

else

fact = 1;

return fact;

}

int factorial(int 2)

{

int fact;

if (n > 1)

fact = 1 * 2;

else

fact = 1;

return fact;

}

int factorial(int 1)

{

int fact;

if (n > 1)

fact = factorial(n - 1) * n;

else

fact = 1;

return 1;

}

int factorial(int 3)

{

int fact;

if (n > 1)

fact = factorial(2) * 3;

else

fact = 1;

return fact;

}

int factorial(int 2)

{

int fact;

if (n > 1)

fact = 1 * 2;

else

fact = 1;

return 2;

}

int factorial(int 3)

{

int fact;

if (n > 1)

fact = 2 * 3;

else

fact = 1;

return fact;

}

int factorial(int 2)

{

int fact;

if (n > 1)

fact = 1 * 2;

else

fact = 1;

return 2;

}

int factorial(int 3)

{

int fact;

if (n > 1)

fact = 2 * 3;

else

fact = 1;

return 6;

}

int factorial(int n)

{

Execution Trace int fact;

if (n > 1) // recursive case (decomposition)

fact = factorial(n – 1) * n; (composition)

(decomposition) else // base case

fact = 1;

return fact;

}

factorial(4)

factorial(3) 4

int factorial(int n)

{

Execution Trace int fact;

if (n > 1) // recursive case (decomposition)

fact = factorial(n – 1) * n; (composition)

(decomposition) else // base case

fact = 1;

return fact;

}

factorial(4)

factorial(3) 4

factorial(2) 3

int factorial(int n)

{

Execution Trace int fact;

if (n > 1) // recursive case (decomposition)

fact = factorial(n – 1) * n; (composition)

(decomposition) else // base case

fact = 1;

return fact;

}

factorial(4)

factorial(3) 4

factorial(2) 3

factorial(1) 2

int factorial(int n)

{

Execution Trace int fact;

if (n > 1) // recursive case (decomposition)

fact = factorial(n – 1) * n; (composition)

(composition) else // base case

fact = 1;

return fact;

}

factorial(4)

*

factorial(3) 4

*

factorial(2) 3

*

factorial(1)->1 2

int factorial(int n)

{

Execution Trace int fact;

if (n > 1) // recursive case (decomposition)

fact = factorial(n – 1) * n; (composition)

(composition) else // base case

fact = 1;

return fact;

}

factorial(4)

*

factorial(3) 4

*

factorial(2)->2 3

int factorial(int n)

{

Execution Trace int fact;

if (n > 1) // recursive case (decomposition)

fact = factorial(n – 1) * n; (composition)

(composition) else // base case

fact = 1;

return fact;

}

factorial(4)

*

factorial(3)->6 4

int factorial(int n)

{

Execution Trace int fact;

if (n > 1) // recursive case (decomposition)

fact = factorial(n – 1) * n; (composition)

(composition) else // base case

fact = 1;

return fact;

}

factorial(4)->24

Improved factorial Method

int factorial(int n)

{

int fact=1; // base case value

fact = factorial(n – 1) * n; // composition

// else do nothing; base case

return fact;

}

Fibonacci Numbers

• The Nth Fibonacci number is the sum of the previous

two Fibonacci numbers

• 0, 1, 1, 2, 3, 5, 8, 13, …

• Recursive Design:

– Decomposition & Composition

• fibonacci(n) = fibonacci(n-1) + fibonacci(n-2)

– Base case:

• fibonacci(1) = 0

• fibonacci(2) = 1

fibonacci Method

int fibonacci(int n)

{

int fib;

if (n > 2)

fib = fibonacci(n-1) + fibonacci(n-2);

else if (n == 2)

fib = 1;

else

fib = 0;

return fib;

}

Execution Trace (decomposition)

fibonacci(4)

fibonacci(3) fibonacci(2)

Execution Trace (decomposition)

fibonacci(4)

fibonacci(3) fibonacci(2)

fibonacci(2) fibonacci(1)

Execution Trace (composition)

fibonacci(4)

+

fibonacci(3) fibonacci(2)

+

fibonacci(2)->1 fibonacci(1)->0

Execution Trace (composition)

fibonacci(4)

+

fibonacci(3)->1 fibonacci(2)->1

Execution Trace (composition)

fibonacci(4)->2

Remember:

Key to Successful Recursion

• if-else statement (or some other branching

statement)

• Some branches: recursive call

– "smaller" arguments or solve "smaller"

versions of the same task (decomposition)

– Combine the results (composition) [if

necessary]

• Other branches: no recursive calls

– stopping cases or base cases

Template

… function(…)

{

if ( … )// base case

{

}

else // decomposition & composition

{

}

return … ; // if not void method

}

Template (only one base case)

… function(…)

{

… result = … ;//base case

{ //decomposition & composition

result = …

}

return result;

}

What Happens Here?

int factorial(int n)

{

int fact=1;

if (n > 1)

fact = factorial(n) * n;

return fact;

}

What Happens Here?

{

return factorial(n – 1) * n;

}

Warning: Infinite Recursion May

Cause a Stack Overflow Error

• Infinite Recursion

– Problem not getting smaller (no/bad decomposition)

– Base case exists, but not reachable (bad base case

and/or decomposition)

– No base case

• Stack: keeps track of recursive calls by OS

– Function begins: add data onto the stack

– Function ends: remove data from the stack

• Recursion never stops; stack eventually runs out of space

– Stack overflow error

Mistakes in recursion

• No composition -> ?

• Bad composition -> ?

Number of Zeros in a Number

• Example: 2030 has 2 zeros

• If n has two or more digits recursive

– the number of zeros is the number of zeros in n with the

last digit removed

– plus an additional 1 if the last digit is zero

• Examples:

– number of zeros in 20030 is number of zeros in 2003

plus 1

– number of zeros in 20031 is number of zeros in 2003

plus 0

numberOfZeros Recursive Design

• numberOfZeros in the number N

• K = number of digits in N

• Decomposition:

– numberOfZeros in the first K - 1 digits

– Last digit

• Composition:

– Add:

• numberOfZeros in the first K - 1digits

• 1 if the last digit is zero

• Base case:

– N has one digit (K = 1)

numberOfZeros method

int numberOfZeros(int n) Which is (are)

{ the base

int zeroCount; case(s)?

if (n==0)

zeroCount = 1; Decompostion

else if (n < 10) // and not 0 ?

zeroCount = 0; // 0 for no zeros

else if (n%10 == 0) Composition?

zeroCount = numberOfZeros(n/10) + 1;

else // n%10 != 0

zeroCount = numberOfZeros(n/10);

return zeroCount;

}

int numberOfZeros(int n)

{

Execution Trace int zeroCount;

if (n==0)

(decomposition) zeroCount = 1;

else if (n < 10) // and not 0

zeroCount = 0; // 0 for no zeros

Each method else if (n%10 == 0)

invocation will zeroCount = numberOfZeros(n/10) + 1;

execute one of the else // n%10 != 0

zeroCount = numberOfZeros(n/10);

if-else cases return zeroCount;

shown at right. }

numberOfZeros(2005)

numberOfZeros(200) 5

numberOfZeros(20) 0

numberOfZeros(2) 0

int numberOfZeros(int n)

{

Execution Trace int zeroCount;

if (n==0)

(composition) zeroCount = 1;

else if (n < 10) // and not 0

zeroCount = 0; // 0 for no zeros

Recursive calls else if (n%10 == 0)

return zeroCount = numberOfZeros(n/10) + 1;

else // n%10 != 0

zeroCount = numberOfZeros(n/10);

return zeroCount;

}

numberOfZeros(2005)->2

+

numberOfZeros(200)->2 5->0

+

numberOfZeros(20)->1 0->1

+

numberOfZeros(2)->0 0->1

Number in English Words

• Process an integer and print out its digits

in words

– Input: 123

– Output: "one two three”

inWords Resursive Design

• inWords prints a number N in English words

• K = number of digits in N

• Decomposition:

– inWords for the first K – 1 digits

– Print the last digit

• Composition:

– Execution order of composed steps [more later]

• Base case:

– N has one digit (K = 1)

inWords method

executes {

when only 1 if (numeral < 10)

digit is left printf(“%s ”, digitWord(numeral));

else //numeral has two or more digits

{

Size of problem inWords(numeral/10);

is reduced for printf(“%s ”, digitWord(numeral%10));

each recursive }

call }

Execution Trace (decomposition)

inwords(987)

[print “nine”]

No output yet, why?

Execution Trace (composition)

inwords(987)

print “nine”

Output: nine eight seven

inWords(987)

if (987 < 10)

1 What Happens

// print digit here

else //two or more digits left with a Recursive

{

inWords(987/10); Call

// print digit here

}

argument 987

inWords(987)

if (987 < 10)

// print digit here

Execution

else //two or more digits left

{

Trace

inWords(987/10); The argument is getting

// print digit here shorter and will eventually

} inWords(98) get to the base case.

2 if (98 < 10)

// print digit here

Computation else //two or more digits left

waits here {

until recursive inWords(98/10);

// print digit here

call returns

}

• recursive call to inWords, with 987/10

or 98 as the argument

inWords(987)

if (987 < 10)

// print digit here

else //two or more digits left

Execution Trace

{

inWords(987/10);

// print digit here

} inWords(98)

if (98 < 10)

// print digit here

else //two or more digits left

{

inWords(98/10);

// print digit here

} inWords(9)

3 if (9 < 10)

// print digit here

• the if condition is false else //two or more digits left

• another recursive call is {

inWords(numeral/10);

made. // print digit here

}

inWords(987)

if (987 < 10)

// print digit here

else //two or more digits left

Execution Trace

{

inWords(987/10); Output: nine

// print digit here

} inWords(98)

if (98 < 10)

// print digit here

else //two or more digits left

{ 4

inWords(98/10);

// print 98 % 10

} inWords(9)

if (9 < 10)

• if condition is true (base // print nine

case) else //two or more digits left

{

• prints nine and returns inWords(numeral/10);

// print digit here

• no recursive call }

inWords(987)

if (987 < 10)

// print out digit here Execution Trace

else //two or more digits left

{ 5

inWords(987/10);

// print digit here

} inWords(98)

if (98 < 10)

// print out digit here

else //two or more digits left

{

inWords(98/10);

// print out 98 % 10 here

}

• prints eight and then returns

inWords(987)

if (987 < 10)

// print out digit here 6 Execution Trace

else //two or more digits left

{

inWords(987/10);

// print 987 % 10

6

Output: nine eight seven

}

the recursive method call.

• prints seven and returns

Composition Matters

public static void inWords(int numeral)

{

if (numeral < 10)

printf(“%s ”, digitWord(numeral));

else //numeral has two or more digits

Print before {

making the printf(“%s ”, digitWord(numeral%10) );

recursive call inWords(numeral/10);

}

}

Recursive Design:

1. Print the last digit

2. inWords for the first K – 1 digits

Execution Trace (decomposition)

inwords(987)

Output: seven

Execution Trace (decomposition)

inwords(987)

Execution Trace (decomposition)

inwords(987)

print “nine”

Output: seven eight nine

Execution Trace (composition)

inwords(987)

print “nine”

No additional output

"Name in the Phone Book" Revisited

Search:

middle page = (first page + last page)/2

Go to middle page;

If (name is on middle page)

done;//this is the base case

else if (name is alphabetically before middle page)

last page = middle page//redefine to front half

Search//recursive call

else //name must be after middle page

first page = middle page//redefine to back half

Search//recursive call

Binary Search Algorithm

• Searching a list for a particular value

– sequential and binary are two common

algorithms

• Sequential search (aka linear search):

– Not very efficient

– Easy to understand and program

• Binary search:

– more efficient than sequential

– but the list must be sorted first!

Why Is It Called "Binary" Search?

Compare sequential and binary search algorithms:

How many elements are eliminated from the list each

time a value is read from the list and it is not the

"target" value?

Binary search: half the list!

each unsuccessful test for the target value

reduces the remaining search list by 1/2.

int search(int target, int first, int last)

Binary Search {

int location = -1; // not found

Method

if (first <= last) // range is not empty

{

• returns the index of the int mid = (first + last)/2;

entry if the target value is

found or -1 if it is not if (target == a[mid])

found location = mid;

• Compare it to the else if (target < a[mid]) // first half

pseudocode for the location = search(target, first, mid - 1);

"name in the phone else //(target > a[mid]) second half

book" problem location = search(target, mid + 1, last);

}

return location;

}

Where is the composition?

• If no items

– not found (-1)

• Else if target is in the middle

– middle location

• Else

– location found by search(first half) or

search(second half)

Binary Search Example

target is 33

The array a looks like this:

Indices 0 1 2 3 4 5 6 7 8 9

Contents 5 7 9 13 32 33 42 54 56 88

mid = (0 + 9) / 2 (which is 4)

33 > a[mid] (that is, 33 > a[4])

So, if 33 is in the array, then 33 is one of:

5 6 7 8 9

33 42 54 56 88

consideration because array elements are sorted.

target is 33

The array a looks like this:

Binary Search Example

Indexes 0 1 2 3 4 5 6 7 8 9

Contents 5 7 9 13 32 33 42 54 56 88

mid = (5 + 9) / 2 (which is 7)

33 < a[mid] (that is, 33 < a[7]) Eliminate

So, if 33 is in the array, then 33 is one of: half of the

5 6 remaining

33 42 elements

mid = (5 + 6) / 2 (which is 5)

33 == a[mid]

So we found 33 at index 5:

5

33

Tips

• Don’t throw away answers (return values)--

need to compose the answers

– Common programming mistake: not capturing

and composing answers (return values)

• Only one return statement at the end

– Easier to keep track of and debug return values

– “One entry, one exit”

Recursive Versus Iterative

Functions

All recursive algorithms/functions

can be rewritten without recursion.

memory--less overhead in keeping track of function

calls

So When Should You Use

Recursion?

• Solutions/algorithms for some problems are

inherently recursive

– iterative implementation could be more

complicated

• When efficiency is less important

– it might make the code easier to understand

• Bottom line is about:

– Algorithm design

– Tradeoff between readability and efficiency

Sometimes recursion has much higher complexity than

iterative methods – Example: Fibonacci numbers.

Recursive Fibonacci method

• This is elegant code, no?

long fib(int n) {

if ( n == 0 ) return 1;

if ( n == 1 ) return 1;

return fib(n-1) + fib(n-2);

}

• Let’s start to trace it for fib(6)

72

Trace of fib(5)

fib(5)

fib(4) fib(3)

1

fib(2) fib(1) fib(1) fib(0) fib(1) fib(0)

1 1 1 1 1

fib(1) fib(0)

1 1

73

Trace of fib(5)

• For fib(5), we call fib(4) and fib(3)

– For fib(4), we call fib(3) and fib(2)

• For fib(3), we call fib(2) and fib(1)

– For fib(2), we call fib(1) and fib(0). Base cases!

– fib(1). Base case!

• For fib(2), we call fib(1) and fib(0). Base cases!

– For fib(3), we call fib(2) and fib(1)

• For fib(2), we call fib(1) and fib(0). Base cases!

• fib(1). Base case!

74

Fibonacci: recursion is a bad choice

and solved again and again

– We don’t remember that we’ve solved one of our

subproblems before

– For this problem, better to store partial solutions

instead of recalculating values repeatedly

(Dynamic programming)

– Turns out to have exponential time-complexity!

75

Non-recursive Fibonacci

• Two bottom-up iterative solutions:

– Create an array of size n, and fill with values

starting from 1 and going up to n

– Or, have a loop from small values going up, but

• only remember two previous Fibonacci values

• use them to compute the next one

• (See next slide)

76

Iterative Fibonacci

long fib(int n) {

if ( n < 2 ) return 1;

long answer;

long prevFib=1, prev2Fib=1; // fib(0) & fib(1)

for (int k = 2; k <= n; ++k) {

answer = prevFib + prev2Fib;

prev2Fib = prevFib;

prevFib = answer;

}

return answer;

}

77

Merge Sort—

A Recursive Sorting Algorithm

• Example of divide and conquer algorithm

• Recursive design:

– Divides array in half and merge sorts the

halves (decomposition)

– Combines two sorted halves

(composition)

– Array has only one element (base case)

• Harder to implement iteratively

Divide and Conquer

• It is often easier to solve several small instances of

a problem than one large one.

– divide the problem into smaller instances of the same

problem

– solve (conquer) the smaller instances recursively

– combine the solutions to obtain the solution for original

input

– Must be able to solve one or more small inputs directly

• This is an algorithm design strategy

– Computer scientists learn many more of these

79

General Strategy for Div. & Conq.

n = size(I)

if (n <= smallsize)

solution = directlySolve(I);

else

divide I into I1, …, Ik.

for each i in {1, …, k}

Si = solve(Ii);

solution = combine(S1, …, Sk);

return solution;

80

Why Divide and Conquer?

• Sometimes it’s the simplest approach

• Divide and Conquer is often more efficient than

“obvious” approaches

– E.g. BinarySearch vs. Sequential Search

– E.g. Mergesort, Quicksort vs. SelectionSort

• But, not necessarily efficient

– Might be the same or worse than another approach

• We must analyze each algorithm's time

complexity

• Note: divide and conquer may or may not be

implemented recursively

81

Top-Down Strategy

• Divide and Conquer algorithms illustrate a top-

down strategy

– Given a large problem, identify and break into smaller

subproblems

– Solve those, and combine results

• Most recursive algorithms work this way

• The alternative? Bottom-up

– Identify and solve smallest subproblems first

– Combine to get larger solutions until solve entire

problem

82

Execution Trace (decomposition)

3 6 8 2 5 4 7 1

3 6 8 2 5 4 7 1

3 6 8 2 5 4 7 1

3 6 8 2 5 4 7 1

Execution Trace (composition)

1 2 3 4 5 6 7 8

2 3 6 8 1 4 5 7

3 6 2 8 4 5 1 7

3 6 8 2 5 4 7 1

Merging Two Sorted Arrays

2

3 6 2 8

Merging Two Sorted Arrays

2 3

3 6 2 8

Merging Two Sorted Arrays

2 3 6

3 6 2 8

Merging Two Sorted Arrays

2 3 6 8

3 6 2 8

Merge Sort Algorithm

1. If array a has more than one element:

a. Copy the first half of the elements in a to array

front

b. Copy the rest of the elements in a to array tail

c. Merge Sort front

d. Merge Sort tail

e. Merge the elements in front and tail into a

2. Otherwise, do nothing

Merge Sort

void sort(int[] a)

{

do recursive case if

if (a.length >= 2)

{

true, base case if false

int halfLength = a.length / 2;

int[] front = new int[halfLength];

int[] tail = new int[a.length – halfLength];

recursive divide(a, front, tail); make "smaller"

calls sort(front); problems by

sort(tail);

dividing array

merge(a, front, tail);

} Combine the

// else do nothing. two sorted

} arrays

base case: a.length == 1 so

a is sorted and no recursive

call is necessary.

Types of Recursion

• Direct

• Indirect

• Tail

• Linear

• Tree

Direct Recursion

A C function is directly recursive if it contains an

explicit call to itself

{

if ( x <= 0 ) return x;

return foo ( x – 1);

}

Indirect Recursion

A C function foo is indirectly recursive if it contains a

call to another function that ultimately calls foo.

if (x <= 0) return {

x; return foo (y – 1);

return bar(x); }

}

Tail Recursion

A recursive function is said to be tail

recursive if there is no pending operations

performed on return from a recursive call

“return the value of the last recursive call as

the value of the function”

factorial is non-tail recursive

int factorial (int n)

{

if (n == 0) return 1;

return n * factorial(n – 1);

}

Note the “pending operation” (namely the

multiplication) to be performed on return

from each recursive call

Tail recursive factorial

int fact_aux (int n, int result) {

if (n == 1) return result;

return fact_aux (n – 1, n * result);

}

factorial (int n) {

return fact_aux (n, 1);

}

Linear Recursion

A recursive function is said to be linearly recursive when no

pending operation invokes another recursive call to the function.

{

if (n == 0) return 1;

return n * factorial ( n – 1);

}

Linear Recursive Count_42s

int count_42s(int array[ ], int n)

{

if (n == 0)

return 0;

return (count_42s( array, n-1 ) );

}

}

Tree Recursion

A recursive function is said to be tree recursive (or non-linearly

recursive when the pending operation does invoke another recursive

call to the function.

recursion.

Fibonacci Numbers

The Fibonacci numbers can be recursively

defined by the rule:

fib(n) = 0 if n is 0,

= 1 if n is 1,

= fib(n-1) + fib(n-2) otherwise

Fib(0) = 0

Fib(1) = 1

Fib(2) = Fib(1) + Fib(0) = 1

Fib(3) = Fib(2) + Fib(1) = 2

Fib(4) = Fib(3) + Fib(2) = 3

Fib(5) = Fib(4) + Fib(3) = 5

Fib(6) = Fib(5) + Fib(4) = 8

Tree Recursive Fibonacci

// Note how the pending operation (the +)

// needs a 2nd recursive call to fib

int fib(int n)

{

if (n == 0) return 0;

if (n == 1) return 1;

}

Tree Recursive Count_42s

int count_42s(int array[ ], int low, int high)

{

if ((low > high)

|| (low == high && array[low] != 42)) {

return 0 ;

}

return 1;

}

count_42s(array, 1 + (low + high)/2, high)) );

}

Converting Recursive Functions

to Tail Recursion

A non-tail recursive function can often be converted to

a tail recursive function by means of an “auxiliary”

parameter that is used to form the result.

The idea is to incorporate the pending operation into

the auxiliary parameter in such a way that the recursive

call no longer has a pending operations (is tail

recursive)

Tail Recursive Fibonacci

int fib_aux ( int n, int next, int result )

{

if ( n == 0 ) return result;

return ( fib_aux ( n - 1, next + result, next ));

}

{

return fib_aux ( n, 1, 0 );

}

Converting Tail Recursive

Functions to Iterative

Let’s assume that any tail recursive function

can be expressed in the general form

F(x){

if ( P( x ) ) return G( x );

return F ( H( x ) );

}

Tail Recursive to Iterative

(cont’d)

P( x ) is the base case of F(x)

If P(x) is true, then the value of F(x) is

the value of some other function, G(x).

the value of the function F on some other

value H(x).

Tail Recursive to Iterative

(cont’d)

F( x ) {

int temp_x;

while ( P(x) is not true ) {

temp_x = x;

x = H (temp_x);

}

return G ( x );

Example – tail recursive factorial

int fact_aux (int n, int result)

{

if (n == 1) return result;

return fact_aux (n – 1, n * result)

}

F = fact_aux

x is really two params – n and result

value of P(n, result) is value of (n == 1)

value of G(n, result) is result

value of H(n, result) is (n – 1, n * result)

Iterative factorial

int fact_aux (int n, int result) {

int temp_n, temp_result;

temp_n = n; // temp_x = x (1)

temp_result = result; // temp_x = x (2)

n = temp_n – 1; // H (temp_x) (1)

result = temp_n * temp_result; // H (temp_x) (2)

}

return result; // G (x)

}

Converting Iteration to Tail

Recursion

recursion into iteration, it’s possible to

convert any iterative loop into the

combination of a recursive function and a

call to that function

A while-loop example

The following code fragment uses a while loop to

read values into an integer array until EOF occurs,

counting the number of integers read.

nt nums [MAX];

int count = 0;

count++;

While loop example (cont’d)

The key to implementing the loop using tail recursion is to

determine which variables capture the “state” of the

computation and use these variables as parameters to the tail

recursive subprogram.

nums -- the array that stores the integers

While loop example (cont’d)

Since we are interested in getting the final value for

count, we will write a function that returns count as its

result.

If the termination condition (EOF) is not true, the

function increments count, reads a number into nums

and calls itself recursively to to input the remainder of

the numbers.

If the termination condition is true, the function simply

returns the final value of count.

While loop example (cont’d)

int read_nums (int count, int nums[ ] )

{

if (scanf (“%d”, &nums[count] != EOF))

return read_nums (count + 1, nums);

return count;

}

While loop example (cont’d)

To call the function, we must pass in the appropriate

initial values

Converting Iteration to

Tail recursion

• Determining the variables used by the

loop

• Writing tail-recursive function with one

parameter for each variable

• Using the loop-termination condition as

the base case

Converting Iteration to

Tail recursion (cont’d)

•Determining how each variable changes

from one iteration to the next and handing

the sequence of expressions that represent

those changes to the recursive call

• Replacing the iterative loop with a call to

the tail recursive function with appropriate

initial values

An exercise for the Student

Convert the following for loop that finds the maximum value in

an array to be tail recursive. Assume that the function max( )

returns the larger of the two parameters returned to it.

int max_num = nums[ 0 ];

for (j = 0; j < MAX; j++)

max_num = max (max_num, nums[ j ] );

Summary

• Recursive call: a method that calls itself

• Powerful for algorithm design at times

• Recursive algorithm design:

• Decomposition (smaller identical problems)

• Composition (combine results)

• Base case(s) (smallest problem, no recursive calls)

• Implementation

– Conditional (e.g. if) statements to separate different cases

– Avoid infinite recursion

• Problem is getting smaller (decomposition)

• Base case exists and reachable

– Composition could be tricky

• Different types of recursion.

- BIRTHDAY PARADOX – A SIMULATION OF SHARED BIRTHDAY EXPERIMENTSUploaded bydatalore
- Data Structures and Algorithms 2009-4-3 0Uploaded byAmritpaul Singh
- 10.RecursionUploaded byelemaniaq
- Chapter 05Uploaded byNguyen Phuong
- Fortran 90 Course NotesUploaded byipixuna
- SAP_LSMW_CONV_00000009Uploaded bytabish24
- B3908-90002Uploaded byTina Bose
- VHDLUploaded byRohit Choudhary
- Performance analysis of AlgorithmsUploaded bydurvasikiran
- ABAP KeywordsUploaded bymohammed573
- TDL Reference Manual 2Uploaded bypankajusb
- Plan VersionsUploaded byAnand Rishi
- Tb40laan SortUploaded byGilmer Calderon Quispe
- Chapter6 Func SimpleRecursionUploaded byMei Guan
- Assignment 7Uploaded byravichandrasadineni
- Computer Programming C-01Uploaded byshrikrush
- Gaurav Sawadekar FYMCAUploaded byAsifPathan
- Graphics lab assignmentUploaded byRitesh Srivastav
- Model Subiecte ExamenUploaded byBarbulată Arina
- 55326265-Commodore-64-Subroutine-Cookbook.pdfUploaded bybandihoot
- Recursive Linked List Recurs i OnUploaded byfembem
- IDoc, Reusable Code for Editing IdocUploaded byTaufik Kadarusman
- Lecture 1Uploaded byRakesh Kumar Nikhil
- Data Structure Question Bank (2)Uploaded byBabu Giri
- Week1 Programming Challenges 3Uploaded byhack the plannet
- Basic LogicUploaded byAhmed Said
- Python Programming QuestionsUploaded byPankaj Rai
- ArraysUploaded byMaDDY
- FortranUploaded bynikhil
- cbse curriculumUploaded byTechbuzz dav14ggm

- Handout PDSUploaded byAmbar Khetan
- proj1.pdfUploaded byMaz Har Ul
- TRANS_2DUploaded bymarcelopipo
- ClippingUploaded bysohiii
- lin1992.pdfUploaded byMaz Har Ul
- dynetxUploaded byMaz Har Ul
- Question Bank CS604BUploaded byMaz Har Ul
- CS---302.pdfUploaded byMaz Har Ul
- CS-302Uploaded byMaz Har Ul
- CS-302-(3001-(O)).pdfUploaded byMaz Har Ul
- CS-302-(O).pdfUploaded byMaz Har Ul
- CS-302 (1).pdfUploaded byMaz Har Ul
- The n-th order backward difference/sum of the discrete-variable functionUploaded byMaz Har Ul
- Discrete-variable real functionsUploaded byMaz Har Ul
- 10.1109@ATSIP.2017.8075588Uploaded byMaz Har Ul
- Cellular edge detection: Combining cellular automata and cellular learning automataUploaded byMaz Har Ul
- 07_chapter 1.pdfUploaded byMaz Har Ul
- DS 302 MI lec 1.pdfUploaded byMaz Har Ul
- CS301-lec02Uploaded byism33
- Data Structure Program Using C and CPPUploaded byMaz Har Ul
- HSRUploaded byMaz Har Ul
- 2004 Gori IcprUploaded byMaz Har Ul
- sub_ncs_301_30sep14Uploaded byNrgk Prasad
- GraphMining 01 IntroductionUploaded byMaz Har Ul
- s41044-016-0016-yUploaded byMaz Har Ul
- Lecture1 (1)Uploaded bylav
- Bresenhamcircle DerivationUploaded byMaz Har Ul
- ECCV12-lecture1Uploaded byMaz Har Ul

- HT66FU30Uploaded byDuc Vu
- Sap Gui Scripting 640Uploaded byzinderrello
- Refer en CIA Dynamic C Para RabbitUploaded bylucas_calles
- ANSYS Mechanical APDL Programmer's Manual - Release 14.pdfUploaded byprasetyo
- QL200 manual y esquematicos del entrenadorUploaded by9io
- FILESTREAMUploaded byRSQLSERVER
- LM Appendix AUploaded bymnahas84
- Recovery of a 3G MMI 3GP and MMI HDD from a Carson crash patch by Walawa75.docxUploaded byJOHNNY5377
- a8r32 Mvp DeluxeUploaded bysebastyan_v5466
- 046_SampleInterviewQuestionBook(1)Uploaded bycrazykoekie
- AIX Version 5.3 Performance ManagementUploaded byanghockbin
- HP Certified Professional Available CertificationsUploaded byVikram Singh
- 50033bUploaded byAline Rabelo
- Wp f ControlsUploaded byTrần Thanh Lợi
- Spring 2010 MidTerm OPKST CS501Uploaded byrung_baaz
- c ProgrammingUploaded byAnjalee Prabha
- Changing FP for EnodeBUploaded byalin7777
- Edk500 Guide English 3.0Uploaded byFabio Avanci
- Atmeljournalnewsletterauto SecurityUploaded bymuliams33
- Odd-numbered Review Question AnswersUploaded byEugune Chow Mun Wai
- Naresh Database AdministratorUploaded byThalaSridhar
- Lecture 1 - IntroductionUploaded byPavithra Madhuwanthi
- Cam 034Uploaded byToan Pham
- DS410Uploaded bylaratoral
- 100 C interview questions and answers - C online test.pdfUploaded byRoshni Khurana
- Huawei AR1200 Series Enterprise RoutersUploaded byElizabeth Rich
- Sip-Dect Om System Manual r30aUploaded byВладиславК.
- ProgrammingExerciseAnswers SelectedUploaded byAditya Shekhawat
- Python Chapter 04 While Loop NotesUploaded byfdgdfg
- BrocadeVDX6740_SCG1020.pdfUploaded bynarasimhakolli46

## Much more than documents.

Discover everything Scribd has to offer, including books and audiobooks from major publishers.

Cancel anytime.