34
Recursion Recursion The Power of Calling a Method from The Power of Calling a Method from Itself Itself Svetlin Nakov Svetlin Nakov Telerik Telerik Corporation Corporation www.telerik. com

10. Recursion

Embed Size (px)

DESCRIPTION

Introduction to Recursion: What is it? Direct and Indirect Recursion Calculating Factorial Recursively and Iteratively Recursive Combinatorial Algorithms: Simulated N Nested Loops Recursion vs. Iteration and When to Use Recursion? Exercises: Implementing Recursive Algorithms

Citation preview

Page 1: 10. Recursion

RecursionRecursionThe Power of Calling a Method from The Power of Calling a Method from

ItselfItself

Svetlin NakovSvetlin NakovTelerik Telerik

CorporationCorporationwww.telerik.com

Page 2: 10. Recursion

Table of ContentsTable of Contents

1.1. What is Recursion?What is Recursion?

2.2. Calculating Factorial RecursivelyCalculating Factorial Recursively

3.3. Generating All 0/1 Vectors Generating All 0/1 Vectors RecursivelyRecursively

4.4. Finding All Paths in a Labyrinth Finding All Paths in a Labyrinth RecursivelyRecursively

5.5. Recursion or Iteration?Recursion or Iteration?

2

Page 3: 10. Recursion

What is Recursion?What is Recursion? RecursionRecursion is when a methods calls is when a methods calls

itselfitself Very powerful technique for Very powerful technique for

implementing combinatorial and other implementing combinatorial and other algorithmsalgorithms

Recursion should haveRecursion should have Direct or indirect recursive callDirect or indirect recursive call

The method calls itself directly or The method calls itself directly or through other methodsthrough other methods

Exit criteria (bottom)Exit criteria (bottom)

Prevents infinite recursionPrevents infinite recursion 3

Page 4: 10. Recursion

Recursive Factorial – Recursive Factorial – ExampleExample

Recursive definition of Recursive definition of n!n! ( (n n factorialfactorial):):n! = n * (n–1)! for n >= 0n! = n * (n–1)! for n >= 00! = 10! = 1

5! = 5 * 4! = 5 * 4 * 3 * 2 * 1 * 1 = 5! = 5 * 4! = 5 * 4 * 3 * 2 * 1 * 1 = 120120

4! = 4 * 3! = 4 * 3 * 2 * 1 * 1 = 244! = 4 * 3! = 4 * 3 * 2 * 1 * 1 = 24

3! = 3 * 2! = 3 * 2 * 1 * 1 = 63! = 3 * 2! = 3 * 2 * 1 * 1 = 6

2! = 2 * 1! = 2 * 1 * 1 = 22! = 2 * 1! = 2 * 1 * 1 = 2

1! = 1 * 0! = 1 * 1 = 11! = 1 * 0! = 1 * 1 = 1

0! = 10! = 1 4

Page 5: 10. Recursion

Recursive Factorial – Recursive Factorial – ExampleExample

Calculating factorial:Calculating factorial: 00! = ! = 11

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

Don't try this at home!Don't try this at home! Use iteration insteadUse iteration instead

static decimal Factorial(decimal num)static decimal Factorial(decimal num)

{{

if (num == 0) if (num == 0)

return 1; return 1;

else else

return num * Factorial(num - 1); return num * Factorial(num - 1);

} }

The The bottom of bottom of

the the recursionrecursion

Recursive Recursive call: the call: the

method calls method calls itselfitself

5

Page 6: 10. Recursion

Recursive Recursive FactorialFactorialLive Live

DemoDemo

Page 7: 10. Recursion

Generating 0/1 VectorsGenerating 0/1 Vectors How to generate all 8-bit vectors How to generate all 8-bit vectors

recursively?recursively?

0000000000000000

0000000100000001

......

0111111101111111

1000000010000000

......

1111111011111110

1111111111111111

How to generate all n-bit vectors?How to generate all n-bit vectors? 7

Page 8: 10. Recursion

Algorithm Algorithm Gen01(n)Gen01(n): put : put 00 and and 11 at the at the last position last position nn and call and call Gen01(n-1)Gen01(n-1) for for the rest:the rest:

