2 views

Uploaded by Maz Har Ul

Recursion -Data Structure Lecture

- notes.pdf
- mmthemas_lisp3
- Algorithms Interview Questions
- 01 DS and Algorithm Session 01
- emb-reportmm
- Week1 Programming Challenges 3
- c coding
- Find Path
- Sample Test 3
- adu
- CProgrammingPart2
- Unit 10 - Algorithms
- Data Structure
- Type Conversions and FunctionsCSE
- Assignment of Algorithms TB
- selection sort sda.docx
- How to prepare for an interview at Google.
- Data Structures Programs
- Ccodechamp Com c Program of Newton Raphson Method c Code Cha
- As IEC 61131.8-2004 Programmable Controllers Guidelines for the Application and Implementation of Programming

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.

- notes.pdfUploaded bynaga7389
- mmthemas_lisp3Uploaded byOgnjenOklobdzija
- Algorithms Interview QuestionsUploaded bySileshiNibret
- 01 DS and Algorithm Session 01Uploaded byDaya Nand Mishra
- emb-reportmmUploaded byMohammad Akeel Khan
- Week1 Programming Challenges 3Uploaded byhack the plannet
- c codingUploaded byanurag_gdu
- Find PathUploaded byrharitechie
- Sample Test 3Uploaded byMohamed Taha
- aduUploaded byAlka Chopra
- CProgrammingPart2Uploaded byEthan Hunt
- Unit 10 - AlgorithmsUploaded byJun Min Noh
- Data StructureUploaded byPiyush Bhardwaj
- Type Conversions and FunctionsCSEUploaded byR ANVESH
- Assignment of Algorithms TBUploaded byMukesh Kumar
- selection sort sda.docxUploaded byMamnuah F-zahra Matikamatika
- How to prepare for an interview at Google.Uploaded byShashi Kolar
- Data Structures ProgramsUploaded byPrabhu
- Ccodechamp Com c Program of Newton Raphson Method c Code ChaUploaded byLokesh Singh
- As IEC 61131.8-2004 Programmable Controllers Guidelines for the Application and Implementation of ProgrammingUploaded bySAI Global - APAC
- Mathematics - Fourier Transforms Using MATLABUploaded byapi-3833675
- IntersectionUploaded byjohnny kalue
- Formating DatastructureUploaded bymahi_meg
- Comparison Table Load (CTBL),Instruksi dasar PLCUploaded byMad Atmadi
- C++indexUploaded byHarsimran Kapoor
- ICT 34 Data Structures and Analysis of AlgorithmUploaded byChristian
- Amity Course structurefor Data strucutre 2015Uploaded byAakash Sehrawat
- Bruteforce_ExhaustiveSearchUploaded byMd. Abdul Mukit
- Computer Science 70 UC Berkeley note 5Uploaded byThomas Smith
- Adr Function Library RegUploaded byimaarha

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

- TypeScript TutorialUploaded bysivakumar
- C++ Notes for ProfessionalsUploaded byPeter Ranieri
- JAVA-CH5Uploaded byNeha Naik
- Function Block Lnguaje CUploaded byIsidro Igigi Hernández
- Function in C programUploaded byaarthi dev
- 18306_L14-Exception Handling.pptUploaded byVinay Prakash
- Robot FrameworkUploaded byGramo
- Event and Listener.docxUploaded byDaksh Mathur
- A Little C PrimerUploaded byFon Pcb
- CS6311 PDS_LAB_MANUAL.pdfUploaded byManishDp
- JAVA STDSUploaded bySreenivasa Reddy Gopireddy
- p - Ejemplos de Macros InglesUploaded byRommel Heredia Tejada
- Dangling Pointer Memory Leak in CUploaded byNaga Pradeep Veerisetty
- Dart Lang SpecUploaded byardnetij20049445
- 02 Implementation of OOP concept in C++Uploaded byamishadalal
- Ansi c Grammar YaccUploaded byRohitRoy91
- How Do I Get the Name of an Object's Type in JavaScript_ - Stack OverflowUploaded bymadscijr
- C sharp 7Uploaded byRafael
- RPGLE - Converting Numeric to AlphaUploaded byshushruthaa
- Delegates and Events.pptUploaded byanupama17sept
- final-blackjackUploaded byapi-359332959
- Factory Method.pptxUploaded byAqib Shafique
- C++ NOTESUploaded bySulaimankhalid Khalid
- TestUploaded byIoana Loredana Teodorescu
- MELJUN CORTES Programming Languages SubprogramsUploaded byMELJUN CORTES, MBA,MPA
- TreesUploaded byLalit Sharma
- Sect 5 SubroutinesUploaded byTRUNG QUOC LE
- Java Chap6 Decision Making Statements ( Prof. Ananda M Ghosh.)Uploaded byProf. (Dr) Ananda M Ghosh.
- CPP.pdfUploaded byMurali Chinni
- passing object as argument in c++Uploaded bysauravnaruka