Recursion Recursive Algorithms and Backtracking SoftUni Team Technical Trainers Software University

Slides:



Advertisements
Similar presentations
The Power of Calling a Method from Itself Svetlin Nakov Telerik Corporation
Advertisements

Svetlin Nakov Telerik Software Academy academy.telerik.com Technical Trainer The Power of the Recursive Algorithms.
JavaScript Basics Course Introduction SoftUni Team Technical Trainers Software University
Software Quality Assurance QA Engineering, Testing, Bug Tracking, Test Automation Software University Technical Trainers SoftUni Team.
 Dimitar Ivanov Introduction to programming with microcontrollers.
C# Advanced Topics Methods, Classes and Objects SoftUni Team Technical Trainers Software University
Methods Writing and using methods, overloads, ref, out SoftUni Team Technical Trainers Software University
Software University Curriculum, Courses, Exams, Jobs SoftUni Team Technical Trainers Software University
Fundamentals SoftUni Welcome to Software University SoftUni Team Technical Trainers Software University
Project Tracking Tools Trello, Asana, Basecamp, GitHub Issue Tracker, TRAC SoftUni Team Technical Trainers Software University
Software Testing Lifecycle Exit Criteria Evaluation, Continuous Integration Ivan Yonkov Technical Trainer Software University.
Teamwork and Personal Skills Course Introduction Software University SoftUni Team Technical Trainers.
NoSQL Databases NoSQL Concepts SoftUni Team Technical Trainers Software University
Conditional Statements Implementing Control-Flow Logic in C# SoftUni Team Technical Trainers Software University
Loops Repeating Code Multiple Times SoftUni Team Technical Trainers Software University
Database APIs and Wrappers
Entity Framework Performance SoftUni Team Technical Trainers Software University
Methods, Arrays, Lists, Dictionaries, Strings, Classes and Objects
Svetlin Nakov Technical Trainer Software University
Build Processes and Continuous Integration Automating Build Processes Software University Technical Trainers SoftUni Team.
Multidimensional Arrays, Sets, Dictionaries Processing Matrices, Multidimensional Arrays, Dictionaries, Sets SoftUni Team Technical Trainers Software University.
Test-Driven Development Learn the "Test First" Approach to Coding SoftUni Team Technical Trainers Software University
Static Members and Namespaces Static Members, Indexers, Operators, Namespaces SoftUni Team Technical Trainers Software University
Graphs and Graph Algorithms Fundamentals, Terminology, Traversal, Algorithms SoftUni Team Technical Trainers Software University
Arrays, Lists, Stacks, Queues Processing Sequences of Elements SoftUni Team Technical Trainers Software University
Very Basic Mathematical Concepts for Programmers
Asynchronous Web Services Writing Asynchronous Web Services SoftUni Team Technical Trainers Software University
C# Basics Course Introduction Svetlin Nakov Technical Trainer Software University
Jekyll Static Site Generator Template-Based Site Generation Svetlin Nakov Technical Trainer Software University
Responsive Design Design that Adapts to Different Devices SoftUni Team Technical Trainers Software University
Exam Preparation Algorithms Course: Sample Exam SoftUni Team Technical Trainers Software University
Tables, Rows, Columns, Cells, Header, Footer, Colspan, Rowspan
High-Quality Code: Course Introduction Course Introduction SoftUni Team Technical Trainers Software University
Design Patterns: Structural Design Patterns General and reusable solutions to common problems in software design Software University
Advanced C# Course Introduction SoftUni Team Technical Trainers Software University
Object-Oriented Programming Course Introduction Svetlin Nakov Technical Trainer Software University
Mocking with Moq Tools for Easier Unit Testing SoftUni Team Technical Trainers Software University
Operators and Expressions
Data Structures Curriculum, Trainers, Evaluation, Exams SoftUni Team Technical Trainers Software University
Mocking Unit Testing Methods with External Dependencies SoftUni Team Technical Trainers Software University
Mocking with Moq Mocking tools for easier unit testing Svetlin Nakov Technical Trainer Software University
Test-Driven Development Learn the "Test First" Approach to Coding Svetlin Nakov Technical Trainer Software University
Programming for Beginners Course Introduction SoftUni Team Technical Trainers Software University
Processing Sequences of Elements
Objects and Classes Using Objects and Classes Defining Simple Classes SoftUni Team Technical Trainers Software University
Sets, Dictionaries SoftUni Team Technical Trainers Software University
Lists and Matrices Lists: Variable-Size Arrays Matrices: Arrays of Arrays (Tables) SoftUni Team Technical Trainers Software University
SoftUni Team Technical Trainers Software University Trees and Tree-Like Structures Trees, Tree-Like Structures, Binary Search Trees,
High-Quality Code: Course Introduction Course Introduction SoftUni Team Technical Trainers Software University
Advanced Tree Structures Binary Trees, AVL Tree, Red-Black Tree, B-Trees, Heaps SoftUni Team Technical Trainers Software University
Functional Programming Data Aggregation and Nested Queries Ivan Yonkov Technical Trainer Software University
Programming Fundamentals Course Introduction SoftUni Team Technical Trainers Software University
Doctrine The PHP ORM SoftUni Team Technical Trainers Software University
Creating Content Defining Topic, Creating Technical Training Materials SoftUni Team Technical Trainers Software University
ASP.NET MVC Course Program, Trainers, Evaluation, Exams, Resources SoftUni Team Technical Trainers Software University
First Steps in PHP Creating Very Simple PHP Scripts SoftUni Team Technical Trainers Software University
Inheritance Class Hierarchies SoftUni Team Technical Trainers Software University
Static Members Static Variables & Methods SoftUni Team Technical Trainers Software University
Stacks and Queues Processing Sequences of Elements SoftUni Team Technical Trainers Software University
Generics SoftUni Team Technical Trainers Software University
High-Quality Programming Code Code Correctness, Readability, Maintainability, Testability, Etc. SoftUni Team Technical Trainers Software University
Recursive Algorithms and Backtracking
Graphs and Graph Algorithms
Processing Sequences of Elements
Repeating Code Multiple Times
Fast String Manipulation
Array and List Algorithms
Processing Variable-Length Sequences of Elements
Iterators and Generators
The Power of Calling a Method from Itself
Presentation transcript:

