1
Introduction to Programming – Lecture 16
1
Chair of Software Engineering
Introduction to Programming
Bertrand Meyer
Last revised 9 December 2004
Introduction to Programming – Lecture 16
2
Chair of Software Engineering
Lecture 16:Introduction to recursion
Introduction to Programming – Lecture 16
3
Chair of Software Engineering
The story of the universe*
Dans le grand temple de Bénarès, sous le dôme qui marque le centre du monde, repose un socle de cuivre équipé de troisaiguilles verticales en diamant de 50 cm de haut.
A la création, Dieu enfila 64 plateaux en or pur sur une des aiguilles, le plus grand en bas et les autres de plus en plus petits. C'est la tour de Brahmâ.
Les moines doivent continûment déplacer les disques de manièreque ceux-ci se retrouvent dans la même configuration sur uneautre aiguille.
La règle de Brahmâ est simple: un seul disque à la fois et jamaisun grand plateau sur un plus petit.
Arrivé à ce résultat, le monde tombera en poussière et disparaîtra.
*According to Édouard Lucas, Récréations mathématiques, Paris, 1883
Introduction to Programming – Lecture 16
4
Chair of Software Engineering
The story of the universe*
In the great temple of Benares, under the dome that marks the center of the world, three diamond needles, a foot and a half high, stand on a copper base.
God on creation strung 64 plates of pure gold on one of the needles, the largest plate at the bottom and the others ever smaller on top of each other. That is the tower of Brahmâ.
The monks must continuously move the plates until they will be set in the same configuration on another needle.
The rule of Brahmâ is simple: only one plate at a time, and never a larger plate on a smaller one.
When they reach that goal, the world will crumble into dust and disappear.
*According to Édouard Lucas, Récréations mathématiques, Paris, 1883
Introduction to Programming – Lecture 16
5
Chair of Software Engineering
The tower of Hanoi
Introduction to Programming – Lecture 16
6
Chair of Software Engineering
The tower of Hanoi
2
Introduction to Programming – Lecture 16
7
Chair of Software Engineering
How many moves?Assume n disks (n ≥ 0); three needles called source, target and other.
The largest disk can only move from source to target if it’s empty; thus all the other disks must be on other.
So the minimal number of moves for any solution is:
Hn = Hn−1 + 1 + Hn−1
= 2 ∗ Hn−1 + 1
Move n−1 from source to other
Move n−1 from other to target
Move largest from source to target
Since Hn = 1, this implies:
Hn = 2n − 1
Introduction to Programming – Lecture 16
8
Chair of Software Engineering
This also gives us an algorithm
hanoi (n: INTEGER; source, target, other: CHARACTER) is-- Transfer n disks from source to target,-- using other as intermediate storage.
requirenon_negative: n >= 0different1: source /= targetdifferent2: target /= otherdifferent3: source /= other
doif n > 0 then
hanoi (n−1, source, other, target)move (source, target)hanoi (n−1, other, target, source)
endend
Introduction to Programming – Lecture 16
9
Chair of Software Engineering
A possible implementation for move
move (source, target: CHARACTER) is-- Prescribe move from source to target.
doio.put_character (source)io.put_string (“ to “)io.put_character (target)io.put_new_line
end
Introduction to Programming – Lecture 16
10
Chair of Software Engineering
An example
Executing the call
hanoi (4, ‘A’, ‘B’, ‘C’)
will print out the sequence of fifteen (24 -1) instructions
A to C B to C B to AA to B A to C C to BC to B A to B A to CA to C C to B A to BB to A C to A C to B
Introduction to Programming – Lecture 16
11
Chair of Software Engineering Introduction to Programming – Lecture 16
12
Chair of Software Engineering
The general notion of recursion
A definition for a concept is recursiveif it involves an instance of the concept itself.
Notes:
• The definition may use more than one “instance of the concept itself”.
• Recursion is the use of a recursive definition
3
Introduction to Programming – Lecture 16
13
Chair of Software Engineering
Examples
Recursive routine
Recursive grammar
Recursively defined programming concept
Recursive data structure
Introduction to Programming – Lecture 16
14
Chair of Software Engineering
Recursive routine
Direct recursion: body includes a call to the routine itself
Example: routine move for the preceding solution of the Towers of Hanoi problem
Introduction to Programming – Lecture 16
15
Chair of Software Engineering
Recursion can be indirect
Routine r includes a call to routine s
s includes a call to r
More generally: r1 calls r2 calls ... calls rn calls r1.
Introduction to Programming – Lecture 16
16
Chair of Software Engineering
Recursive grammar
Instruction = Assignment | Conditional | Compound | ...
Conditional = if Expression then Instructionelse Instruction end
Introduction to Programming – Lecture 16
17
Chair of Software Engineering
Defining lexicographical order
Problem: define the notion that word w1 is “before”word w2, according to alphabetical order.
Conventions:
A word is a sequence of zero or more letters.A letter is one of:A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
For any two letters it is known which one is “smaller”than the other; the order is that of the preceding list.
Introduction to Programming – Lecture 16
18
Chair of Software Engineering
Examples
ABC before DEF
AB before DEF
empty word before ABC
A before AB
A before ABC
4
Introduction to Programming – Lecture 16
19
Chair of Software Engineering
A recursive definition
The word w1 is “before” the word w2 if and only if one of the following conditions holds:
w1 is empty and w2 is not empty
Neither w1 nor w2 is empty, and the first letter of w1 is smaller than the first letter of w2 .
Neither w1 nor w2 is empty, their first letters are the same, and the word obtained by removing the first letter of w1 is (recursively) before the word obtained by removing the first letter of w2.
Introduction to Programming – Lecture 16
20
Chair of Software Engineering
Recursive data structure
Let G be some type. A binary tree over G is either:EmptyA node, consisting of three elements:
A value of type GA binary tree over G, called the left child of the nodeA binary tree over G, called the right child of the node
Introduction to Programming – Lecture 16
21
Chair of Software Engineering
Binary tree class skeleton
class BINARY_TREE [G] feature
item: G
left: BINARY_TREE [G]right: BINARY_TREE [G]
... Insertion and deletion features ...
end
Introduction to Programming – Lecture 16
22
Chair of Software Engineering
A recursive routine on a recursive data structure
count: INTEGER is-- Number of nodes
doResult := 1if left /= Void then
Result := Result + left.countendif right /= Void then
Result := Result + right.countend
end
Introduction to Programming – Lecture 16
23
Chair of Software Engineering
Children and parents
Theorem: Single ParentEvery node in a binary tree has exactly one parent, except for the root which has no parent.
Introduction to Programming – Lecture 16
24
Chair of Software Engineering
More binary tree properties and terminology
A node of a binary tree may have:
both a left child and a right childonly a left childonly a right childno child
5
Introduction to Programming – Lecture 16
25
Chair of Software Engineering
More properties and terminology
Upward path:Sequence of zero or more nodes, where any node in the sequence is the parent of the previous one if any.
Theorem: Root PathFrom any node of a binary tree, there is a single upward path tothe root.
Theorem: Downward PathFor any node of a binary tree, there is a single downward path connecting the root to the node through successive applications of left and right links.
Introduction to Programming – Lecture 16
26
Chair of Software Engineering
Height of a binary tree
Height:Maximum numbers of nodes on a downward path from the root to a leaf.
height: INTEGER is-- Maximum nuber of nodes on a downward path.
locallh, rh: INTEGER
doif left /= Void then lh := left.height endif right /= Void then rh := right.height endResult := 1 + lh.max (rh)
end
Introduction to Programming – Lecture 16
27
Chair of Software Engineering
Binary tree operations
add_left (x: G) is-- Create left child of value x.
requireno_left_child_behind: left = Void
docreate left.make (x)
end
add_right (x: G) ...Same model...
make (x: G) is-- Initialize with item value x.
doitem := x
ensureset: item = x
end
Introduction to Programming – Lecture 16
28
Chair of Software Engineering
Binary tree traversals
print_all is-- Print all node values.
doif left /= Void then left.print_all endprint (item)if right /= Void then right.print_all end
end
Introduction to Programming – Lecture 16
29
Chair of Software Engineering
Binary tree traversals
Inorder:traverse left subtree, visit root , traverse right subtree.Preorder:visit root , traverse left, traverse right.Postorder:traverse left, traverse right, visit root .
Introduction to Programming – Lecture 16
30
Chair of Software Engineering
Binary search tree
A binary tree has a left subtreeand a right subtree
A binary tree over a sorted set G is a binary search tree if for every node n:
For every node x of the left subtree of n,x.item ≤ n.item
For every node x of the right subtree of n,x.item ≥ n.item
6
Introduction to Programming – Lecture 16
31
Chair of Software Engineering
Printing elements in order
class BINARY_SEARCH_TREE [G ...] featureitem: Gleft, right: BINARY_SEARCH_TREE [G]right: BINARY_SEARCH_TREE [G]
sort is-- Print element values in order
doif left /= Void then left.sort end
print (item)
if right /= Void then right.sort endend
end
Introduction to Programming – Lecture 16
32
Chair of Software Engineering
Searching in a binary search tree
class BINARY_SEARCH_TREE [G ...] featureitem: Gleft, right: BINARY_SEARCH_TREE [G]right: BINARY_SEARCH_TREE [G]
has (x: G): BOOLEAN is-- Does x appear in any node?
requireargument_exists: x /= Void
doif x = item then
Result := Trueelseif x < item and left /= Void then
Result := left.has (x)elseif x > item and right /= Void then
Result := right.has (x)end
endend
Introduction to Programming – Lecture 16
33
Chair of Software Engineering
Insertion into a binary search tree
Do it as an exercise!
Introduction to Programming – Lecture 16
34
Chair of Software Engineering
Why binary search trees?
Linear structures: insertion, search and deletion are O (n)
Binary search tree: average behavior for insertion, deletion and search is O (log (n))
But: worst-time behavior is O (n)!
Note measures of complexity: best case, average, worst case.
Introduction to Programming – Lecture 16
35
Chair of Software Engineering
Well-formed recursive definition
A useful recursive definition should ensure that:
R1 There is at least one non-recursive branch.R2 Every recursive branch occurs in a context that
differs from the original.R3 For every recursive branch, the change of context
(R2) brings it closer to at least one of the non-recursive cases (R1).
Introduction to Programming – Lecture 16
36
Chair of Software Engineering
Recursion variant
The rountine‘s precondition implies that the variant is non-negative.If an execution of the routine starts with a value vfor the variant, the value v‘ of the variant for any recursive call satisfies 0 ≤ v‘ < v.
Every recursive routine should use a recursion variant, an integer quantity associated with any call, such that:
7
Introduction to Programming – Lecture 16
37
Chair of Software Engineering
Hanoi: what is the variant?
hanoi (n: INTEGER; source, target, other: CHARACTER) is-- Transfer n disks from source to target,-- using other as intermediate storage.
require…
doif n > 0 then
hanoi (n−1, source, other, target)move (source, target)hanoi (n−1, other, target, source)
endend
Introduction to Programming – Lecture 16
38
Chair of Software Engineering
Printing: what is the variant?
class BINARY_SEARCH_TREE [G ...] featureitem: Gleft, right: BINARY_SEARCH_TREE [G]right: BINARY_SEARCH_TREE [G]
sort is-- Print element values in order
doif left /= Void then left.sort end
print (item)
if right /= Void then right.sort endend
end
Introduction to Programming – Lecture 16
39
Chair of Software Engineering
Contracts for recursive routines
hanoi (n: INTEGER; source, target, other: CHARACTER) is-- Transfer n disks from source to target,-- using other as intermediate storage.-- variant: n-- invariant: disks on each needle are piled in-- decreasing size
require…
doif n > 0 then
hanoi (n−1, source, other, target)move (source, target)hanoi (n−1, other, target, source)
endensure
…end
Introduction to Programming – Lecture 16
40
Chair of Software Engineering
McCarthy’s 91 function
M (n) =
n − 10 if n > 100
M (M (n + 11)) if n ≤ 100
Introduction to Programming – Lecture 16
41
Chair of Software Engineering
Another function
bizarre (n) =
1 if n = 1
bizarre (n / 2) if n is even
bizarre ((3 ∗ n + 1) / 2) if n > 1 and n is odd
Introduction to Programming – Lecture 16
42
Chair of Software Engineering
Fibonacci numbers
fib (1) = 0fib (2) = 1
fib (n) = fib (n−2) + fib (n−1) for n > 2
8
Introduction to Programming – Lecture 16
43
Chair of Software Engineering
Factorial function
0! = 1
n! = n * (n − 1)! for n > 0
Recursive definition is interesting for demonstration purposes only; practical implementation will use loop (or table)
Introduction to Programming – Lecture 16
44
Chair of Software Engineering
Our original example of a loophighest_name: STRING is
-- Alphabetically greatest station name of line fdo
fromf.start ; Result := ""
untilf.after
loopResult := greater (Result, f.item.name)f.forth
endend
item
count1forthstart
afterbefore
Introduction to Programming – Lecture 16
45
Chair of Software Engineering
A recursive equivalent
highest_name: STRING is-- Alphabetically greatest station name-- of line f
requirenot f.is_empty
dof.startResult := f.highest_from_cursor
end
Introduction to Programming – Lecture 16
46
Chair of Software Engineering
Auxiliary function for recursionhighest_from_cursor: STRING is
-- Alphabetically greatest name of stations of-- line f starting at current cursor position
requiref /= Void; not f.off
doResult := f.item.namef.forthif not f.after then
Result := greater (Result, highest_from_cursor)end
end item
count1forth
after
Introduction to Programming – Lecture 16
47
Chair of Software Engineering
Loop version using arguments
maximum (a: ARRAY [STRING]): STRING is-- Alphabetically greatest item in a
requirea.count >= 1
locali: INTEGER
dofrom
i := a.lower + 1; Result := a.item (a.lower)invariant
i > a.lower ; i <= a.upper + 1-- Result is the maximum element of a [a.lower .. i−1]
untili > a.upper
loopif a.item (i) > Result then Result := a.item (i) endi := i + 1
endend
Introduction to Programming – Lecture 16
48
Chair of Software Engineering
Recursive version
maxrec (a: ARRAY [STRING]): STRING is-- Alphabetically greatest item in a
requirea.count >= 1
doResult := max_sub_array (a, a.lower)
end
max_sub_array (a: ARRAY [STRING]; i: INTEGER): STRING is-- Alphabetically greatest item in a starting from index i
requirei >= a.lower ; i <= a.upper
doResult := a.item (i)if i < a.upper then
Result := greater (Result, max_sub_array (a, i + 1))end
end
9
Introduction to Programming – Lecture 16
49
Chair of Software Engineering
Recursion elimination
Recursive calls cause (in a default implementation without optimization) a run-time penalty: need to maintain stack of preserved values
Various optimizations are possible
Sometimes a recursion can be replaced by a loop; this is known as recursion elimination
“Tail recursion” (last instruction of routine is recursive call) can usually be eliminated
Introduction to Programming – Lecture 16
50
Chair of Software Engineering
Recursion elimination
r (x) isdo
... Some instructions ...
r (x’)
... More instructions ...end
After call, need to revert to previous values of arguments and other context information
May need x!
x := x’goto start_of_r
-- e.g. r (x–1)
Introduction to Programming – Lecture 16
51
Chair of Software Engineering
Using a stack
Queries:Is the stack empty? is_emptyTop element, if any: item
Commands:Push an element on top: putPop top element, if any: remove
“Top” position
Introduction to Programming – Lecture 16
52
Chair of Software Engineering
Recursion as a problem-solving technique
Applicable if you have a way to construct a solution to the problem, for a certain input set, from solutions for one or more smallerinput sets.
Introduction to Programming – Lecture 16
53
Chair of Software Engineering
End of lecture 16