Chapter 19 : Recursion

Preview:

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 Presentation

Citation preview

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.

Recommended