Recursion Recursive Algorithms and Backtracking SoftUni Team Technical Trainers Software University

2 1.What is Recursion? 2.Recursive Factorial 3.Generating 0/1 Vectors and Combinations 4.Backtracking  The 8 Queens Problem  Finding All Paths in a Labyrinth Recursively 5.Recursion or Iteration?  Harmful Recursion and Optimizing Bad Recursion Table of Contents

What is Recursion?

4  Recursion is when a method calls itself  Powerful technique for combinatorial and branched search algorithms design  Recursion should have:  Direct or indirect recursive call  The method calls itself directly  Оr through other methods  Exit criteria (bottom)  Prevents infinite recursion What is Recursion?

5  Recursive definition of n! (n factorial): Recursive Factorial – Example n! = n * (n–1)! for n > 0 0! = 1  5! = 5 * 4! = 5 * 4 * 3 * 2 * 1 * 1 = 120  4! = 4 * 3! = 4 * 3 * 2 * 1 * 1 = 24  3! = 3 * 2! = 3 * 2 * 1 * 1 = 6  2! = 2 * 1! = 2 * 1 * 1 = 2  1! = 1 * 0! = 1 * 1 = 1  0! = 1

6  Calculating factorial:  0! = 1  n! = n* (n-1)!, n>0 Recursive Factorial – Example static decimal Factorial(int num) { if (num == 0) return 1; else return 1; else return num * Factorial(num - 1); } return num * Factorial(num - 1); } The bottom of the recursion Recursive call: the method calls itself

Recursive Factorial Live Demo

8  Recursive calls are slightly slower than iteration  Parameters and return values travel through the stack at each step  Prefer iteration for linear calculations (without branched calls) Performance: Recursion vs. Iteration static long RecurFact(int n) { if (n == 0) return 1; else return 1; else return n * Fact(n - 1); } return n * Fact(n - 1); } static long IterFact(int num) { long result = 1; for (int i = 1; i <= n; i++) for (int i = 1; i <= n; i++) result *= i; result *= i; return result; } return result; } Recursive factorial: Iterative factorial:

Factorial Performance Live Demo

10  Infinite recursion == a method calls itself infinitely  Typically, infinite recursion == bug in the program  The bottom of the recursion is missing or wrong  In C# / Java / C++ causes "stack overflow" error Infinite Recursion static long Calulate(int n) { return Calulate(n + 1); return Calulate(n + 1);}

Infinite Recursion Live Demo

