An Introduction to Programming and Object Oriented Design
An Introduction to Programming and Object Oriented Design using Java 2 nd Edition. May 2004 Jaime Niño Frederick Hosch Chapter 19 : Recursion
Objectives ñ After studying this chapter you should understand the following: ñ recursion, and the relationship between recursive and iterative algorithms; ñ the design of the quick sort algorithm; ñ indirect recursion; ñ backtracking and the class of problems it solves; ñ object recursion and its class structure. May 2004 NH-Chapter 19 1
Objectives ñ Also, you should be able to: ñ write simple recursive algorithms; ñ use backtracking in the solution to problems; ñ structure class definitions to use object recursion. May 2004 NH-Chapter 19 2
Iterative Algorithms ñ Algorithm ñ Specifies a step in the solution process. ñ Step is iterated. ñ After each iteration, we are closer to solution. ñ Solution is reached after a finite number of iterations. May 2004 NH-Chapter 19 3
Recursion ñ Algorithms ñ Solve a trivial, basic case of problem, ñ Solution to general case is reduced to one that is a step closer to basic case. May 2004 NH-Chapter 19 4
Iteration v. s. Recursion ñ Reducing general case to a easier case roughly corresponds to a single iterative step. ñ Reaching base case stops recursion as exit condition stops iteration. May 2004 NH-Chapter 19 5
Iteration v. s. Recursion ñ In an iterative solution ñ step toward solution until while condition is false. ñ explicitly drive repetition with a loop. ñ In a recursive solution, ñ reduce or “unwind” problem until base case. ñ write a solution for base case and for reduction step. May 2004 NH-Chapter 19 6
Recursive solution form if ( trivial case ) solve directly else solve in terms of a slightly easier case May 2004 NH-Chapter 19 7
Sorting a list ñ Trivial case ñ size of list is one or zero. ñ General case ñ Size of list is greater than 1. ñ Slightly easier problem ñ reduce general case to sort a list with one fewer element. May 2004 NH-Chapter 19 8
Sorting a list if ( list is empty or has one element ) solution is easy: do nothing else sort the list, assuming a way of sorting a list with one fewer element is available May 2004 NH-Chapter 19 9
Recursive algorithm implementation ñ Trivial case ñ Solved directly. ñ General case ñ algorithm invokes itself to solve a slightly reduced case. ñ solution is built from solution of slightly reduced case. May 2004 NH-Chapter 19 10
Recursive algorithm execution ñ Results in a chain of self-calls, ñ each a slightly easier problem to solve that previous. ñ Finally method is invoked with trivial case. May 2004 NH-Chapter 19 11
Recursive algorithm correctness ñ Must guarantee that general case will eventually reduce to basic case. May 2004 NH-Chapter 19 12
Example: Exponentiation public static int power (int number, int exponent) The specified number raised to the specified power. require: exponent >= 0 May 2004 NH-Chapter 19 13
Exponentiation iterative solution public static int power (int number, int exponent) { int result = 1; int count = 0; while (count != exponent) { result = number * result; count = count + 1; } return result; } ñ Invariant: result equals number raised to the count power. ñ Exponent requirement to be >= 0 ensures iteration will terminate. May 2004 NH-Chapter 19 14
Exponentiation recursive solution ñ Base cases: raise integer to the power 0. ñ General case: raise integer to the power n, n is an integer and n > 0. ñ Reduction step: raising a number to the power n-1. May 2004 NH-Chapter 19 15
Exponentiation recursive solution ñ Compute number to the power n, assuming we have already computed number to the power n-1. ñ If we have numbern-1, ñ multiply this value by number to get numbern. ñ number n-1 is gotten by a self-call: power (number, n-1) May 2004 NH-Chapter 19 16
Exponentiation recursive solution /** * The specified number raised to the specified power. * require: exponent >= 0 */ public static int power (int number, int exponent) { int result; if (exponent == 0) result = 1; else result = number * power(number, exponent-1); NH-Chapter 19 May 2004 return result; 17
Tracing recursion: invoking power(2, 3) if (exponent == 0) number 2 exponent 3 result = 1; else result = number * power(number, exponent-1); result return result; May 2004 NH-Chapter 19 18
Tracing recursion : invoking power(2, 3) if (exponent == 0) number 2 exponent 3 result = 1; else result = number * power(number, exponent-1); result return result; May 2004 NH-Chapter 19 19
Tracing recursion : invoking power(2, 3) if (exponent == 0) number 2 exponent 3 result = 1; else result = number * power(number, exponent-1); return result; May 2004 result invoke NH-Chapter 19 20
Tracing recursion : invoking power(2, 2) if (exponent == 0) number 2 exponent 2 result = 1; else result = number * power(number, exponent-1); result return result; May 2004 NH-Chapter 19 21
Tracing recursion : invoking power(2, 2) if (exponent == 0) number 2 exponent 2 result = 1; else result = number * power(number, exponent-1); result return result; May 2004 NH-Chapter 19 22
Tracing recursion : invoking power(2, 2) if (exponent == 0) number 2 exponent 2 result = 1; else result = number * power(number, exponent-1); return result; May 2004 result invoke NH-Chapter 19 23
Tracing recursion : invoking power(2, 1) if (exponent == 0) number 2 exponent 1 result = 1; else result = number * power(number, exponent-1); result return result; May 2004 NH-Chapter 19 24
Tracing recursion : invoking power(2, 1) if (exponent == 0) number 2 exponent 1 result = 1; else result = number * power(number, exponent-1); result return result; May 2004 NH-Chapter 19 25
Tracing recursion : invoking power(2, 1) if (exponent == 0) number 2 exponent 1 result = 1; else result = number * power(number, exponent-1); return result; May 2004 result invoke NH-Chapter 19 26
Tracing recursion : invoking power(2, 0) if (exponent == 0) number 2 exponent 0 result = 1; else result = number * power(number, exponent-1); result return result; May 2004 NH-Chapter 19 27
Tracing recursion : invoking power(2, 0) if (exponent == 0) number 2 exponent 0 result 1 result = 1; else result = number * power(number, exponent-1); return result; May 2004 NH-Chapter 19 28
Tracing recursion : invoking power(2, 0) if (exponent == 0) number 2 exponent 0 result 1 result = 1; else result = number * power(number, exponent-1); return result; May 2004 NH-Chapter 19 29
Tracing recursion: resuming power(2, 1) if (exponent == 0) number 2 exponent 1 result = 1; else result = number * power(number, exponent-1); return result; May 2004 result Result of previous call 1 NH-Chapter 19 30
Tracing recursion : resuming power(2, 1) if (exponent == 0) number 2 exponent 1 result 2 result = 1; else result = number * power(number, exponent-1); return result; May 2004 NH-Chapter 19 31
Tracing recursion : resuming power(2, 1) if (exponent == 0) number 2 exponent 1 result 2 result = 1; else result = number * power(number, exponent-1); return result; May 2004 NH-Chapter 19 32
Tracing recursion : resuming power(2, 2) if (exponent == 0) number 2 exponent 2 result = 1; else result = number * power(number, exponent-1); return result; May 2004 result Result of previous call 2 NH-Chapter 19 33
Tracing recursion : resuming power(2, 2) if (exponent == 0) number 2 exponent 2 result 4 result = 1; else result = number * power(number, exponent-1); return result; May 2004 NH-Chapter 19 34
Tracing recursion : resuming power(2, 2) if (exponent == 0) number 2 exponent 2 result 4 result = 1; else result = number * power(number, exponent-1); return result; May 2004 NH-Chapter 19 35
Tracing recursion : resuming power(2, 3) if (exponent == 0) number 2 exponent 3 result = 1; else result = number * power(number, exponent-1); return result; May 2004 result Result of previous call 4 NH-Chapter 19 36
Tracing recursion : resuming power(2, 3) if (exponent == 0) number 2 exponent 3 result 8 result = 1; else result = number * power(number, exponent-1); return result; May 2004 NH-Chapter 19 37
Tracing recursion : resuming power(2, 3) if (exponent == 0) number 2 exponent 3 result 8 result = 1; else result = number * power(number, exponent-1); return result; May 2004 NH-Chapter 19 38
Finding the minimum element: Recursive version public int min. Final. Exam (List<Student> students) The lowest final exam grades of the specified Students. require: students. size() > 0 May 2004 NH-Chapter 19 39
Finding the minimum element: Recursive version ñ Base case: find smallest on list containing one element. ñ General case: find smallest on list with n elements, where n > 1. ñ Reducing general case: find smallest on list with n-1 elements. May 2004 NH-Chapter 19 40
Finding the minimum element: Recursive version ñ how to find smallest of n elements, assuming we know how to find smallest of n-1 elements. ñ Find smallest of the n-1 elements after first. ñ Find smallest of this and the first. May 2004 NH-Chapter 19 41
Finding the minimum element: Recursive version private int min. Final. Exam (List<Student> students, int first) The lowest final exam grades of Students on the list with indexes greater than or equal to first. require: 0 <= first && first < students. size() public int min. Final. Exam (List<Student> students) { return min. Final. Exam(students, 0); } May 2004 NH-Chapter 19 42
Finding the minimum element: Recursive version private int min. Final. Exam (List<Student> students, int first) { int smallest; int grade. Of. First = students. get(first). final. Exam(); if (first == students. size()-1) { smallest = grade. Of. First; // the base case else {// the general case: int min. Of. Rest = min. Final. Exam(students, first+1); if (min. Of. Rest < grade. Of. First) smallest = min. Of. Rest; else smallest = grade. Of. First; } return smallest; } May 2004 NH-Chapter 19 43
Selection sort: recursive version ñ Base cases: sort an empty list or with 1 element. ñ General case: sort a list containing n elements, n > 1. ñ Reducing general case: sort a list containing n-1 elements. May 2004 NH-Chapter 19 44
Selection sort: recursive version ñ Find the smallest element and put it in first place. ñ Sort the remaining n-1 elements. ñ Note: sorting the remaining n-1 elements, refers to a segment of the list first remaining n-1 elements May 2004 NH-Chapter 19 45
Selection sort: recursive version private static <Element> void selection. Sort ( List<Element> list, int first, Order<Element> order) { if (first < list. size()) { find the smallest element and put it first; sort the remaining n-1 elements } } May 2004 NH-Chapter 19 46
Selection sort: recursive version private static <Element> void selection. Sort ( List<Element> list, int first, Order<Element> order) { if (first < list. size()) { int small = smallest. Of(list, first, list. size()-1, order); interchange(list, first, small); selection. Sort(list, first+1, order); } } May 2004 NH-Chapter 19 47
Selection sort: recursive version public static <Element> void selection. Sort ( List<Element> list, Order<Element> order) { selection. Sort(list, 0, order); } May 2004 NH-Chapter 19 48
Towers of Hanoi ñ move stack of disks from starting peg to one of the other pegs. Disks are moved one at a time, and a disk can never be placed on top of a smaller one. May 2004 NH-Chapter 19 49
Example of moves with 3 discs 1 May 2004 2 NH-Chapter 19 3 50
Example of moves with 3 discs 1 May 2004 2 NH-Chapter 19 3 51
Example of moves with 3 discs 1 May 2004 2 NH-Chapter 19 3 52
Example of moves with 3 discs 1 May 2004 2 NH-Chapter 19 3 53
Example of moves with 3 discs 1 May 2004 2 NH-Chapter 19 3 54
Example of moves with 3 discs 1 May 2004 2 NH-Chapter 19 3 55
Example of moves with 3 discs 1 May 2004 2 NH-Chapter 19 3 56
Example of moves with 3 discs 1 May 2004 2 NH-Chapter 19 3 57
Example of moves with 3 discs 1 May 2004 2 NH-Chapter 19 3 58
Example of moves with 3 discs 1 May 2004 2 NH-Chapter 19 3 59
Example of moves with 3 discs 1 May 2004 2 NH-Chapter 19 3 60
Example of moves with 3 discs 1 May 2004 2 NH-Chapter 19 3 61
Example of moves with 3 discs 1 May 2004 2 NH-Chapter 19 3 62
Example of moves with 3 discs 1 May 2004 2 NH-Chapter 19 3 63
Example of moves with 3 discs 1 May 2004 2 NH-Chapter 19 3 64
Puzzle. Solver method move. Tower public void move. Tower (int size, int from, int to) Move a tower of the specified number of disks from the specified starting peg to the specified destination peg. require: size >= 1 1 <= from && from <= 3 1 <= to && to <= 3 from != to May 2004 NH-Chapter 19 65
Puzzle. Solver method move. Tower ñ It uses a private method to move one disc: private void move. Disk (int from, int to) Move a single disk from the specified peg to the specified destination. require: 1 <= from && from <= 3 1 <= to && to <= 3 from != to May 2004 NH-Chapter 19 66
Puzzle. Solver method move. Tower ñ Base case: a tower with 1 disc. ñ General case: a tower with n discs. ñ Reduction case: move a tower with n-1 discs. May 2004 NH-Chapter 19 67
Puzzle. Solver method move. Tower ñ Reduce problem of moving n disks to problem of moving n-1: ñ Move n-1 disks from the starting peg to the “other” peg. ñ Move a disk from the starting peg to the destination peg. ñ Move n-1 disks from the “other” peg to the destination peg. ñ To find “other” peg ñ subtract source peg number (from) and destination peg number (to) from 6 (= 1 + 2 + 3). May 2004 NH-Chapter 19 68
Puzzle. Solver : move. Tower implementation public void move. Tower (int n, int from, int to) { if (n == 1) { move. Disk(from, to); } else { int other = 6 -from-to; // not from or to move. Tower(n-1, from, other); move. Disk(from, to); move. Tower(n-1, other, to); } } May 2004 NH-Chapter 19 69
Puzzle. Solver: move. Disk ñ Simply solution: private void move. Disk (int from, int to) { System. out. println( "Move a disk from peg " + from + " to peg " + to + '. '); } May 2004 NH-Chapter 19 70
Puzzle. Solver: move. Disk ñ Not very satisfactory. ñ Puzzle. Solver is a model class; ñ should be independent of the user interface. May 2004 NH-Chapter 19 71
Puzzle. Solver: move. Disk ñ Better way to implement move. Disk ñ Use the Observer pattern. ñ When output client is notified, pass move to make: public class Move A move in the Towers puzzle. Pegs are numbered 1, 2, 3. public Move (int from, int to) Create a move of a disk from the peg from to the peg to. public int from () Peg the disk is moved from. public int to () Peg the disk is moved to. May 2004 NH-Chapter 19 72
Puzzle. Solver: move. Disk private void move. Disk (int from, int to) { set. Changed(); notify. Observers(new Move(from, to)); } May 2004 NH-Chapter 19 73
Quicksort ñ Quicksort 1. puts an arbitrary element in proper position, 2. smaller elements are below it. 3. larger elements are above it. ñ Sublists 2, 3 are recursively sorted. May 2004 NH-Chapter 19 74
Quicksort ñ Implement a private method to sort a list segment. ñ sort calls method with entire list: public static <Element> void quick. Sort ( List<Element> list, Order<Element> order) { quick. Sort(list, 0, list. size()-1, order); } //Sort list elements indexed first through last. // require 0 <= first && last < list. size() private static <Element> void quick. Sort ( List<Element> list, int first, int last, Order<Element> order) { … } May 2004 NH-Chapter 19 75
Quicksort ñ Base case ñ an empty list or a list with a single element. ñ The general case is handled by the three steps: 1. puts an arbitrary element in proper position, 2. smaller elements are below it. 3. larger elements are above it. ñ Sublists 2, 3 are sorted. May 2004 NH-Chapter 19 76
Quicksort: partition ñ This method positions pivot such that: ñ Smaller elements in list are below it. ñ Larger elements in list are above it. ñ Reports where pivot was placed. May 2004 NH-Chapter 19 77
Quicksort private static <Element> void quick. Sort List<Element> list, int first, int last, Order<Element> order) { ( if (first < last) { int position; // pivot index position = partition(list, first, last, order); quick. Sort(list, first, position-1, order); quick. Sort(list, position+1, last, order); } } May 2004 NH-Chapter 19 78
Quicksort: partition ñ Choose middle element of sublist as pivot element. ñmove the pivot element into the last position May 2004 NH-Chapter 19 79
Quicksort: partition s s s L L L ? ? ? 28 (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) pi May 2004 i NH-Chapter 19 80
Quicksort: partition ñ i, pi start at 0 ñ Compare i-th entry with pivot pi May 2004 i NH-Chapter 19 81
Quicksort: partition ñ Compare i-th entry with pivot. pi i May 2004 NH-Chapter 19 82
Quicksort: partition ñ Compare i-th entry with pivot. pi May 2004 i NH-Chapter 19 83
Quicksort: partition ñ Compare i-th entry with pivot. It’s less. ñ Swap and increment indices. pi May 2004 i NH-Chapter 19 84
Quicksort: partition ñ Compare i-th entry with pivot. 12 41 45 61 55 1 46 56 23 3 18 73 19 30 28 (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10)(11)(12)(13)(14) pi May 2004 i NH-Chapter 19 85
Quicksort: partition ñ Compare i-th entry with pivot. It’s less. ñ Swap and increment indices. 12 41 45 61 55 1 46 56 23 3 18 73 19 30 28 (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10)(11)(12)(13)(14) pi May 2004 i NH-Chapter 19 86
Quicksort: partition ñ Compare i-th entry with pivot. 12 1 45 61 55 41 46 56 23 3 18 73 19 30 28 (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10)(11)(12)(13)(14) pi May 2004 i NH-Chapter 19 87
Quicksort: partition ñ Compare i-th entry with pivot. 12 1 45 61 55 41 46 56 23 3 18 73 19 30 28 (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10)(11)(12)(13)(14) pi May 2004 i NH-Chapter 19 88
Quicksort: partition ñ Compare i-th entry with pivot. It’s less. ñ Swap and increment. 12 1 45 61 55 41 46 56 23 3 18 73 19 30 28 (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10)(11)(12)(13)(14) pi May 2004 i NH-Chapter 19 89
Quicksort: partition ñ Compare i-th entry with pivot. It’s less. ñ Swap and increment indices. 12 1 23 61 55 41 46 56 45 3 18 73 19 30 28 (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10)(11)(12)(13)(14) pi May 2004 i NH-Chapter 19 90
Quicksort: partition ñ Compare i-th entry with pivot. It’s less. ñ Swap and increment indices. 12 1 23 3 55 41 46 56 45 61 18 73 19 30 28 (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10)(11)(12)(13)(14) pi May 2004 i NH-Chapter 19 91
Quicksort: partition ñ Compare i-th entry with pivot. 12 1 23 3 18 41 46 56 45 61 55 73 19 30 28 (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10)(11)(12)(13)(14) pi May 2004 i NH-Chapter 19 92
Quicksort: partition ñ Compare i-th entry with pivot. It’s less ñ Swap and increment indices. 12 1 23 3 18 41 46 56 45 61 55 73 19 30 28 (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10)(11)(12)(13)(14) pi May 2004 i NH-Chapter 19 93
Quicksort: partition ñ Compare i-th entry with pivot. 12 1 23 3 18 19 46 56 45 61 55 73 41 30 28 (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10)(11)(12)(13)(14) pi May 2004 NH-Chapter 19 i 94
Quicksort: partition ñ Loop exited. Swap pivot with pi. 12 1 23 3 18 19 46 56 45 61 55 73 41 30 28 (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10)(11)(12)(13)(14) pi May 2004 NH-Chapter 19 i 95
Quicksort: partition 12 1 23 3 18 19 28 56 45 61 55 73 41 30 46 (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10)(11)(12)(13)(14) pi May 2004 NH-Chapter 19 i 96
partition implementation private static <Element> int partition (List<Element> list, int first, int last, Order<Element> order) { int pi; // pivot index int i; // index of the next to examine Element pivot; // pivot item int mid = (first+last)/2; pivot = list. get(mid); interchange(list, mid, last); // put pivot item at end. pi = first; while (i != last) { // list. get(last) is pivot item if (order. in. Order(list. get(i), pivot)) { interchange(list, pi, i); pi = pi+1; } i = i+1; } interchange(list, pi, last); // put pivot item in place return pi; } May 2004 NH-Chapter 19 97
Indirect Recursion ñ Method m 1 invokes m 2 which invokes m 3 … which invokes mn which invokes m 1. May 2004 NH-Chapter 19 98
Indirect Recursion: Remove. Set ñ Given a balanced string of parentheses as argument, removes the first balanced substring from the front. ñ Examples ñ remove. Set("()") "" ñ remove. Set("()()") "()()()" ñ remove. Set("((()))") "" ñ remove. Set("(()()))()(())") "()(())" May 2004 NH-Chapter 19 99
Remove. Set design ñ Remove first “(“ ñ Invoke reduce. Closed for matching “)” private String reduce. Closed (String s) A String equal to specified String with first substring with one more closed parenthesis than open parenthesis removed. May 2004 NH-Chapter 19 100
Remove. Set design ñ For example, ñ reduce. Closed(")") "“ ñ reduce. Closed(")()()") "()()“ ñ reduce. Closed("(()()))(()) "(())“ ñ reduce. Closed("()()(()()))()(())") "()(())" May 2004 NH-Chapter 19 101
Remove. Closed design ñ Basic case: first character is “)”. ñ General case : first character of s is open parenthesis; then s starts with balanced substring. ñ Remove balanced substring, ñ Recursively apply method to what’s left. May 2004 NH-Chapter 19 102
Remove. Closed design ñ Use remove. Set to remove balanced substring : private String reduce. Closed (String s) { if (head(s) == ')') return tail(s); else // head(s) == '(‘, remove balanced set return reduce. Closed(remove. Set(s)); } May 2004 NH-Chapter 19 103
Backtracking ñ Algorithmic technique for solving problems that cannot be solved directly. ñ Backtracking is used when a large set of possible solutions must be examined to find an actual solution to the problem. May 2004 NH-Chapter 19 104
Backtracking ñ For backtracking to be an appropriate technique, problem solution must be: ñ a composite, made up of parts; ñ constructible in a series of steps, with each step adding a piece to the solution. ñ At each step there will several possible ways of extending the partial solution of the previous step. Some of these alternative will lead to a solution, others will not. May 2004 NH-Chapter 19 105
Backtracking example ñ suppose we have a maze consisting of a set of rooms connected by passages. ñ Each room is connected to one or more passages. ñ A passage may lead to another room, or may lead to the maze exit. May 2004 NH-Chapter 19 106
Backtracking example ñ For instance, a maze with seven rooms might look like this, where the rooms are lettered and the doors are labelled north, south, east, west. May 2004 NH-Chapter 19 107
Backtracking example ñ Problem: find a path from a given room to the exit. ñ Note solution is composite: ñ “to reach the exit from room F, go south to room D, west to room C, east to room E, east to the exit. ” ñ The path can be constructed in a series of steps, each step adding a component to the partial solution built in the previous step. May 2004 NH-Chapter 19 108
Backtracking example ñ At each step, there may be several alternatives. ñ For example, the first step in the above solution is “go south to room D. ” ñ This partial solution can be extended in two ways: “go west to room C” or “go south to room G. ” ñ The first option leads to a solution, while the second does not. Room G is a dead end. May 2004 NH-Chapter 19 109
Backtracking example ñ Backtracking works by repeatedly extending a partial solution until a solution is found or a “dead end” is reached. ñ A dead end is simply a state that cannot be further extended. ñ If a dead end is reached, the algorithm “backs up” to the most recent point at which untried possibilities exist, and tries one. May 2004 NH-Chapter 19 110
Backtracking example ñ To see how this works, suppose we are trying to reach the exit from room A in the above maze. room A: go north to room B: dead end; back up to room A. go south to room C: go north to room D: go east to room F dead end; back up to room D. go south to room G dead end; back up to room D. no more choices (dead end); back up to room C go east to room E: go east to exit. May 2004 NH-Chapter 19 111
Implementing backtracking ñ Implement a backtracking algorithm for the maze traversal problem. ñ A Maze is composed of a number of Rooms, with each Room connected to a number of other Rooms. May 2004 NH-Chapter 19 112
Implementing backtracking public List<Room> connections () The list of Rooms this Room is connected to. public boolean is. Exit () This Room is a maze exit. May 2004 NH-Chapter 19 113
Implementing backtracking public class Path. Point A Room and a connection from the Room. public Path. Point (Room room, int connection) Create a new Path. Point. require: 0<=connection&& connection < room. connections(). size() May 2004 NH-Chapter 19 114
Implementing backtracking ñ A path is a list of Path. Points modeling a sequence of connected Rooms. ñ If Path. Point [B, j] follows [A, i] on list, then connection i from Room A leads to Room B. That is, A. connections(i) == B. ñ Require: path has no repeated Rooms. ñ A Path from Room A to H is : [(A, 1), (C, 2), (E, 1)] May 2004 NH-Chapter 19 115
Implementing backtracking ñ write a method that will produce an exit path from a specified Room: public List<Path. Point> exit. Path. From (Room room) A path leading from the specified Room to an exit; returns null if no path exists. ñuse an auxiliary method that takes a partial solution and extends it. private List<Path. Point> extended. Path. From (Room room, List<Path. Point> path) The specified path extended from the specified Room to an exit. Returns null if the path cannot be extended to an exit. The specified path must be empty or lead to the specified Room. May 2004 NH-Chapter 19 116
Implementing backtracking ñ The public method calls the auxiliary method with an empty initial path: public List<Path. Point> exit. Path. From (Room room) { return extended. Path. From( room, new Default. List<Path. Point>()); } May 2004 NH-Chapter 19 117
Implementing backtracking private List<Path. Point> extended. Path. From ( Room room, List<Path. Point> path) { if (room. is. Exit()) return path; else { boolean found = false; List<Path. Point> solution = null; int i = 0; while (i < room. connections(). size() && !found){ // get a Room to extend the path Room next. Room = room. connections(). get(i); if (!path. Contains(path, next. Room)) { List<Path. Point> extended. Path = path. copy(). add(new Path. Point(room, i)); solution = extended. Path. From(next. Room, extended. Path); found = solution != null; } i = i+1; } return solution; } NH-Chapter 19 May 2004 } 118
Object recursion ñ Examine another form of recursion, called structural recursion or object recursion. ñ Structural recursion uses object structure in a recursive manner to derive problem solutions. May 2004 NH-Chapter 19 119
Object recursion ñ Two flavors of solver objects: ñ General problem solver, ñ the trivial problem solver. ñ We make these children of a common abstract parent: May 2004 NH-Chapter 19 120
Object recursion ñ Construct an odometer-like counter consisting of a sequence of digits. ñ A digit turning over from 9 to 0 causes its left neighbor to increment ñ A solution is simply a stable state of the counter, one in which all digits are set. ñ to find first solution: that is, reset all digits to 0. ñ to find next solution: increment the counter by 1. ñ There is a final solution, all digits are 9. ñ We specify that attempting to find the next solution after the final state will fail: i. e. , a counter that is all 9 s will not turn over to all 0 s. May 2004 NH-Chapter 19 121
Object recursion ñ Digit: general solver class. ñ Each Digit instance is responsible for a single digit of the solution. ñ Each Digit has an associate, the Digit to its left. ñ A Digit extends solution provided by its associate. ñ Digits are “linked together” to form the counter. ñ The high-order (left-most) Digit has a Null. Digit as its associate. (it needs no associate). ñ Null. Digit trivial solver class. ñ The logic in the Null. Digit simply ends the recursion. May 2004 NH-Chapter 19 122
Object recursion: Digit. Counter ñNote: a Digit and its associate have the same structure. May 2004 NH-Chapter 19 123
Object recursion: Digit. Counter public class Digit. Counter { private Virtual. Digit low. Digit; // right-most /** * Create a new Digit. Counter with the specifi * number of digits. * @require : digits >= 1 */ public Digit. Counter (int digits) { Virtual. Digit d = new Null. Digit(); for (int i = 1; i <= digits; i = i+1) d = new Digit(d); low. Digit = d; } … May 2004 NH-Chapter 19 124
Object recursion: Digit. Counter public void first () { low. Digit. first(); } public void next () { low. Digit. next(); } public boolean solved () { return low. Digit. solved(); } public String to. String () { return low. Digit. to. String(); } //definition of Virtual. Digit interface // Digit class, Null. Digit class. }//end Digit. Counter May 2004 NH-Chapter 19 125
Object recursion: Digit. Counter ñDigit. Counter contains a private interface implemented by Digit and Null. Digit. private interface Virtual. Digit { public boolean solved (); public void first (); public void next (); public String to. String (); } May 2004 NH-Chapter 19 126
Object recursion: Digit ñDigit class ñImplements Virtual. Digit interface. ñContains an int as data component for the digit. ñWhen given command first, instructs left neighbor to find first number, and then sets itself to 0. ñWhen given the command next, ñit increments its digit if it’s not 9. ñIf its digit is 9, it instructs its left neighbor to increment, and sets itself to 0. ñIn each case checks neighbor was successful. May 2004 NH-Chapter 19 127
Object recursion: Digit private class Digit implements Virtual. Digit public { void next () { private Virtual. Digit associate; // left if nghb (digit < 9) { private boolean solved; // valid num digit = digit + 1; private int digit; // my digit solved = true; } else { public Digit (Virtual. Digit associate) { associate. next(); this. associate = associate; if (associate. solve this. digit = 0; this. solved = false; solved = true; } } else public boolean solved () { solved = false; return solved; } } } public void first () { public String to. String () { associate. first(); if (solved) if (associate. solved()) { return associate. to. Str digit = 0; else solved = true; return "No solution"; } else } solved = false; }//end Digit } May 2004 NH-Chapter 19 128
Object recursion: Null. Digit private class Null. Digit implements Virtual. Digit { private boolean solved; public Null. Digit () { this. solved = false; } public boolean solved () { return solved; } public void first () { solved = true; } public void next () { solved = false; } public String to. String () { if (solved) return ""; else return "No solution"; } } May 2004 NH-Chapter 19 129
Summary ñ Introduced the problem solving technique of recursion. ñ Two forms of recursive computation: ñ algorithmic recursion, in which a method invokes itself directly or indirectly, ñ object recursion, based on the creation of composite object structure in which the structure of a component is the same as that of the composite object. May 2004 NH-Chapter 19 130
Summary ñ Algorithmic recursion solution logic depends on ñ identifying simple base cases that can be easily solved directly, and ñ describing how to reduce the general case to one that is slightly simpler: that is, slightly closer to a base case. ñ The method that actualizes this logic invokes itself to solve the slightly simpler case to which the general case is reduced. May 2004 NH-Chapter 19 131
Summary ñ A well-known algorithm using direct recursion is quick sort. ñ Quick sort is much more efficient that the selection and bubble sorts generally requiring on the order of n log 2 n steps to sort a list of n elements. ñ Quick sort works by ñ positioning an arbitrary element, with smaller elements below and larger elements above. ñ list segments containing the smaller elements and the larger elements are then recursively sorted. May 2004 NH-Chapter 19 132
Summary ñ Indirect recursion, a method is invoked before it returns through a sequence of other method invocations. That is, ñ method m 1 invokes m 2 which invokes m 3 … which invokes mn which invokes m 1. ñ When indirect recursion is used, we generally set a collection of mutually recursive methods. May 2004 NH-Chapter 19 133
Summary ñ Backtracking is an algorithmic technique for examining a set of possible solutions to a problem in an organized way in order to find an actual solution. ñ Solution to problem is a composite, made up of several pieces. ñ Each step in a backtracking algorithm attempts to extend partial solution produced by the previous step. ñ If not possible to extend partial solution, algorithm “backs up” to find another partial solution to extend. May 2004 NH-Chapter 19 134
Summary ñ Using object recursion, a solver object is structured with a similar solver object as an associate. ñ Solver object delegates the responsibility of solving a simpler version of the problem to its associate, and then extends the solution provided by the associate. ñ Recursive nature of approach is seen here : a solution to the general case is found by using a solution to a simpler case given by the associate. May 2004 NH-Chapter 19 135
- Slides: 136