Recursion - PowerPoint PPT Presentation

About This Presentation
Title:

Recursion

Description:

Recursion Based on Chapter 7 of Koffmann and Wolfgang Famous Quotations To err is human, to forgive divine. Alexander Pope, An Essay on Criticism, English poet and ... – PowerPoint PPT presentation

Number of Views:321
Avg rating:3.0/5.0
Slides: 80
Provided by: EliotMoss5
Category:

less

Transcript and Presenter's Notes

Title: Recursion


1
Recursion
  • Based on Chapter 7 of
  • Koffmann and Wolfgang

2
Famous Quotations
  • To err is human, to forgive divine.
  • Alexander Pope, An Essay on Criticism, English
    poet and satirist (1688 - 1744)
  • To iterate is human, to recurse, divine.
  • L. Peter Deutsch, computer scientist, or ....
  • Robert Heller, computer scientist, or ....
  • unknown ....

3
Chapter Outline
  • Thinking recursively
  • Tracing execution of a recursive method
  • Writing recursive algorithms
  • Methods for searching arrays
  • Recursive data structures
  • Recursive methods for a LinkedList class
  • Solving the Towers of Hanoi problem with
    recursion
  • Processing 2-D images with recursion
  • Backtracking to solve searchproblems, as in mazes

4
Recursive Thinking
  • Recursion is
  • A problem-solving approach, that can ...
  • Generate simple solutions to ...
  • Certain kinds of problems that ...
  • Would be difficult to solve in other ways
  • Recursion splits a problem
  • Into one or more simpler versions of itself

5
Recursive Thinking An Example
  • Strategy for processing nested dolls
  • if there is only one doll
  • do what it needed for it
  • else
  • do what is needed for the outer doll
  • Process the inner nest in the same way

6
Recursive Thinking Another Example
  • Strategy for searching a sorted array
  • if the array is empty
  • return -1 as the search result (not
    present)
  • else if the middle element target
  • return subscript of the middle element
  • else if target lt middle element
  • recursively search elements before middle
  • else
  • recursively search elements after the middle

7
Recursive Thinking The General Approach
  1. if problem is small enough
  2. solve it directly
  3. else
  4. break into one or more smaller subproblems
  5. solve each subproblem recursively
  6. combine results into solution to whole
    problem

8
Requirements for Recursive Solution
  • At least one small case that you can solve
    directly
  • A way of breaking a larger problem down into
  • One or more smaller subproblems
  • Each of the same kind as the original
  • A way of combining subproblem results into an
    overall solution to the larger problem

9
General Recursive Design Strategy
  • Identify the base case(s) (for direct solution)
  • Devise a problem splitting strategy
  • Subproblems must be smaller
  • Subproblems must work towards a base case
  • Devise a solution combining strategy

10
Recursive Design Example
  • Recursive algorithm for finding length of a
    string
  • if string is empty (no characters)
  • return 0 ? base case
  • else ? recursive case
  • compute length of string without first
    character
  • return 1 that length
  • Note Not best technique for this problem
    illustrates the approach.

11
Recursive Design Example Code
  • Recursive algorithm for finding length of a
    string
  • public static int length (String str)
  • if (str null
  • str.equals())
  • return 0
  • else
  • return length(str.substring(1)) 1

12
Recursive Design Example printChars
  • Recursive algorithm for printing a string
  • public static void printChars
  • (String str)
  • if (str null
  • str.equals())
  • return
  • else
  • System.out.println(str.charAt(0))
  • printChars(str.substring(1))

13
Recursive Design Example printChars2
  • Recursive algorithm for printing a string?
  • public static void printChars2
  • (String str)
  • if (str null
  • str.equals())
  • return
  • else
  • printChars2(str.substring(1))
  • System.out.println(str.charAt(0))

14
Recursive Design Example mystery
  • What does this do?
  • public static int mystery (int n)
  • if (n 0)
  • return 0
  • else
  • return n mystery(n-1)

15
Proving a Recursive Method Correct
  • Recall Proof by Induction
  • Prove the theorem for the base case(s) n0
  • Show that
  • If the theorem is assumed true for n,
  • Then it must be true for n1
  • Result Theorem true for all n 0.