12  Direct recursion  A method directly calls itself  Indirect recursion  Method A calls B, method B calls A  Or even A  B  C  A  Funny example of infinite indirect recursion:  Direct and Indirect Recursion void A() { … A(); A();} void A() { … B(); B();} void B() { … A(); A();}

13  Recursive methods have 3 parts:  Pre-actions (before calling the recursion)  Recursive calls (step-in)  Post-actions (after returning from recursion)  Recursive computation can be based on:  Pre-actions + recursive calls (forward way)  Recursive calls + post-actions (backward way)  Pre-actions + recursive calls + post-actions (combined way) Recursion Pre-Actions and Post-Actions

14 Pre-Actions and Post-Actions – Example static void PrintFigure(int n) { if (n == 0) // Bottom of the recursion if (n == 0) // Bottom of the recursion return; return; // Pre-action: print n asterisks // Pre-action: print n asterisks Console.WriteLine(new string('*', n)); Console.WriteLine(new string('*', n)); // Recursive call: print figure of size n-1 // Recursive call: print figure of size n-1 PrintFigure(n - 1); PrintFigure(n - 1); // Post-action: print n hashtags // Post-action: print n hashtags Console.WriteLine(new string('#', n)); Console.WriteLine(new string('#', n));}

Pre-Actions and Post-Actions Live Demo

16  How to generate all 8-bit vectors recursively?   ...   ...    How to generate all n-bit vectors? Generating 0/1 Vectors

17  Algorithm Gen01(n) : put 0 and 1 at the last position n and call Gen01(n-1) for the rest: Generating 0/1 Vectors (2)xxxxxx0 Gen01(6):Gen01(5)xxxxxx1Gen01(5)xxxxx0y Gen01(5):Gen01(4)xxxxx1yGen01(4) … Gen01(-1): Print;Stop! 

18 Generating 0/1 Vectors (3) static void Gen01(int index, int[] vector) { if (index < 0) if (index < 0) Print(vector); Print(vector); else else 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() { int n = 8; int n = 8; int[] vector = new int[n]; int[] vector = new int[n]; Gen01(n-1, vector); Gen01(n-1, vector);}

Generating 0/1 Vectors Live Demo

Generating Combinations Simple Recursive Algorithm

21  Combinations in math represent all the ways to extract a subset from a larger set of elements  Select k members from a set of n elements  Example: we can select 3 different elements from the set {4, 5, 6, 7, 8} in 10 different ways: (4, 5, 6) (4, 5, 7) (4, 5, 8) (4, 6, 7) (4, 6, 8) (4, 7, 8) (5, 6, 7) (5, 6, 8) (5, 7, 8) (6, 7, 8)  Combinations with and without repetitions can be easily generated with recursion Generating Combinations

22  Algorithm GenCombs(k) : put the numbers [1 … n] at position k and call GenCombs(k+1) recursively for the rest of the elements: Generating Combinations (2)1xxxxxx GenCombs(0):GenCombs(1) Put all numbers in range [1..n] at position k11xxxxx GenCombs(1):GenCombs(2) GenCombs(n): …  Print;Stop! Bottom of recursion

23 Generating Combinations (3) static void GenCombs( int[] arr, int index, int startNum, int endNum) int[] arr, int index, int startNum, int endNum){ if (index >= arr.Length) // Combination found --> print it if (index >= arr.Length) // Combination found --> print it Console.WriteLine("(" + String.Join(", ", arr) + ")"); Console.WriteLine("(" + String.Join(", ", arr) + ")"); else else for (int i = startNum; i <= endNum; i++) for (int i = startNum; i <= endNum; i++) { arr[index] = i; arr[index] = i; GenCombs(arr, index + 1, GenCombs(arr, index + 1, i + 1, endNum); i + 1, endNum); }} static void Main() { int[] arr = new int[8]; int[] arr = new int[8]; GenCombs(arr, 0, 4, 8); GenCombs(arr, 0, 4, 8);}

Generating Combinations Live Demo

Backtracking Solving Computational Problems by Generating All Candidates

26  What is backtracking?  Backtracking is a class of algorithms for finding all solutions to some combinatorial computational problem  E.g. find all paths from Sofia to Varna  How does backtracking work?  At each step tries all perspective possibilities recursively  Drop all non-perspective possibilities as early as possible  Backtracking has exponential running time! Backtracking

27 Backtracking Algorithm (Pseudocode) void Backtracking(Node node) { if (node is solution) if (node is solution) PrintSolution(node); PrintSolution(node); else else for each child c of node for each child c of node if (c is perspective candidate) if (c is perspective candidate) { MarkPositionVisited(c); MarkPositionVisited(c); Backtracking(c); Backtracking(c); UnmarkPositionVisited(c); UnmarkPositionVisited(c); }}

The "8 Queens" Puzzle Backtracking in Practice

29  Write a program to find all possible placements of  8 queens on a chessboard  So that no two queens can attack each other  Eight_queens_puzzle Eight_queens_puzzle The "8 Queens" Puzzle

30  Backtracking algorithm  For finding all solutions to the "8 Queens Puzzle"  At each step:  Put a queen at free position  Recursive call  Remove the queen Solving The "8 Queens" Puzzle void PutQueens(row) { if (row == 8) if (row == 8) PrintSolution(); PrintSolution(); else else for (col = 0 … 7) for (col = 0 … 7) if (CanPlaceQueen(row, col)) if (CanPlaceQueen(row, col)) { MarkAllAttackedPositions(row, col); MarkAllAttackedPositions(row, col); PutQueens(row + 1); PutQueens(row + 1); UnmarkAllAttackedPositions(row, col); UnmarkAllAttackedPositions(row, col); }}

The "8 Queens" Puzzle In-Class Exercise (Lab)

32  We are given a labyrinth  Represented as matrix of cells of size M x N  Empty cells are passable, the others (*) are not  We start from the top left corner and can move in all 4 directions: left, right, up, down  We want to find all paths to the bottom right corner Finding All Paths in a Labyrinth Start position End position

33  There are 3 different paths from the top left corner to the bottom right corner: Finding All Paths in a Labyrinth (2) 012* **3** 654 7***** *8910**3*7* ***** ) 2)012***3** *****9 10 3)

