Recursion

20
Recursion CS 367 – Introduction to Data Structures

description

Recursion. CS 367 – Introduction to Data Structures. Definition. Mathematically a recursive function is one that is defined in terms of an absolute case and itself example. 1n = 0 n*(n-1)!n > 0. n =. Consider n = 3: n result 0!1 1!1 * 0! = 1 2!2 * 1! = 2 3!3 * 2! = 6. - PowerPoint PPT Presentation

Transcript of Recursion

Page 1: Recursion

Recursion

CS 367 – Introduction to Data Structures

Page 2: Recursion

Definition• Mathematically

– a recursive function is one that is defined in terms of an absolute case and itself

– example

n =1 n = 0n*(n-1)! n > 0

Consider n = 3:n result0! 11! 1 * 0! = 12! 2 * 1! = 23! 3 * 2! = 6

Page 3: Recursion

Definition

• Programming– a recursive function is one that knows the

answer to a specific case; in all other cases, the function calls itself again

– exampleint factorial(int n) {

if(n == 0)

return 1;

else

return n * factorial(n – 1);

}

Page 4: Recursion

Function Call

• To understand recursion, we need a better idea of what happens on a function call– remember the program stack?

• on a function call, the compiler creates an activation record

– parameters passed in– local variables– return address– return value (where applicable)

• activation record gets pushed on the program stack

Page 5: Recursion

Activation Records

main()

f1()

f2()

f3()

return valuereturn addresslocal variables

parametersreturn value

return addresslocal variables

parametersreturn value

return addresslocal variables

parameters

Page 6: Recursion

Calling a Function

• The program compiler takes care of building the activation record for each function– this means you don’t have to worry about

writing it– it also means that a single function call is

really a lot more code than you think• this means it takes awhile to do

Page 7: Recursion

Calling a Function

• High level codevoid main() { int z = double(5);}

int double(int x) { int y = x * 2; return y;}

• Compiler code# mainld r1, 5push addrpush r1jmp # double

# doublepop r2mult r3, r2, 2pop r2push r3jmp r2

Page 8: Recursion

Calling a Function• The previous compiler code is very incomplete

(and not quite correct either )• Previous code does prove a point

– calling a function requires more memory• must create and store the activation record

– calling a function takes more time• must run extra code to build the activation record

• Fastest program would be one that only had a main function– this is very unrealistic – why?– if it were easy to do, still would be a bad idea – why?

Page 9: Recursion

Anatomy of a Recursive Call

• Consider the factorial example used earlier

int factorial(int n) {if(n == 0) { return 1; }else { return n * factorial(n-1); }

}

• Now consider the following code for main()void main() {

int f = factorial(3);print(f);

}

Page 10: Recursion

Anatomy of a Recursive Call

main() main()

factorial(3)

n = 3ret = 3 * f2

f =

f1()

main()

factorial(2)

n = 3ret = 3 * f2 f1()

n = 2ret = 2 * f3 f2()

main()

factorial(1)

n = 3ret = 3 * f2 f1()

n = 2ret = 2 * f3 f2()

n = 1ret = 1 * f4 f3()

main()

factorial(0)

n = 3ret = 3 * f1()

n = 2ret = 2 * f2()

n = 1ret = 1 * f3()

n = 0ret = 1 f3()

main()

return

n = 3ret = 3 * f2 f1()

n = 2ret = 2 * f3 f2()

n = 1ret = 1 * 1 f3()

main()

return

n = 3ret = 3 * f2 f1()

n = 2ret = 2 * 1 f2()

f = f = f =

f = f = f = main()

return

n = 3ret = 3 * 2 f1()

f =

Page 11: Recursion

Anatomy of a Recursive Call

• Obviously, the last step in the previous example is missing (not enough room)– f1 will return 6 and the value (f) in main will be

equal to 6

• Major point– using recursion can get very expensive

• consume lots of memory• execute a lot of extra instructions

– what is the alternative?

Page 12: Recursion

Loops

• Almost any recursive function can be re-written as a loop– a loop will be much less time consuming

• no extra activation records to construct and store

– consider the factorial example one last timeint factorial(int n) {

int sum = 1;for(int i=1; i<=n; i++)

sum *= i;return sum;

}

Page 13: Recursion

Loops

• Notice no function calls inside this version of factorial()– will run much faster than the recursive version

• Why use recursion?– in some cases it is easier to understand and

write a recursive function

Page 14: Recursion

Reverse()

• Consider a function that prints a string of characters in the reverse order– ABC will be printed out as CBA

void reverse() {

char ch = getChar();

if(ch != ‘\n’) {

reverse();

System.out.println(ch);

}

}

Page 15: Recursion

Reverse()

• Note that this recursive function doesn’t return anything– simply reads a character and waits to print it

until the one after it is printed• very easy to understand• very quick to program

– how would you convert this to an iterative solution?

Page 16: Recursion

Reverse()

• Sol’n in Java

void reverse() {

String stack = new String();

stack = buffer.readLine();

for(top=stack.length()-1; top>=0; top--)

System.out.print(stack.charAt(top));

}

• Sol’n in C/C++

void reverse() {

char stack[80];

int top=0;

stack[top] = getch();

while(stack[top] != ‘\n’)

stack[++top] = getch();

for(top -= 1; top >= 0; top--)

System.out.print(stack[top]);

}

Page 17: Recursion

Reverse()• Iterative sol’n must first read whole string into

memory– then it can use a loop to print the string out– Java sol’n looks so simple because of the

String.length() operator• it tells us exactly how long the string is• many languages don’t have this feature

• There are fewer steps and less code in the recursive sol’n– because we’re interacting with I/O, recursive nature

isn’t such a big deal• why?

Page 18: Recursion

Backtracing

• One of the best uses of recursion is in navigating a large, directed search space– in other words, if you are at a certain point, P, in the

search space, you need to pick the next spot to search

• if you go in one direction, you can only go back the other direction by first returning to point P

– examples• finding a path from one city to another• 8 queens example• best move in a game• searching through a tree data structure (next week)

Page 19: Recursion

Finding a Path

• Consider the graph of flights from the lecture on stacks

PR

X Q

W

Y

Z

S

T

Key : city (represented as C)

: flight from city C1 to city C2C1 C2

flight goes from W to SW S

Example

Page 20: Recursion

Finding a Path

• We showed how to use a stack to find a route from P to Y

• We can also do it using recursionpublic boolean findPath(City origin, City destination) {

// pick a possible city to go to – make that city the origin

if(findPath(nextCity, destination))// found the city

else// that path didn’t work, try another one

}

• The above recursive sol’n is still going to need some kind of loop inside it– have to check all the possible routes from a city