16
Proving a Recursive Method Correct (2)
  • Recursive proof is similar to induction
  • Show base case recognized and solved correctly
  • Show that
  • If all smaller problems are solved correctly,
  • Then original problem is also solved correctly
  • Show that each recursive case makes progress
    towards the base case ? terminates properly

17
Tracing a Recursive Method
Overall result
length(ace)
3
return 1 length(ce)
2
return 1 length(e)
1
return 1 length()
0
18
Tracing a Recursive Method (2)
19
Recursive Definitions of Mathematical Formulas
  • Mathematicians often use recursive definitions
  • These lead very naturally to recursive algorithms
  • Examples include
  • Factorial
  • Powers
  • Greatest common divisor

20
Recursive Definitions Factorial
  • 0! 1
  • n! n x (n-1)!
  • If a recursive function never reaches its base
    case, a stack overflow error occurs

21
Recursive Definitions Factorial Code
  • public static int factorial (int n)
  • if (n 0) // or throw exc. if lt 0
  • return 1
  • else
  • return n factorial(n-1)

22
Recursive Definitions Power
  • x0 1
  • xn x ? xn-1
  • public static double power
  • (double x, int n)
  • if (n lt 0) // or throw exc. if lt 0
  • return 1
  • else
  • return x power(x, n-1)

23
Recursive Definitions Greatest Common Divisor
  • Definition of gcd(m, n), for integers m gt n gt 0
  • gcd(m, n) n, if n divides m evenly
  • gcd(m, n) gcd(n, m n), otherwise
  • public static int gcd (int m, int n)
  • if (m lt n)
  • return gcd(n, m)
  • else if (m n 0) // could check ngt0
  • return n
  • else
  • return gcd(n, m n)

24
Recursion Versus Iteration
  • Recursion and iteration are similar
  • Iteration
  • Loop repetition test determines whether to exit
  • Recursion
  • Condition tests for a base case
  • Can always write iterative solution to a problem
    solved recursively, but
  • Recursive code often simpler than iterative
  • Thus easier to write, read, and debug

25
Tail Recursion ? Iteration
  • When recursion involves single call that is at
    the end ...
  • It is called tail recursion and it easy to make
    iterative
  • public static int iterFact (int n)
  • int result 1
  • for (int k 1 k lt n k)
  • result result k
  • return result

26
Efficiency of Recursion
  • Recursive method often slower than iterative
    why?
  • Overhead for loop repetition smaller than
  • Overhead for call and return
  • If easier to develop algorithm using recursion,
  • Then code it as a recursive method
  • Software engineering benefit probably outweighs
    ...
  • Reduction in efficiency
  • Dont optimize prematurely!

27
Recursive Definitions Fibonacci Series
  • Definition of fibi, for integer i gt 0
  • fib1 1
  • fib2 1
  • fibn fibn-1 fibn-2, for n gt 2

28
Fibonacci Series Code
  • public static int fib (int n)
  • if (n lt 2)
  • return 1
  • else
  • return fib(n-1) fib(n-2)
  • This is straightforward, but an inefficient
    recursion ...

29
Efficiency of Recursion Inefficient Fibonacci
calls apparently O(2n) big!
30
Efficient Fibonacci
  • Strategy keep track of
  • Current Fibonacci number
  • Previous Fibonacci number
  • left to compute

31
Efficient Fibonacci Code
  • public static int fibStart (int n)
  • return fibo(1, 0, n)
  • private static int fibo (
  • int curr, int prev, int n)
  • if (n lt 1)
  • return curr
  • else
  • return fibo(currprev, curr, n-1)

32
Efficient Fibonacci A Trace
Performance is O(n)
33
Recursive Array Search
  • Can search an array using recursion
  • Simplest way is linear search
  • Examine one element at a time
  • Start with the first element, end with the last
  • One base case for recursive search empty array
  • Result is -1 (negative, not an index ? not found)
  • Another base case current element matches target
  • Result is index of current element
  • Recursive case search rest, without current
    element