34  Suppose we have an algorithm FindExit(x,y) that finds and prints all paths to the exit (bottom right corner) starting from position (x,y)  If (x,y) is not passable, no paths are found  If (x,y) is already visited, no paths are found  Otherwise:  Mark position (x,y) as visited (to avoid cycles)  Find recursively all paths to the exit from all neighbor cells: (x-1,y), (x+1,y), (x,y+1), (x,y-1)  Mark position (x,y) as free (can be visited again) Finding All Paths in a Labyrinth (3)

35  Representing the labyrinth as matrix of characters (in this example 5 rows and 7 columns):  Spaces (' ') are passable cells  Asterisks ('*') are not passable  The symbol 'e' is the exit (can occur multiple times) Find All Paths: Algorithm static char[,] lab = { {' ', ' ', ' ', '*', ' ', ' ', ' '}, {' ', ' ', ' ', '*', ' ', ' ', ' '}, {'*', '*', ' ', '*', ' ', '*', ' '}, {'*', '*', ' ', '*', ' ', '*', ' '}, {' ', ' ', ' ', ' ', ' ', ' ', ' '}, {' ', ' ', ' ', ' ', ' ', ' ', ' '}, {' ', '*', '*', '*', '*', '*', ' '}, {' ', '*', '*', '*', '*', '*', ' '}, {' ', ' ', ' ', ' ', ' ', ' ', 'е'}, {' ', ' ', ' ', ' ', ' ', ' ', 'е'},};

