chapter 19 : recursion
DESCRIPTION
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; - PowerPoint PPT PresentationTRANSCRIPT
An Introduction to Programming and Object
Oriented Design using Java2nd Edition. May 2004
Jaime NiñoFrederick Hosch
Chapter 19 : Recursion
2May 2004 NH-Chapter 19
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.
3May 2004 NH-Chapter 19
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.
4May 2004 NH-Chapter 19
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.
5May 2004 NH-Chapter 19
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.
6May 2004 NH-Chapter 19
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.
7May 2004 NH-Chapter 19
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.
8May 2004 NH-Chapter 19
Recursive solution form
if ( trivial case )
solve directly
else
solve in terms of a slightly easier case
9May 2004 NH-Chapter 19
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.
10May 2004 NH-Chapter 19
Sorting a list
if ( list is empty or has one element )solution is easy: do nothing
elsesort the list, assuming a way of sorting a listwith one fewer element is available
11May 2004 NH-Chapter 19
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.
12May 2004 NH-Chapter 19
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.
13May 2004 NH-Chapter 19
Recursive algorithm correctness
Must guarantee that general case will eventually reduce to basic case.
14May 2004 NH-Chapter 19
Example: Exponentiation
public static int power (int number, int exponent)The specified number raised to the specified power.
require:exponent >= 0
15May 2004 NH-Chapter 19
Exponentiation iterative solution
Invariant: result equals number raised to the count power. Exponent requirement to be >= 0 ensures iteration will terminate.
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;
}
16May 2004 NH-Chapter 19
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.
17May 2004 NH-Chapter 19
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)
18May 2004 NH-Chapter 19
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);return result;
}
19May 2004 NH-Chapter 19
Tracing recursion: invoking power(2,3)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
3
20May 2004 NH-Chapter 19
Tracing recursion : invoking power(2,3)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
3
21May 2004 NH-Chapter 19
Tracing recursion : invoking power(2,3)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
3
invoke
22May 2004 NH-Chapter 19
Tracing recursion : invoking power(2,2)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
2
23May 2004 NH-Chapter 19
Tracing recursion : invoking power(2,2)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
2
24May 2004 NH-Chapter 19
Tracing recursion : invoking power(2,2)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
2
invoke
25May 2004 NH-Chapter 19
Tracing recursion : invoking power(2,1)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
1
26May 2004 NH-Chapter 19
Tracing recursion : invoking power(2,1)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
1
27May 2004 NH-Chapter 19
Tracing recursion : invoking power(2,1)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
1
invoke
28May 2004 NH-Chapter 19
Tracing recursion : invoking power(2,0)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
0
29May 2004 NH-Chapter 19
Tracing recursion : invoking power(2,0)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
0
1
30May 2004 NH-Chapter 19
Tracing recursion : invoking power(2,0)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
0
1
31May 2004 NH-Chapter 19
Tracing recursion:resuming power(2,1)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
1
Result of previous call
1
32May 2004 NH-Chapter 19
Tracing recursion :resuming power(2,1)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
1
2
33May 2004 NH-Chapter 19
Tracing recursion :resuming power(2,1)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
1
2
34May 2004 NH-Chapter 19
Tracing recursion :resuming power(2,2)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
2
Result of previous call
2
35May 2004 NH-Chapter 19
Tracing recursion :resuming power(2,2)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
2
4
36May 2004 NH-Chapter 19
Tracing recursion :resuming power(2,2)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
2
4
37May 2004 NH-Chapter 19
Tracing recursion :resuming power(2,3)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
3
Result of previous call
4
38May 2004 NH-Chapter 19
Tracing recursion :resuming power(2,3)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
3
8
39May 2004 NH-Chapter 19
Tracing recursion :resuming power(2,3)
if (exponent == 0)
result = 1;
else
result = number * power(number,exponent-1);
return result;
number
exponent
result
2
3
8
40May 2004 NH-Chapter 19
Finding the minimum element: Recursive version
public int minFinalExam (List<Student> students)
The lowest final exam grades of the specified Students.
require:students.size() > 0
41May 2004 NH-Chapter 19
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.
42May 2004 NH-Chapter 19
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.
43May 2004 NH-Chapter 19
Finding the minimum element: Recursive version
private int minFinalExam (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 minFinalExam (List<Student> students) {
return minFinalExam(students,0);
}
44May 2004 NH-Chapter 19
Finding the minimum element: Recursive version
private int minFinalExam (List<Student> students,int first) {
int smallest;
int gradeOfFirst = students.get(first).finalExam();
if (first == students.size()-1) {
smallest = gradeOfFirst; // the base case
else {// the general case:
int minOfRest = minFinalExam(students,first+1);
if (minOfRest < gradeOfFirst)
smallest = minOfRest;
else
smallest = gradeOfFirst;
}
return smallest;
}
45May 2004 NH-Chapter 19
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.
46May 2004 NH-Chapter 19
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
47May 2004 NH-Chapter 19
Selection sort: recursive version
private static <Element> void selectionSort (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
}}
48May 2004 NH-Chapter 19
Selection sort: recursive version
private static <Element> void selectionSort (List<Element> list, int first, Order<Element> order)
{if (first < list.size()) {
int small = smallestOf(list,first,list.size()-1,order);
interchange(list,first,small);selectionSort(list,first+1,order);
}}
49May 2004 NH-Chapter 19
Selection sort: recursive version
public static <Element> void selectionSort (List<Element> list, Order<Element> order) {
selectionSort(list,0,order);}
50May 2004 NH-Chapter 19
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.
51May 2004 NH-Chapter 19
Example of moves with 3 discs
1 32
52May 2004 NH-Chapter 19
Example of moves with 3 discs
1 32
53May 2004 NH-Chapter 19
Example of moves with 3 discs
1 2 3
54May 2004 NH-Chapter 19
Example of moves with 3 discs
1 2 3
55May 2004 NH-Chapter 19
Example of moves with 3 discs
1 32
56May 2004 NH-Chapter 19
Example of moves with 3 discs
1 32
57May 2004 NH-Chapter 19
Example of moves with 3 discs
1 2 3
58May 2004 NH-Chapter 19
Example of moves with 3 discs
1 2 3
59May 2004 NH-Chapter 19
Example of moves with 3 discs
1 32
60May 2004 NH-Chapter 19
Example of moves with 3 discs
1 32
61May 2004 NH-Chapter 19
Example of moves with 3 discs
1 2 3
62May 2004 NH-Chapter 19
Example of moves with 3 discs
1 2 3
63May 2004 NH-Chapter 19
Example of moves with 3 discs
1 32
64May 2004 NH-Chapter 19
Example of moves with 3 discs
1 32
65May 2004 NH-Chapter 19
Example of moves with 3 discs
1 2 3
66May 2004 NH-Chapter 19
PuzzleSolver method moveTower
public void moveTower (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 >= 11 <= from && from <= 31 <= to && to <= 3from != to
67May 2004 NH-Chapter 19
PuzzleSolver method moveTower
It uses a private method to move one disc:
private void moveDisk (int from, int to)
Move a single disk from the specified peg to the specified destination.
require:1 <= from && from <= 3
1 <= to && to <= 3from != to
68May 2004 NH-Chapter 19
PuzzleSolver method moveTower
Base case: a tower with 1 disc.
General case: a tower with n discs.
Reduction case: move a tower with n-1 discs.
69May 2004 NH-Chapter 19
PuzzleSolver method moveTower
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).
70May 2004 NH-Chapter 19
PuzzleSolver : moveTower implementation
public void moveTower (int n, int from, int to) {
if (n == 1) {moveDisk(from,to);
} else {int other = 6-from-to; // not from or tomoveTower(n-1,from,other);moveDisk(from,to);moveTower(n-1,other,to);
}}
71May 2004 NH-Chapter 19
PuzzleSolver: moveDisk
Simply solution:
private void moveDisk (int from, int to) {
System.out.println("Move a disk from peg " + from +" to peg " + to + '.');
}
72May 2004 NH-Chapter 19
PuzzleSolver: moveDisk
Not very satisfactory. PuzzleSolver is a model class;
should be independent of the user interface.
73May 2004 NH-Chapter 19
PuzzleSolver: moveDisk
Better way to implement moveDisk Use the Observer pattern. When output client is notified, pass move to make:
public class MoveA 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.
74May 2004 NH-Chapter 19
PuzzleSolver: moveDisk
private void moveDisk (int from, int to) {setChanged();notifyObservers(new Move(from, to));
}
75May 2004 NH-Chapter 19
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.
76May 2004 NH-Chapter 19
Quicksort
Implement a private method to sort a list segment. sort calls method with entire list:
public static <Element> void quickSort (List<Element> list, Order<Element> order) {quickSort(list,0,list.size()-1,order);
}
//Sort list elements indexed first through last.// require 0 <= first && last < list.size()private static <Element> void quickSort (
List<Element> list, int first, int last,Order<Element> order) {…
}
77May 2004 NH-Chapter 19
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.
78May 2004 NH-Chapter 19
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.
79May 2004 NH-Chapter 19
Quicksort
private static <Element> void quickSort (List<Element> list, int first, int last,Order<Element> order) {
if (first < last) { int position; // pivot index position = partition(list,first,last,order); quickSort(list,first,position-1,order); quickSort(list,position+1,last,order);}
}
80May 2004 NH-Chapter 19
Quicksort: partition
Choose middle element of sublist as pivot element.
1 2346 28
(5) (6) (8)(7)
3
(9)
18 3073 19
(10) (11) (13)(12)
56
(14)
61 1241 45
(0) (1) (3)(2)
55
(4)
move the pivot element into the last position
1 2346 56
(5) (6) (8)(7)
3
(9)
18 3073 19
(10) (11) (13)(12)
28
(14)
61 1241 45
(0) (1) (3)(2)
55
(4)
81May 2004 NH-Chapter 19
Quicksort: partition
L ?L L
(5) (6) (8)(7)
?
(9)
? ?? ?
(10) (11) (13)(12)
28
(14)
s Ls s
(0) (1) (3)(2)
L
(4)
pi i
82May 2004 NH-Chapter 19
Quicksort: partition
i, pi start at 0 Compare i-th entry with pivot
pi i
1 2346 56
(5) (6) (8)(7)
3
(9)
18 3073 19
(10) (11) (13)(12)
28
(14)
61 1241 45
(0) (1) (3)(2)
55
(4)
83May 2004 NH-Chapter 19
Quicksort: partition
Compare i-th entry with pivot.
pi i
1 2346 56
(5) (6) (8)(7)
3
(9)
18 3073 19
(10) (11) (13)(12)
28
(14)
61 1241 45
(0) (1) (3)(2)
55
(4)
84May 2004 NH-Chapter 19
Quicksort: partition
Compare i-th entry with pivot.
pi i
1 2346 56
(5) (6) (8)(7)
3
(9)
18 3073 19
(10) (11) (13)(12)
28
(14)
61 1241 45
(0) (1) (3)(2)
55
(4)
85May 2004 NH-Chapter 19
Quicksort: partition
Compare i-th entry with pivot. It’s less. Swap and increment indices.
pi i
1 2346 56
(5) (6) (8)(7)
3
(9)
18 3073 19
(10) (11) (13)(12)
28
(14)
61 1241 45
(0) (1) (3)(2)
55
(4)
86May 2004 NH-Chapter 19
Quicksort: partition
Compare i-th entry with pivot.
ipi
1 2346 56
(5) (6) (8)(7)
3
(9)
18 3073 19
(10)(11) (13)(12)
28
(14)
12 6141 45
(0) (1) (3)(2)
55
(4)
87May 2004 NH-Chapter 19
Quicksort: partition
Compare i-th entry with pivot. It’s less. Swap and increment indices.
pi i
1 2346 56
(5) (6) (8)(7)
3
(9)
18 3073 19
(10)(11) (13)(12)
28
(14)
12 6141 45
(0) (1) (3)(2)
55
(4)
88May 2004 NH-Chapter 19
Quicksort: partition
Compare i-th entry with pivot.
pi i
41 2346 56
(5) (6) (8)(7)
3
(9)
18 3073 19
(10)(11) (13)(12)
28
(14)
12 611 45
(0) (1) (3)(2)
55
(4)
89May 2004 NH-Chapter 19
Quicksort: partition
Compare i-th entry with pivot.
pi i
41 2346 56
(5) (6) (8)(7)
3
(9)
18 3073 19
(10)(11) (13)(12)
28
(14)
12 611 45
(0) (1) (3)(2)
55
(4)
90May 2004 NH-Chapter 19
Quicksort: partition
Compare i-th entry with pivot. It’s less. Swap and increment.
pi i
41 2346 56
(5) (6) (8)(7)
3
(9)
18 3073 19
(10)(11) (13)(12)
28
(14)
12 611 45
(0) (1) (3)(2)
55
(4)
91May 2004 NH-Chapter 19
Quicksort: partition
Compare i-th entry with pivot. It’s less. Swap and increment indices.
pi i
41 4546 56
(5) (6) (8)(7)
3
(9)
18 3073 19
(10)(11) (13)(12)
28
(14)
12 611 23
(0) (1) (3)(2)
55
(4)
92May 2004 NH-Chapter 19
Quicksort: partition
Compare i-th entry with pivot. It’s less. Swap and increment indices.
pi i
41 4546 56
(5) (6) (8)(7)
61
(9)
18 3073 19
(10)(11) (13)(12)
28
(14)
12 31 23
(0) (1) (3)(2)
55
(4)
93May 2004 NH-Chapter 19
Quicksort: partition
Compare i-th entry with pivot.
pi i
41 4546 56
(5) (6) (8)(7)
61
(9)
55 3073 19
(10)(11) (13)(12)
28
(14)
12 31 23
(0) (1) (3)(2)
18
(4)
94May 2004 NH-Chapter 19
Quicksort: partition
Compare i-th entry with pivot. It’s less Swap and increment indices.
pi i
41 4546 56
(5) (6) (8)(7)
61
(9)
55 3073 19
(10)(11) (13)(12)
28
(14)
12 31 23
(0) (1) (3)(2)
18
(4)
95May 2004 NH-Chapter 19
Quicksort: partition
Compare i-th entry with pivot.
pi i
19 4546 56
(5) (6) (8)(7)
61
(9)
55 3073 41
(10)(11) (13)(12)
28
(14)
12 31 23
(0) (1) (3)(2)
18
(4)
96May 2004 NH-Chapter 19
Quicksort: partition
Loop exited. Swap pivot with pi.
pi i
19 4546 56
(5) (6) (8)(7)
61
(9)
55 3073 41
(10)(11) (13)(12)
28
(14)
12 31 23
(0) (1) (3)(2)
18
(4)
97May 2004 NH-Chapter 19
Quicksort: partition
pi i
19 4528 56
(5) (6) (8)(7)
61
(9)
55 3073 41
(10)(11) (13)(12)
46
(14)
12 31 23
(0) (1) (3)(2)
18
(4)
98May 2004 NH-Chapter 19
partition implementation
private static <Element> int partition (List<Element> list, int first, int last, Order<Element> order) {
int pi; // pivot indexint i; // index of the next to examineElement pivot; // pivot itemint mid = (first+last)/2;pivot = list.get(mid);interchange(list,mid,last); // put pivot item at end.pi = first;i = first; while (i != last) { // list.get(last) is pivot item
if (order.inOrder(list.get(i),pivot)) {interchange(list,pi,i);pi = pi+1;
}i = i+1;
}interchange(list,pi,last); // put pivot item in placereturn pi;
}
99May 2004 NH-Chapter 19
Indirect Recursion
Method m1 invokes m2 which invokes m3 … which invokes mn which invokes m1.
100May 2004 NH-Chapter 19
Indirect Recursion: RemoveSet
Given a balanced string of parentheses as argument, removes the first balanced substring from the front.
Examples removeSet("()") "" removeSet("()()()()") "()()()" removeSet("((()))") "" removeSet("(()()(()()))()(())") "()(())"
101May 2004 NH-Chapter 19
RemoveSet design
Remove first “(“ Invoke reduceClosed for matching “)”
private String reduceClosed (String s)A String equal to specified String with first substring with one more closed parenthesis than open parenthesis removed.
102May 2004 NH-Chapter 19
RemoveSet design
For example, reduceClosed(")") "“
reduceClosed(")()()") "()()“
reduceClosed("(()()))(()) "(())“
reduceClosed("()()(()()))()(())") "()(())"
103May 2004 NH-Chapter 19
RemoveClosed 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.
104May 2004 NH-Chapter 19
RemoveClosed design
Use removeSet to remove balanced substring :
private String reduceClosed (String s) {
if (head(s) == ')')
return tail(s);
else // head(s) == '(‘, remove balanced set
return reduceClosed(removeSet(s));
}
105May 2004 NH-Chapter 19
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.
106May 2004 NH-Chapter 19
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.
107May 2004 NH-Chapter 19
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.
108May 2004 NH-Chapter 19
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.
A
B
E
F
C
D
G
exit
s
ews
w
w
n
s
we
w
n
e
109May 2004 NH-Chapter 19
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.
110May 2004 NH-Chapter 19
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.
111May 2004 NH-Chapter 19
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.
112May 2004 NH-Chapter 19
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 Cgo east to room E:
go east to exit.
113May 2004 NH-Chapter 19
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.
114May 2004 NH-Chapter 19
Implementing backtracking
public List<Room> connections ()
The list of Rooms this Room is connected to.
public boolean isExit ()
This Room is a maze exit.
115May 2004 NH-Chapter 19
Implementing backtracking
public class PathPointA Room and a connection from the Room.
public PathPoint (Room room, int connection)
Create a new PathPoint.
require:0<=connection&&connection <
room.connections().size()
116May 2004 NH-Chapter 19
Implementing backtracking A path is a list of PathPoints modeling a sequence of connected
Rooms. If PathPoint [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)]
A
B
E
F
C
D
G
H
0
201
0
0
0
1
11
0
0
20
117May 2004 NH-Chapter 19
Implementing backtracking write a method that will produce an exit path from a
specified Room:
public List<PathPoint> exitPathFrom (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<PathPoint> extendedPathFrom (Room room, List<PathPoint> 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.
118May 2004 NH-Chapter 19
Implementing backtracking The public method calls the auxiliary method with an
empty initial path:
public List<PathPoint> exitPathFrom (Room room) {
return extendedPathFrom(room, new
DefaultList<PathPoint>());}
119May 2004 NH-Chapter 19
Implementing backtrackingprivate List<PathPoint> extendedPathFrom ( Room room, List<PathPoint> path) { if (room.isExit()) return path; else { boolean found = false; List<PathPoint> solution = null; int i = 0;
while (i < room.connections().size() && !found){ // get a Room to extend the path Room nextRoom = room.connections().get(i);
if (!pathContains(path, nextRoom)) { List<PathPoint> extendedPath = path.copy().add(new PathPoint(room,i));
solution = extendedPathFrom(nextRoom,extendedPath); found = solution != null; }
i = i+1; } return solution; }}
120May 2004 NH-Chapter 19
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.
121May 2004 NH-Chapter 19
Object recursion
Two flavors of solver objects: General problem solver, the trivial problem solver.
We make these children of a common abstract parent:
GeneralSolverTrivialSolver
Solver
«interface»
122May 2004 NH-Chapter 19
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 9s will not turn over to all 0s.
123May 2004 NH-Chapter 19
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 NullDigit as its
associate. (it needs no associate).
NullDigit trivial solver class. The logic in the NullDigit simply ends the recursion.
124May 2004 NH-Chapter 19
Object recursion: DigitCounter
associate
DigitNullDigit
VirtualDigit
«interface»
Note: a Digit and its associate have the same structure.
NullDigitDigit
associate
Digit
associate
Digit
associate
125May 2004 NH-Chapter 19
Object recursion: DigitCounter
public class DigitCounter {
private VirtualDigit lowDigit; // right-most digit
/** * Create a new DigitCounter with the specified * number of digits. * @require : digits >= 1 */public DigitCounter (int digits) {
VirtualDigit d = new NullDigit();for (int i = 1; i <= digits; i = i+1)
d = new Digit(d);lowDigit = d;
}…
126May 2004 NH-Chapter 19
Object recursion: DigitCounter
public void first () {lowDigit.first();
}
public void next () {lowDigit.next();
}
public boolean solved () {return lowDigit.solved();
}
public String toString () {return lowDigit.toString();
}
//definition of VirtualDigit interface // Digit class, NullDigit class.}//end DigitCounter
127May 2004 NH-Chapter 19
Object recursion: DigitCounter
private interface VirtualDigit {
public boolean solved ();
public void first ();public void next ();public String toString
();}
DigitCounter contains a private interface implemented by Digit and NullDigit.
128May 2004 NH-Chapter 19
Object recursion: Digit
Digit classImplements VirtualDigit 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.
129May 2004 NH-Chapter 19
Object recursion: Digitprivate class Digit implements VirtualDigit { private VirtualDigit associate; // left nghb private boolean solved; // valid num private int digit; // my digit
public Digit (VirtualDigit associate) {this.associate = associate;this.digit = 0;this.solved = false;
} public boolean solved () {
return solved; } public void first () {
associate.first();if (associate.solved()) {
digit = 0;solved = true;
} elsesolved = false;
}
public void next () {if (digit < 9) { digit = digit + 1; solved = true;} else { associate.next(); if (associate.solved()) {
digit = 0;solved = true;
} elsesolved = false;
}}
public String toString () { if (solved) return associate.toString() + digit; else return "No solution";}
}//end Digit
130May 2004 NH-Chapter 19
Object recursion: NullDigitprivate class NullDigit implements VirtualDigit {
private boolean solved;public NullDigit () {
this.solved = false;}public boolean solved () {
return solved;}public void first () {
solved = true;}public void next () {
solved = false;}public String toString () {
if (solved)return "";
elsereturn "No solution";
}}
131May 2004 NH-Chapter 19
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.
132May 2004 NH-Chapter 19
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.
133May 2004 NH-Chapter 19
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 nlog2n 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.
134May 2004 NH-Chapter 19
Summary
Indirect recursion, a method is invoked before it returns through a sequence of other method invocations. That is, method m1 invokes m2 which invokes m3 … which invokes mn which invokes m1.
When indirect recursion is used, we generally set a collection of mutually recursive methods.
135May 2004 NH-Chapter 19
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.
136May 2004 NH-Chapter 19
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.