34
Recursive Array Search Linear Algorithm
  • if the array is empty
  • return -1
  • else if first element matches target
  • return index of first element
  • else
  • return result of searching rest of the
    array,
  • excluding the first element

35
Linear Array Search Code
  • public static int linSrch (
  • Object items, Object targ)
  • return linSrch(items, targ, 0)
  • private static int linSrch (
  • Object items, Object targ, int n)
  • if (n gt items.length) return -1
  • else if (targ.equals(itemsn))
  • return n
  • else
  • return linSrch(items, targ, n1)

36
Linear Array Search Code Alternate
  • public static int lSrch (
  • Object items, Object o)
  • return lSrch(items, o, items.length-1)
  • private static int lSrch (
  • Object items, Object o, int n)
  • if (n lt 0) return -1
  • else if (o.equals(itemsn))
  • return n
  • else
  • return lSrch(items, targ, n-1)

37
Array Search Getting Better Performance
  • Item not found O(n)
  • Item found n/2 on average, still O(n)
  • How can we perhaps do better than this?
  • What if the array is sorted?
  • Can compare with middle item
  • Get two subproblems of size ? n/2
  • What performance would this have?
  • Divide by 2 at each recursion ? O(log n)
  • Much better!

38
Binary Search Algorithm
  • Works only on sorted arrays!
  • Base cases
  • Empty (sub)array
  • Current element matches the target
  • Check middle element with the target
  • Consider only the array half where target can
    still lie

39
Binary Search Algorithm Steps
  1. if array is empty
  2. return -1 as result
  3. else if middle element matches
  4. return index of middle element as result
  5. else if target lt middle element
  6. return result of searching lower portion of
    array
  7. else
  8. return result of searching upper portion of
    array

40
Binary Search Example
41
Binary Search Code
  • private static int bSrch (Object a,
  • Comparable t, int lo, int hi)
  • if (lo gt hi) // no elements
  • return -1
  • int mid (lo hi) / 2
  • int comp t.compareTo(amid)
  • if (comp 0) // t equals mid element
  • return mid
  • else if (comp lt 0) // t lt mid element
  • return bSrch(a, t, lo, mid-1)
  • else
  • return bSrch(a, t, mid1, hi)

42
Binary Search Code (2)
  • public static int bSrch (
  • Object a, Comparable t)
  • return bSrch(a, t, 0, a.length-1)
  • Java API routine Arrays.binarySearch does this
    for
  • Sorted arrays of primitive types (int, etc.)
  • Sorted arrays of objects
  • Objects must be Comparable

43
Recursive Data Structures
  • Just as we have recursive algorithms
  • We can have recursive data structures
  • Like algorithms, a recursive data structure has
  • A base case, a simple data structure, or null
  • A recursive case includes a smaller instance of
    the same data structure

44
Recursive Data Structures (2)
  • Computer scientists often define data structures
    recursively
  • Trees (Chapter 8) are defined recursively
  • Linked lists can also be defined recursively
  • Recursive methods are very natural in processing
    recursive data structures
  • The first language developed for artificial
    intelligence research was a recursive language
    called LISP

45
Recursive Definition of Linked List
  • A linked list is either
  • An empty list ? the base case, or
  • A head node, consisting of ? recursive case
  • A data item and
  • A reference to a linked list (rest of list)

46
Code for Recursive Linked List
  • public class RecLLltEgt
  • private NodeltEgt head null
  • private static class NodeltEgt
  • private E data
  • private NodeltEgt rest
  • private Node (E data, NodeltEgt rest)
  • this.data data
  • this.rest rest
  • ...

47
Code for Recursive Linked List (2)
  • private int size (NodeltEgt head)
  • if (head null)
  • return 0
  • else
  • return 1 size(head.next)
  • public int size ()
  • return size(head)

48
Code for Recursive Linked List (3)
  • private String toString (NodeltEgt head)
  • if (head null)
  • return
  • else
  • return toString(head.data) \n
  • toString(head.next)
  • public String toString ()
  • return toString(head)

49
Code for Recursive Linked List (4)
  • private NodeltEgt find (
  • NodeltEgt head, E data)
  • if (head null)
  • return null
  • else if (data.equals(head.data))
  • return head
  • else
  • return find(head.next, data)
  • public boolean contains (E data)
  • return find(head, data) ! null