Generating 0/1 Vectors Generating 0/1 Vectors (2)(2)

8

xx xx xx xx xx xx 00

Gen01(6):Gen01(6):

Gen01(5)Gen01(5)

xx xx xx xx xx xx 11

Gen01(5)Gen01(5)

xx xx xx xx xx 00 yy

Gen01(5):Gen01(5):

Gen01(4)Gen01(4)

xx xx xx xx xx 11 yy

Gen01(4)Gen01(4)

......Gen01(-1) Gen01(-1) Stop!Stop!

Page 9: 10. Recursion

Generating 0/1 Vectors Generating 0/1 Vectors (3)(3)

static void Gen01(int index, int[] vector)static void Gen01(int index, int[] vector){{ if (index == -1)if (index == -1) Print(vector);Print(vector); elseelse for (int i=0; i<=1; i++)for (int i=0; i<=1; i++) {{ vector[index] = i;vector[index] = i; Gen01(index-1, vector);Gen01(index-1, vector); }}}}

static void Main()static void Main(){{ int size = 8;int size = 8; int[] vector = new int[size];int[] vector = new int[size]; Gen01(size-1, vector);Gen01(size-1, vector);}}

9

Page 10: 10. Recursion

Generating 0/1 Generating 0/1 VectorsVectors

Live DemoLive Demo

Page 11: 10. Recursion

Finding All Paths in a Finding All Paths in a LabyrinthLabyrinth

We are given a labyrinthWe are given a labyrinth Represented as matrix of cells of Represented as matrix of cells of

size M x Nsize M x N Empty cells are passable, the others Empty cells are passable, the others

(*) are not(*) are not We start from the top left corner We start from the top left corner

and can move in the all and can move in the all 44 directions: left, right, up, downdirections: left, right, up, down

We need to find all paths to the We need to find all paths to the bottom right cornerbottom right corner

11

Start Start positipositi

ononEnd End

positipositionon

**

** ** ** **

** ** ** ** **

Page 12: 10. Recursion

Finding All Paths in a Finding All Paths in a Labyrinth (2)Labyrinth (2)

There are 3 different paths from There are 3 different paths from the top left corner to the bottom the top left corner to the bottom right corner:right corner:

12

00 11 22 **

** ** 33 ** **

66 55 44

77 ** ** ** ** **

88 99 1010 1111 1212 1313 1414

00 11 22 ** 88 99 1010

** ** 33 ** 77 ** 1111

44 55 66 1212

** ** ** ** ** 1313

1414

1) 2)

00 11 22 **

** ** 33 ** **

44 55 66 77 88

** ** ** ** ** 99

1010

3)

Page 13: 10. Recursion

Finding All Paths in a Finding All Paths in a Labyrinth (2)Labyrinth (2)

Suppose we have an algorithm Suppose we have an algorithm FindExit(x,y)FindExit(x,y) that finds and prints all paths to the exit that finds and prints all paths to the exit (bottom right corner) starting from position (bottom right corner) starting from position (x,y)(x,y)

If If (x,y)(x,y) is not passable, no paths are found is not passable, no paths are found If If (x,y)(x,y) is already visited, no paths are is already visited, no paths are

foundfound Otherwise:Otherwise:

Mark position Mark position (x,y)(x,y) as visited (to avoid cycles) as visited (to avoid cycles)

Find all paths to the exit from all neighbor cells:Find all paths to the exit from all neighbor cells: (x-1,y)(x-1,y) , , (x+1,y) (x+1,y) , , (x,y+1) (x,y+1) , , (x,y-1) (x,y-1)

Mark position Mark position (x,y)(x,y) as free (can be visited again) as free (can be visited again)

13

Page 14: 10. Recursion

Representing the labyrinth as matrix of Representing the labyrinth as matrix of characters (in this example characters (in this example 55 rows and rows and 77 columns):columns):

Spaces ('Spaces (' ') are passable cells') are passable cells Asterisks ('Asterisks ('**') are not passable cells') are not passable cells The symbol 'The symbol 'ee' is the exit (can be multiple)' is the exit (can be multiple)

