1 / 40

Stuff

Stuff. No stuff today!. Last Time. The complexity of binary search. Started Recursion by looking at what recursion is, and how the java runtime engine uses activation frames to handle program flow. Today. Recursion, Cont. Types of recursion: Tail Non-Tail Indirect Excessive Infinite

nantai
Télécharger la présentation

Stuff

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Stuff • No stuff today! CISC121 - Prof. McLeod

  2. Last Time • The complexity of binary search. • Started Recursion by looking at what recursion is, and how the java runtime engine uses activation frames to handle program flow. CISC121 - Prof. McLeod

  3. Today • Recursion, Cont. • Types of recursion: • Tail • Non-Tail • Indirect • Excessive • Infinite • Backtracking CISC121 - Prof. McLeod

  4. Recursion and the Run-Time Stack – Summary • Execution stops at any method call and execution is passed to that method. • Information on the calling method is preserved in the run-time stack, and a new frame is created for the newly called method. • As recursive calls continue, the frames continue to pile up, each one waiting to complete their execution. • Finally, the last recursive call is made and the “anchor condition” or the “stopping case” is encountered. The method completes without making another recursive call and may provide a Return value, for example. CISC121 - Prof. McLeod

  5. Recursion and the Run-Time Stack – Summary, Cont. • The frame for the last call, the “stopping case” is popped off the stack, with the Return value being passed down into the next frame. • The frame below accepts the Return value, completes, gets popped off, and so on, until the only frame remaining is the frame that contains the original call to the recursive method. • This frame accepts the value from the method, and continues its execution. CISC121 - Prof. McLeod

  6. An Example • Remember that the activation frames can also hold code after the recursive call. • See TestRecursion.java CISC121 - Prof. McLeod

  7. Another Example • Write code that computes the sum below for n terms: • (This sum does not converge very quickly!) CISC121 - Prof. McLeod

  8. Another Example – Cont. • Write sum using a recursive definition: CISC121 - Prof. McLeod

  9. Tail Recursion public static double sum (int n) { if (n == 1) return 1.0; else return Math.pow(-1, n) / n + sum(n-1); } // end sum • (Note that Math.pow() returns a double). • This kind of recursion is called “tail recursion”, since the recursive call is at the end of the method. CISC121 - Prof. McLeod

  10. Tail Recursion – Cont. • Tail recursions can always be easily written non-recursively with a loop: public static double loopsum (int n) { double sum = 1.0; for (int i = 2; i <= n; i++) sum += Math.pow(-1, i) / i; return sum; } // end loopsum CISC121 - Prof. McLeod

  11. Comparison of Recursion and Loops • Using “System.currentTimeMillis()”. • Results (times are average of four readings): CISC121 - Prof. McLeod

  12. Tail Recursion – Cont. • So, this experiment shows that the loop is a bit faster than recursion and will not encounter the stack overflow condition. • There is usually little reason to write a recursive method that uses only tail recursion - use a loop instead. • Tail recursion is when the recursive call is at the end of the method, and there is only one recursive call. CISC121 - Prof. McLeod

  13. Non-Tail Recursion • Another example, a method to calculate the “Greatest Common Divisor”, or “GCD” for two integers. • For example, GCD(800, 64) would return 32. CISC121 - Prof. McLeod

  14. Non-Tail Recursion – Cont. • In code: public static int GCD (int n, int m) { if (n < m) return GCD(m, n); else if ((n % m) > 0) return GCD(m, n % m); else return m; } // end GCD CISC121 - Prof. McLeod

  15. Non-Tail Recursion – Cont. • This is a (pretty trivial!) example of “Non-Tail Recursion”, since it has two recursive calls before the end of the method. • (Note that, in Java, unless you have a return statement in each branch of a conditional, you must have a return statement outside the conditional.) • This example could also be coded fairly easily with a loop. CISC121 - Prof. McLeod

  16. Non-Tail Recursion • A method where there are either multiple recursive calls, or the recursive call is not at the end of the method. • It is the most common kind of recursion. • (Quicksort is an excellent example of Non-Tail Recursion). CISC121 - Prof. McLeod

  17. Indirect Recursion • Recursion that does not occur by a direct call. • For example, f() calls g() and then g() calls f(). • Another example used to calculate sin, tan and cos, using the formulae: CISC121 - Prof. McLeod

  18. Indirect Recursion - Cont. • The stopping case for this recursion is for when x is small: • See the program “RecursiveTrigFunctions.java” CISC121 - Prof. McLeod

  19. Excessive Recursion • An example can be made from the definition of the Fibonacci numbers: • The sequence obtained (by adding the two previous numbers to get the next one) is: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, … CISC121 - Prof. McLeod

  20. Excessive Recursion - Cont. • In Java: public int Fib (int n) { if (n < 2) return n; else return Fib(n-2) + Fib(n-1); } // end Fib CISC121 - Prof. McLeod

  21. Excessive Recursion - Cont. • 25 method calls, and 12 additions are required just to calculate Fib(6)!: CISC121 - Prof. McLeod

  22. Excessive Recursion - Cont. • For Fib(30), 2,692,537 calls would be required and 1,346,268 additions!!! • (In testing the code, Fib(40) was taking a very long time, and would likely lead to stack overflow.) • In comparison, an iterative version of the method, that is about three times as long (in code), would only require 87 assignments and 29 additions to calculate Fib(30). CISC121 - Prof. McLeod

  23. Infinite Recursion • This is what happens when the stopping case is not encountered. • For example, if the line if (n == 1) return 1.0; had been left out of the “sum” example, the recursive process would never have hit the stopping case and would have continued until stack overflow occurs (even for small n). CISC121 - Prof. McLeod

  24. Infinite Recursion - Cont. • A “stack overflow” error would have been reported and the program would crash. • The heart of a recursive method contains a conditional statement where at least one branch of the conditional leads to a non-recursive completion. The conditional must test an expression that includes at least one of the method’s parameters. • The recursive calls from the other branches should be made to “smaller” executions of the method. CISC121 - Prof. McLeod

  25. Example of Recursion - Towers of Hanoi A B C • Move all disks from pin A to pin C subject to: • One disk at a time must be moved to a pin from the top. • Cannot have a larger disk over a smaller one. • See powerpoint “solution”… CISC121 - Prof. McLeod

  26. Towers of Hanoi • For n disks: • Apply the solution for n-1 disks, moving them to pin B, using pin C as a temporary pin. • Apply the n=1 solution, moving the largest disk from pin A to pin C. • Apply the n-1 solution again moving disks from pin B to pin C, using pin A as a temporary pin. CISC121 - Prof. McLeod

  27. Towers of Hanoi, Cont. • So, the solution for n disks uses the solution for n-1 disks. • Solution algorithm: • Move n-1 disks from pin A to pin B, using pin C for temporary storage. • Move final disk from pin A to pin C. • Move n-1 disks from pin B to pin C using pin A for temporary storage. • Recursive anchor case: • If n=1 move disk from pin A to pin C. • See TowersSolution.java CISC121 - Prof. McLeod

  28. Backtracking • Backtracking is an algorithmic tool that is used in developing artificial intelligence algorithms. • It is used when different possible paths exist from a given position, and it is not known which one is optimum. • A path is tried, followed by another try, and so on. If the optimum solution is not encountered, then the last path is “backtracked” and another path is tried. The backtracking can go all the way back to the first decision. CISC121 - Prof. McLeod

  29. Backtracking - Cont. BAD BAD CISC121 - Prof. McLeod

  30. Backtracking – Cont. • Three possible outcomes from backtracking: • Stop when the first path to success is found. • Discover all possible paths to success (full exploration). • Discover optimal path (still requires full exploration). • Optimal could be shortest, lowest cost, least effort, etc. CISC121 - Prof. McLeod

  31. Backtracking and Recursion • As usual, recursion makes coding easier: • Recursive backtracking algorithm for single outcome: • If successful, finished! (anchor case) • else: • for every possible, untried choice from current position: • move to the new choice • check to see if the rest of the problem can be solved: (recursive) • if so, finished! • if not, try another choice • if all choices tried without success, backtrack CISC121 - Prof. McLeod

  32. Backtracking - Cont. • For example, the problem of “placing n queens on an n x n chessboard, without any queen threatening any other.” (the “Nqueens” problem) can be solved by backtracking. CISC121 - Prof. McLeod

  33. The “NQueen’s” Problem • One Queen on an 8x8 grid (a chessboard!), and who she “threatens”: CISC121 - Prof. McLeod

  34. The “NQueen’s” Problem - Cont. • The solution for 8 Queen’s on an 8x8 grid, for example: CISC121 - Prof. McLeod

  35. The “NQueen’s” Problem - Cont. • It is easy enough to manually solve this problem for n=4. • Showing each step - see “FourQueensSoln.ppt”. • Watch for backtracking! CISC121 - Prof. McLeod

  36. The “NQueen’s” Problem - Cont. • Number rows and columns from zero. • Move through grid column by column. • Note that only one Queen can occupy each column and therefore each column must have a Queen. • Start from column zero and go to column n-1. CISC121 - Prof. McLeod

  37. The “NQueen’s” Problem - Cont. • Pseudocode for recursive method: boolean solveNQ (int col) if col >= size then all done! for row 0 to row n-1, where n is board size if (row, col) is a safe position: place Queen at (row, col) if solveNQ (col + 1) is true then return true else remove Queen from (row, col) (Outside of loop:) return false CISC121 - Prof. McLeod

  38. static boolean solveNQ(Board B, int col) { // anchor case: we have succeeded! if (col >= B.getSize()) return true; // try putting a queen in each row of this column for (int row = 0; row < B.getSize(); row++) { if (B.safePosition(row, col)) { B.putQueen(row, col); if (solveNQ(B, col+1)) return true; else B.removeQueen(row, col); } // end if } // end for // anchor case: there is no solution return false; } // end solveNQ CISC121 - Prof. McLeod

  39. The “NQueen’s” Problem - Cont. • See “Board.java” and “NQueen.java” for the other methods. CISC121 - Prof. McLeod

  40. Recursion - A Summary • Recursive methods call themselves. • Recursive algorithms are very easy to code when a logical recursive definition (including an anchor case) is given. • Make sure the recursive method includes the anchor case, and calls are made to smaller values each time. • Most recursive algorithms can be coded as an iterative version (using loops). But the iterative version is not always as easy to build (except for tail recursion). • Recursive code is easy to read and de-bug. • It should be used when the longer execution time is not as important as being able to use a smaller program that can be coded and de-bugged in less time. CISC121 - Prof. McLeod

More Related