50
Code for Recursive Linked List (5)
  • private int indexOf (
  • NodeltEgt head, E data)
  • if (head null)
  • return -1
  • else if (data.equals(head.data))
  • return 0
  • else
  • return 1 indexOf(head.next, data)
  • public int indexOf (E data)
  • return indexOf(head, data)

51
Code for Recursive Linked List (6)
  • private void replace (NodeltEgt head,
  • E oldE, E newE)
  • if (head null)
  • return
  • else // replace all old always recurse
  • if (oldE.equals(head.data))
  • head.data newE
  • replace(head.next, oldE, newE)
  • public void replace (E oldE, E newE)
  • replace(head, oldE, newE)

52
Code for Recursive Linked List (7)
  • private void add (NodeltEgt head, E data)
  • // Note different base case!!
  • if (head.next null)
  • head.next new NodeltEgt(data)
  • else // replace all old always recurse
  • add(head.next, data)
  • public void add (E data)
  • if (head null)
  • head new NodeltEgt(data)
  • else
  • add(head, data)

53
Code for Recursive Linked List (8)
  • private boolean remove (
  • NodeltEgt pred, NodeltEgt curr, E data)
  • if (curr null) // a base case
  • return false
  • else if (data.equals(curr.data))
  • pred.next curr.next
  • return true // 2d base case
  • else
  • return remove(curr, curr.next, data)

54
Code for Recursive Linked List (9)
  • public boolean remove (E data)
  • if (head null)
  • return false
  • else if (data.equals(head.data))
  • head head.next
  • return true
  • else
  • return remove(head, head.next, data)

55
Alternate Recursive Linked List
  • private NodeltEgt add (
  • NodeltEgt head, E data)
  • if (head null)
  • return new NodeltEgt(data)
  • else
  • return new NodeltEgt(
  • data, add(head.next, data))
  • // more elegant more allocation
  • public void add (E data)
  • head add(head, data)

56
Alternate Recursive Linked List (2)
  • private NodeltEgt add (
  • NodeltEgt head, E data)
  • if (head null)
  • return new NodeltEgt(data)
  • else
  • head.next add(head.next, data)
  • return head
  • public void add (E data)
  • head add(head, data)

57
Alternate Recursive Linked List (3)
  • private NodeltEgt remove (
  • NodeltEgt head, E data)
  • if (head null) return null
  • else if (data.equals(head.data))
  • return remove(head.next, data)
  • else
  • head.next remove(head.next, data)
  • return head
  • public void remove (E data)
  • head remove(head, data)

58
Problem Solving with Recursion
  • Towers of Hanoi
  • Counting grid squares in a blob
  • Backtracking, as in maze search

59
Towers of Hanoi Description
  • Goal Move entire tower to another peg
  • Rules
  • You can move only the top disk from a peg.
  • You can only put a smaller on a larger disk (or
    on an empty peg)

60
Towers of Hanoi Solution Strategy
61
Towers of Hanoi Solution Strategy (2)
62
Towers of Hanoi Program Specification
63
Towers of Hanoi Program Specification (2)
64
Towers of Hanoi Recursion Structure
  • move(n, src, dst, tmp)
  • if n 1 move disk 1 from src to dst
  • otherwise
  • move(n-1, src, tmp, dst)
  • move disk n from src to dst
  • move(n-1, tmp, dst, src)

65
Towers of Hanoi Code
  • public class TowersOfHanoi
  • public static String showMoves(int n,
  • char src, char dst, char tmp)
  • if (n 1)
  • return Move disk 1 from src
  • to dst \n
  • else return
  • showMoves(n-1, src, tmp, dst)
  • Move disk n from src
  • to dst \n
  • showMoves(n-1, tmp, dst, src)

66
Towers of Hanoi Performance Analysis
  • How big will the string be for a tower of size n?
  • Well just count lines call this L(n).
  • For n 1, one line L(1) 1
  • For n gt 1, one line plus twice L for next smaller
    size
  • L(n1) 2 x L(n) 1
  • Solving this gives L(n) 2n 1 O(2n)
  • So, dont try this for very large n you will do
    a lot of string concatenation and garbage
    collection, and then run out of heap space and
    terminate.