Find All Paths: Find All Paths: AlgorithmAlgorithm

14

static char[,] lab = static char[,] lab = {{ {' ', ' ', ' ', '*', ' ', ' ', ' '},{' ', ' ', ' ', '*', ' ', ' ', ' '}, {'*', '*', ' ', '*', ' ', '*', ' '},{'*', '*', ' ', '*', ' ', '*', ' '}, {' ', ' ', ' ', ' ', ' ', ' ', ' '},{' ', ' ', ' ', ' ', ' ', ' ', ' '}, {' ', '*', '*', '*', '*', '*', ' '},{' ', '*', '*', '*', '*', '*', ' '}, {' ', ' ', ' ', ' ', ' ', ' ', 'е'},{' ', ' ', ' ', ' ', ' ', ' ', 'е'},};};

Page 15: 10. Recursion

Find All Paths: Find All Paths: Algorithm (2)Algorithm (2)

15

static void FindExit(int row, int col)static void FindExit(int row, int col){{ if ((col < 0) || (row < 0) || (col >= if ((col < 0) || (row < 0) || (col >= lab.GetLength(1))lab.GetLength(1)) || (row >= lab.GetLength(0)))|| (row >= lab.GetLength(0))) {{ // We are out of the labyrinth -> can't find a // We are out of the labyrinth -> can't find a pathpath return;return; }}

// Check if we have found the exit// Check if we have found the exit if (lab[row, col] == 'е') if (lab[row, col] == 'е') {{ Console.WriteLine("Found the exit!");Console.WriteLine("Found the exit!"); }}

if (lab[row, col] != ' ')if (lab[row, col] != ' ') {{ // The current cell is not free -> can't find a // The current cell is not free -> can't find a pathpath return;return; }} (example continues)(example continues)

Page 16: 10. Recursion

Find All Paths: Find All Paths: Algorithm (3)Algorithm (3)

16

// Temporary mark the current cell as visited// Temporary mark the current cell as visited

lab[row, col] = 's';lab[row, col] = 's';

// Invoke recursion the explore all possible // Invoke recursion the explore all possible

directionsdirections

FindExit(row, col-1); // leftFindExit(row, col-1); // left

FindExit(row-1, col); // upFindExit(row-1, col); // up

FindExit(row, col+1); // rightFindExit(row, col+1); // right

FindExit(row+1, col); // downFindExit(row+1, col); // down

// Mark back the current cell as free// Mark back the current cell as free

lab[row, col] = ' ';lab[row, col] = ' ';

}}

static void Main()static void Main()

{{

FindExit(0, 0);FindExit(0, 0);

}}

Page 17: 10. Recursion

Find All Paths in a Find All Paths in a LabyrinthLabyrinth

Live DemoLive Demo

Page 18: 10. Recursion

How to print all paths found by our How to print all paths found by our recursive algorithm?recursive algorithm? Each move's direction can be stored in Each move's direction can be stored in

arrayarray

Need to pass the movement direction at Need to pass the movement direction at each recursive calleach recursive call

At the start of each recursive call the At the start of each recursive call the current direction is appended to the arraycurrent direction is appended to the array

At the end of each recursive call the last At the end of each recursive call the last direction is removed form the arraydirection is removed form the array

Find All Paths and Print Find All Paths and Print ThemThem

18

static char[] path = static char[] path = new char[lab.GetLength(0) * new char[lab.GetLength(0) * lab.GetLength(1)];lab.GetLength(1)];static int position = 0;static int position = 0;

Page 19: 10. Recursion

Find All Paths and Print Find All Paths and Print Them (2)Them (2)

19

static void FindPathToExit(int row, int col, char static void FindPathToExit(int row, int col, char direction)direction){{ ...... // Append the current direction to the path// Append the current direction to the path path[position++] = direction;path[position++] = direction;

if (lab[row, col] == 'е')if (lab[row, col] == 'е') {{ // The exit is found -> print the current path// The exit is found -> print the current path }} ......

// Recursively explore all possible directions// Recursively explore all possible directions FindPathToExit(row, col - 1, 'L'); // leftFindPathToExit(row, col - 1, 'L'); // left FindPathToExit(row - 1, col, 'U'); // upFindPathToExit(row - 1, col, 'U'); // up FindPathToExit(row, col + 1, 'R'); // rightFindPathToExit(row, col + 1, 'R'); // right FindPathToExit(row + 1, col, 'D'); // downFindPathToExit(row + 1, col, 'D'); // down ......

// Remove the last direction from the path// Remove the last direction from the path position--;position--;}}

Page 20: 10. Recursion

Find and Print Find and Print All Paths in a All Paths in a

LabyrinthLabyrinthLive DemoLive Demo

Page 21: 10. Recursion

Recursion or Recursion or Iteration?Iteration?When to Use and When to Avoid When to Use and When to Avoid

Recursion?Recursion?

Page 22: 10. Recursion

Recursion Can be Recursion Can be Harmful!Harmful!

When used incorrectly the recursion When used incorrectly the recursion could take too much memory and could take too much memory and computing powercomputing power

Example:Example:static decimal Fibonacci(int n)static decimal Fibonacci(int n){{ if ((n == 1) || (n == 2))if ((n == 1) || (n == 2)) return 1;return 1; elseelse return Fibonacci(n - 1) + Fibonacci(n - 2);return Fibonacci(n - 1) + Fibonacci(n - 2);}}

static void Main()static void Main(){{ Console.WriteLine(Fibonacci(10)); // 89Console.WriteLine(Fibonacci(10)); // 89 Console.WriteLine(Fibonacci(50)); // This will Console.WriteLine(Fibonacci(50)); // This will hang!hang!}} 22

Page 23: 10. Recursion

Harmful RecursionHarmful RecursionLive DemoLive Demo

Page 24: 10. Recursion

How the Recursive How the Recursive Fibonacci Calculation Fibonacci Calculation

Works?Works?

24

fib(n) makes about fib(n) recursive callsfib(n) makes about fib(n) recursive calls The same value is calculated many, many times!The same value is calculated many, many times!

Page 25: 10. Recursion

Fast Recursive Fast Recursive FibonacciFibonacci

Each Fibonacci sequence member Each Fibonacci sequence member can be remembered once it is can be remembered once it is calculatedcalculated Can be returned directly when Can be returned directly when

needed againneeded again

25

static decimal[] fib = new decimal[MAX_FIB];static decimal[] fib = new decimal[MAX_FIB];static decimal Fibonacci(int n)static decimal Fibonacci(int n){{ if (fib[n] == 0)if (fib[n] == 0) {{ // The value of fib[n] is still not calculated// The value of fib[n] is still not calculated if ((n == 1) || (n == 2))if ((n == 1) || (n == 2)) fib[n] = 1;fib[n] = 1; elseelse fib[n] = Fibonacci(n - 1) + Fibonacci(n - fib[n] = Fibonacci(n - 1) + Fibonacci(n - 2);2); }} return fib[n];return fib[n];}}

Page 26: 10. Recursion

Fast Recursive Fast Recursive FibonacciFibonacci

Live DemoLive Demo

Page 27: 10. Recursion

When to Use When to Use Recursion?Recursion?

Avoid recursion when an obvious Avoid recursion when an obvious iterative algorithm existsiterative algorithm exists Examples: factorial, Fibonacci numbersExamples: factorial, Fibonacci numbers

Use recursion for combinatorial algorithm Use recursion for combinatorial algorithm where at each step you need to where at each step you need to recursively explore more than one recursively explore more than one possible continuationpossible continuation Examples: permutations, all paths in Examples: permutations, all paths in

labyrinthlabyrinth

If you have only one recursive call in the If you have only one recursive call in the body of a recursive method, it can directly body of a recursive method, it can directly become iterative (like calculating factorial)become iterative (like calculating factorial)

27

Page 28: 10. Recursion

SummarySummary Recursion means to call a method from Recursion means to call a method from

itselfitself It should always have a bottom at which It should always have a bottom at which

recursive calls stoprecursive calls stop Very powerful technique for Very powerful technique for

implementing combinatorial algorithmsimplementing combinatorial algorithms Examples: generating combinatorial Examples: generating combinatorial

configurations like permutations, configurations like permutations, combinations, variations, etc.combinations, variations, etc.

Recursion can be harmful when not Recursion can be harmful when not used correctlyused correctly

28

Page 29: 10. Recursion

QuestionsQuestions??

RecursionRecursion

http://academy.telerik.com

Page 30: 10. Recursion

ExercisesExercises

1.1. Write a recursive program that simulates Write a recursive program that simulates execution of n nested loops from 1 to n. execution of n nested loops from 1 to n. Examples:Examples:

1 1 11 1 1

1 1 21 1 2

1 1 31 1 3

1 1 1 2 11 1 1 2 1

n=2 -> 1 2 n=3 -> ...n=2 -> 1 2 n=3 -> ...

2 1 3 2 32 1 3 2 3

2 2 3 3 12 2 3 3 1

3 3 23 3 2

3 3 33 3 3 30

Page 31: 10. Recursion

Exercises (2)Exercises (2)

2.2. Write a recursive program for generating and Write a recursive program for generating and

printing all the combinations with duplicates printing all the combinations with duplicates

of k elements from n-element set. Example:of k elements from n-element set. Example:

n=3, k=2 n=3, k=2 (1 1), (1 2), (1 3), (2 2), (2 3), (3 (1 1), (1 2), (1 3), (2 2), (2 3), (3

3)3)

3.3. Write a recursive program for generating and Write a recursive program for generating and

printing all permutations of the numbers 1, 2, printing all permutations of the numbers 1, 2,

..., n for given integer number n. Example:..., n for given integer number n. Example:

n=3 n=3 {1, 2, 3}, {1, 3, 2}, {2, 1, 3}, {1, 2, 3}, {1, 3, 2}, {2, 1, 3},

{2, 3, 1}, {3, 1, 2},{3, 2, 1}{2, 3, 1}, {3, 1, 2},{3, 2, 1}

31

Page 32: 10. Recursion

Exercises (3)Exercises (3)

4.4. Write a recursive program for generating Write a recursive program for generating and printing all ordered k-element subsets and printing all ordered k-element subsets from n-element set from n-element set (variations V(variations Vkk

nn).).

Example: n=3, k=2Example: n=3, k=2

(1 1), (1 2), (1 3), (2 1), (2 2), (2 3), (3 1), (1 1), (1 2), (1 3), (2 1), (2 2), (2 3), (3 1), (3 2), (3 3)(3 2), (3 3)

5.5. Write a program for generating and Write a program for generating and printingprinting all all subsetssubsets of of k strings from k strings from given given set of strings.set of strings.

Example: s = {test, Example: s = {test, rockrock, , funfun}}, k=2, k=2

(test (test rockrock)),, (test (test funfun)),, ( (rockrock funfun))32

Page 33: 10. Recursion

Exercises (4)Exercises (4)

6.6. We are given a matrix of passable and non-We are given a matrix of passable and non-passable cells. Write a recursive program for passable cells. Write a recursive program for finding all paths between two cells in the finding all paths between two cells in the matrix.matrix.

7.7. Modify the above program to check whether a Modify the above program to check whether a path exists between two cells without finding path exists between two cells without finding all possible paths. Test it over an empty 100 x all possible paths. Test it over an empty 100 x 100 matrix.100 matrix.

8.8. Write a program to find the largest connected Write a program to find the largest connected area of adjacent empty cells in a matrix.area of adjacent empty cells in a matrix.

9.9. Implement the BFS algorithm to find the Implement the BFS algorithm to find the shortest path between two cells in a matrix shortest path between two cells in a matrix (read about (read about Breath-First Search in Wikipedia). in Wikipedia).

33

Page 34: 10. Recursion

Exercises (5)Exercises (5)

6.6. We are given a matrix of passable and We are given a matrix of passable and non-passable cells. Write a recursive non-passable cells. Write a recursive program for finding all areas of program for finding all areas of passable cells in the matrix.passable cells in the matrix.

10.10.Write a recursive program that Write a recursive program that traverses the entire hard disk drive C:\ traverses the entire hard disk drive C:\ and displays all folders recursively and and displays all folders recursively and all files inside each of them.all files inside each of them.

34