36 Find All Paths: Algorithm (2) static void FindExit(int row, int col) { if ((col = lab.GetLength(1)) if ((col = lab.GetLength(1)) || (row >= lab.GetLength(0))) || (row >= lab.GetLength(0))) { // We are out of the labyrinth -> can't find a path // We are out of the labyrinth -> can't find a path 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 path // The current cell is not free -> can't find a path return; return; } (example continues)

37 Find All Paths: Algorithm (3) // Temporaryly mark the current cell as visited // Temporaryly mark the current cell as visited lab[row, col] = 's'; lab[row, col] = 's'; // Invoke recursion to explore all possible directions // Invoke recursion to explore all possible directions FindExit(row, col - 1); // left FindExit(row, col - 1); // left FindExit(row - 1, col); // up FindExit(row - 1, col); // up FindExit(row, col + 1); // right FindExit(row, col + 1); // right FindExit(row + 1, col); // down FindExit(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() { FindExit(0, 0); FindExit(0, 0);}

Find All Paths in a Labyrinth Live Demo

39  How to print all paths found by our recursive algorithm?  Each move's direction can be stored in a list  Need to pass the movement direction at each recursive call (L, R, U, or D)  At the start of each recursive call the current direction is appended to the list  At the end of each recursive call the last direction is removed from the list Find All Paths and Print Them static List path = new List ();

40 Find All Paths and Print Them (2) static void FindPathToExit(int row, int col, char direction) { // Append the current direction to the path // Append the current direction to the path path.Add(direction); path.Add(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'); // left FindPathToExit(row, col - 1, 'L'); // left FindPathToExit(row - 1, col, 'U'); // up FindPathToExit(row - 1, col, 'U'); // up FindPathToExit(row, col + 1, 'R'); // right FindPathToExit(row, col + 1, 'R'); // right FindPathToExit(row + 1, col, 'D'); // down FindPathToExit(row + 1, col, 'D'); // down // Remove the last direction from the path // Remove the last direction from the path path.RemoveAt(path.Count - 1); path.RemoveAt(path.Count - 1);}

Find and Print All Paths in a Labyrinth Live Demo

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

43  When used incorrectly recursion could take too much memory and computing power  Example: Recursion Can be Harmful! static decimal Fibonacci(int n) { if ((n == 1) || (n == 2)) if ((n == 1) || (n == 2)) return 1; return 1; else else return Fibonacci(n - 1) + Fibonacci(n - 2); return Fibonacci(n - 1) + Fibonacci(n - 2);} static void Main() { Console.WriteLine(Fibonacci(10)); // 89 Console.WriteLine(Fibonacci(10)); // 89 Console.WriteLine(Fibonacci(50)); // This will hang! Console.WriteLine(Fibonacci(50)); // This will hang!}

Harmful Recursion Live Demo

45  fib(n) makes about fib(n) recursive calls  The same value is calculated many, many times! How the Recursive Fibonacci Calculation Works?

46  Each Fibonacci sequence member  Can be remembered once it is calculated  Can be returned directly when needed again Fast Recursive Fibonacci static decimal[] fib = new decimal[MAX_FIB]; static decimal Fib(int n) { if (fib[n] == 0) if (fib[n] == 0) { // fib[n] is still not calculated // fib[n] is still not calculated if ((n == 1) || (n == 2)) if ((n == 1) || (n == 2)) fib[n] = 1; fib[n] = 1; else else fib[n] = Fib(n - 1) + Fib(n - 2); fib[n] = Fib(n - 1) + Fib(n - 2); } return fib[n]; return fib[n];}

Fast Recursive Fibonacci Live Demo

48  Avoid recursion when an obvious iterative algorithm exists  Examples: factorial, Fibonacci numbers  Use recursion for combinatorial algorithms where  At each step you need to recursively explore more than one possible continuation  I.e. for branched recursive algorithms  Examples: permutations, all paths in a labyrinth  If you have only one recursive call in the body of a recursive method, it can directly become iterative (like calculating factorial) When to Use Recursion?

49  Recursion means to call a method from itself  It should always have a bottom at which the recursive calls stop  Very powerful technique for implementing combinatorial algorithms  Examples: generating combinatorial configurations like vectors, permutations, combinations, variations, etc.  Backtracking finds all solutions / optimal solution of combinatorial problem by generating all possibilities  Without non-perspective candidates  Recursion can be harmful when not used correctly Summary

? ? ? ? ? ? ? ? ? Recursion

License  This course (slides, examples, labs, videos, homework, etc.) is licensed under the "Creative Commons Attribution- NonCommercial-ShareAlike 4.0 International" licenseCreative Commons Attribution- NonCommercial-ShareAlike 4.0 International 51  Attribution: this work may contain portions from  "Fundamentals of Computer Programming with C#" book by Svetlin Nakov & Co. under CC-BY-SA licenseFundamentals of Computer Programming with C#CC-BY-SA  "Data Structures and Algorithms" course by Telerik Academy under CC-BY-NC-SA licenseData Structures and AlgorithmsCC-BY-NC-SA

Free Software University  Software University Foundation – softuni.orgsoftuni.org  Software University – High-Quality Education, Profession and Job for Software Developers  softuni.bg softuni.bg  Software Facebook  facebook.com/SoftwareUniversity facebook.com/SoftwareUniversity  Software YouTube  youtube.com/SoftwareUniversity youtube.com/SoftwareUniversity  Software University Forums – forum.softuni.bgforum.softuni.bg