67
Counting Cells in a Blob
  • Desire Process an image presented as a
    two-dimensional array of color values
  • Information in the image may come from
  • X-Ray
  • MRI
  • Satellite imagery
  • Etc.
  • Goal Determine size of any area considered
    abnormal because of its color values

68
Counting Cells in a Blob (2)
  • A blob is a collection of contiguous cells that
    are abnormal
  • By contiguous we mean cells that are adjacent,
    horizontally, vertically, or diagonally

69
Counting Cells in a Blob Example
70
Counting Cells in a Blob Recursive Algorithm
  • Algorithm countCells(x, y)
  • if (x, y) outside grid
  • return 0
  • else if color at (x, y) normal
  • return 0
  • else
  • Set color at (x, y) to Temporary (normal)
  • return 1 sum of countCells on neighbors

71
Counting Cells Program Specification
72
Count Cells Code
  • public class Blob implements GridColors
  • private TwoDimGrid grid
  • public Blob(TwoDimGrid grid)
  • this.grid grid
  • public int countCells(int x, int y)
  • ...

73
Count Cells Code (2)
  • public int countCells(int x, int y)
  • if (x lt 0 x gt grid.getNCols()
  • y lt 0 y gt grid.getNRows())
  • return 0
  • Color xyColor grid.getColor(x, y)
  • if (!xyColor.equals(ABNORMAL)) return 0
  • grid.recolor(x, y, TEMPORARY)
  • return 1
  • countCells(x-1,y-1)countCells(x-1,y)
  • countCells(x-1,y1)countCells(x,y-1)
  • countCells(x,y1)countCells(x1,y-1)
  • countCells(x1,y)countCells(x1,y1)

74
Backtracking
  • Backtracking systematic trial and error search
    for solution to a problem
  • Example Finding a path through a maze
  • In walking through a maze, probably walk a path
    as far as you can go
  • Eventually, reach destination or dead end
  • If dead end, must retrace your steps
  • Loops stop when reach place youve been before
  • Backtracking systematically tries alternative
    paths and eliminates them if they dont work

75
Backtracking (2)
  • If you never try exact same path more than once,
    and
  • You try all possibilities,
  • You will eventually find a solution path if one
    exists
  • Problems solved by backtracking a set of choices
  • Recursion implements backtracking
    straightforwardly
  • Activation frame remembers choice made at that
    decision point
  • A chess playing program likely involves
    backtracking

76
Maze Solving Algorithm findPath(x, y)
  1. if (x,y) outside grid, return false
  2. if (x,y) barrier or visited, return false
  3. if (x,y) is maze exit, color PATH and return true
  4. else
  5. set (x,y) color to PATH (optimistically)
  6. for each neighbor of (x,y)
  7. if findPath(neighbor), return true
  8. set (x,y) color to TEMPORARY (visited)
  9. return false

77
Maze Solving Code
  • public class Maze implements GridColors
  • private TwoDimGrid maze
  • public Maze (TwoDimGrid maze)
  • this.maze maze
  • public boolean findPath()
  • return findPath(0, 0)
  • public boolean findPath (int x, int y)
  • ...

78
Maze Solving Code (2)
  • public boolean findPath (int x, int y)
  • if (x lt 0 x gt maze.getNCols()
  • y lt 0 y gt maze.getNRows())
  • return false
  • Color xyColor maze.getColor(x,y)
  • if (!xyColor.equals(BACKGROUND))
  • return false
  • maze.recolor(x, y, PATH)
  • if (x maze.getNCols() 1
  • y maze.getNRows() 1)
  • return true
  • ...

79
Maze Solving Code (3)
  • // square ok, but not end
  • // its colored PATH (tentatively)
  • if (findPath(x-1, y )
  • findPath(x1, y )
  • findPath(x , y-1)
  • findPath(x , y1))
  • return true
  • // a dead end mark visited and return
  • maze.recolor(x, y, TEMPORARY)
  • return false
Write a Comment
User Comments (0)
About PowerShow.com