Simple Recursion Algorithm

Document Sample
Simple Recursion Algorithm Powered By Docstoc
					Simple Recursive Algorithms

        A short list of categories
   Algorithm types we will consider include:
       Simple recursive algorithms
       Backtracking algorithms
       Divide and conquer algorithms
       Dynamic programming algorithms
       Greedy algorithms
       Branch and bound algorithms
       Brute force algorithms
       Randomized algorithms

        Simple recursive algorithms
   A simple recursive algorithm:
       Solves the base cases directly
       Recurs with a simpler subproblem or subproblems
       May do some extra work to convert the solution to the
        simpler subproblem into a solution to the given problem
   I call these “simple” because several of the other
    algorithm types are inherently recursive

        Some example algorithms
   We will look briefly at the following simple
    recursive algorithms:
       Factorial
       All permutations
       Tree traversal
       Flood fill
       Quicksort
       Towers of Hanoi
       Ackermann’s function
   We will also consider the equivalence of loops and

   The factorial function is the “Hello World” of recursion
       public static long factorial(int n) {
          if (n <= 1) return 1;
          else return n * factorial(n - 1);
   The problem with this example is that it can be done almost
    as easily with a loop (so why bother learning recursion?)
       public static long factorial(int n) {
          int result = 1;
          while (n > 1) {
             result *= n;
   In the following slides, we look at some example problems
    for which recursion really is simpler
   A permutation of a set of objects is a particular ordering
    of those objects
   When we speak of “all permutations” of a set, we mean
    all possible ways of ordering those objects
   Examples:
       Given the empty set { }, the only possible permutation is { }
       Given the set {A}, the only possible permutation is {A}
       Given the set {A, B}, the possible permutations are {AB, BA}
       Given the set {A, B, C}, the possible permutations are
        {ABC, ACB, BAC, BCA, CAB, CBA}
       Etc.

        Finding all permutations of n objects
   To find all permutations of n objects:
       Find all permutations of n-1 of those objects
       Insert the remaining object into all possible positions of each
        permutation of n-1 objects
   Example: To find all permutations of 3 objects {A, B, C}
       Find all permutations of 2 of the objects, say B and C:
                B     C         and           C       B
       Insert the remaining object, A, into all possible positions
        (marked by ^) in each of the permutations of B and C:
          ^ B ^ C ^             and      ^ C ^ B ^
         ABC BAC BCA                    ACB CAB CBA

         A program to find permutations
   We will develop complete Java code to find all permutations of
    a nonempty String of characters
   ArrayList<String> permutationsOf(String s) {
       if (s.length() == 1) {
           // return a new ArrayList containing just s
       else {
           // separate the first character from the rest
           // get all permutationsOf ( the rest of the characters )
           // for each permutation,
           //      add the first character in all possible positions, and
           //      put each result into a new ArrayList
       // return the new ArrayList
    permutationsOf(String), part I
ArrayList<String> permutationsOf(String s) {
   ArrayList<String> result = new ArrayList<String>();

  if (s.length() == 1) { // base case
      // return a new ArrayList containing just s
      return result;
   // continued...

        permutationsOf(String), part II
    else {
      // separate the first character from the rest
      char first = s.charAt(0);
      String rest = s.substring(1);

        // get all permutationsOf the rest of the characters
        ArrayList<String> simpler = permutationsOf(rest); // recursive step

        // for each permutation,
        for (String permutation : simpler) { // extra work
           // add the first character in all possible positions, and
           ArrayList additions = insertAtAllPositions(first, permutation);
           // put each result into a new ArrayList
        return result;
        Insert in all positions
   Given one String representing one permutation of n-1 characters,
    we want to return all permutations resulting from inserting a
    given character in all n possible positions

     private ArrayList<String> insertAtAllPositions(char ch, String s) {
       ArrayList<String> result = new ArrayList<String>();
       for (int i = 0; i <= s.length(); i++) {
          String inserted = s.substring(0, i) + ch + s.substring(i);
       return result;

   A tree is composed of nodes            nodes                  root
       Each node contains a value
       Each node may have children
       One special node is called the        B       C       D     E
        root of the tree
       Nodes with children are           F   G       H       I     J    K
        called internal nodes
       Nodes without children are                L       M        N
        called leaves

         Tree traversals
   It’s easy to traverse (“walk”) a tree recursively
   Here’s a recursive method which, if called with the root of a
    tree, will print out all the values in the tree:
        void printTree(Node n) {
            print the value in node n;
            for each child c of n, printTree(c)
   Or, in actual Java:
    void printTree(Node n) {
       Iterator iter = node.getChildren().iterator();
       while (iter.hasNext()) {
   Many data structures are best handled recursively

        Flood fill
   To “flood fill” an area with color oldColor, starting
    from a particular pixel of color newColor:

       void floodFill(Pixel p, Color oldColor, Color newColor) {
           if p is not oldColor, just return
           else {
              set color of p to newColor
              for each pixel q adjacent to p (horizontally or vertically),
                  floodFill(q, oldColor, newColor)

   Quicksort is (in some sense) the fastest sorting
    algorithm known
       From an array of numbers, pick one to use as a pivot
       45 3 17 48 72 25 8 99 14 9 12 21 81 64 33 12
        (we’ll use 45 as the pivot)
       Partition the numbers into those smaller than or equal to the
        pivot, and those larger than the pivot
       3 17 25 8 14 9 12 21 33 12 45 48 72 99 81 64

            Now quicksort the left side:         And the right side:
        3 8 9 12 12 14 17 21 25 33 45 48 64 72 81 99

        Towers of Hanoi
   “Towers of Hanoi” is commonly used as an example
    of a problem with a simple recursive solution
       There are three pegs
       The first (source) peg holds some
        number of rings
       You want to move all rings to the
        last (destination) peg
       You can only move one ring at a
       You can never put a larger ring     src   aux   dest
        on top of a smaller ring
       You have one auxiliary peg you
        can use
        Solution to Towers of Hanoi

                 src      aux        dest

   Move the top n-1 rings from src to aux (recursively)
   Move the largest ring from src to dest
   Move the n-1 rings from aux to dest (recursively)

   Notice that there are two recursive calls in this algorithm
       Hence, the number of calls doubles at each level of the recursion
   For a large number of rings, this is a very expensive algorithm!

        Ackermann’s function
   Ackermann’s function is a deceptively simple little set
    of equations:
       A(0, y) = y + 1
       A(x, 0) = A(x - 1, 1)
       A(x, y) = A(x - 1, A(x, y - 1))
   This can easily be written as a recursive method
       A(4, 0) = 13
       A(4, 1) = 65533
       A(4, 2) = 2 65536-3
   After this, the numbers start to get huge quickly
   This function takes a long time to compute (why?)
        Recursion isn’t necessary
   Computers don’t have “recursive hardware”!
   When a higher-level language is compiled, recursive calls are
    implemented with a stack
       When you enter a method, all its local variables (including its formal
        parameters) are created and put onto a stack
       The method operates on its own copies of the local variables
       When the method exits, its local variables are removed from the stack
   The compiler changes recursive code into nonrecursive code
   It follows, then, that anything you could do recursively, you
    could also do nonrecursively by using loops and a stack

        Tree traversals, again
   Here’s a recursive method which, if called with the root of a
    tree, will print out all the values in the tree:
       void printTree(Node n) {
           print the value in node n;
           for each child c of n {
   Here it is without recursion:
       void printTree(Node n) {
           create a new stack s;
           push n onto s;
           while (s is not empty) {
              remove a node m from s and print it
              push the children of m (if any) onto stack s
        Loops aren’t necessary
   You can replace any recursion with loops (and a stack for local variables)
   In addition, you can replace any loop with a recursion
   For example, consider zeroing out an array:
      static void zeroOut(int[] a) {
            for (int i = 0; i < a.length; i++) a[i] = 0;
   Or:
      static void zeroOut(int[] a, int n) { // call with n = 0
            if (n < a.length) {
                a[n] = 0;
                zeroOut(a, n + 1);
   Of course, this is an example, not a proof
   It can be proved (we won’t do it here) that loops can always be replaced by

       Closing comments
   The intent of this set of slides is to get you more
    familiar with some of the uses of recursion
   Recursion and loops are, in some sense, equivalent--
    anything you can do with one, you can do with the
   Once you understand recursion, though, it is often
    simpler to use recursion than to use loops

The End


Shared By: