1.3 Recursive Algorithms

78 downloads 149 Views 153KB Size Report
1, and Pfin = 3 (i.e., we wish to move three disks on pole 1 to pole 3). Figure 1.6 contains two ways of viewing the process that we're about to describe. Execution  ...
94

Chapter 1

Algorithms

1.3 Recursive Algorithms The recursive paradigm which we introduced in the Prologue is going to play a major role throughout this book. Many of our algorithms will be direct translations into our algorithmic language of recursive paradigm approaches to problems. In this section we’ll discuss two such algorithms and a variation on one of these, all written in our algorithmic language. The algorithmic expression of the essence of the recursive paradigm reducing to a previous case requires a feature of the language not needed for the algorithms of Section 1.1. We will discuss this feature procedures and their simpler special case functions informally here and in more detail in Section 1.4. While procedures and functions do not have to involve recursion, their use to implement recursion will be their main purpose in this book. Warning. The material in this section and the next is more difficult than that in Section 1.1, particularly if you have not used recursion in a programming language. What is important, however, is not that you grasp all the details now but rather that you get a feel for the idea of recursion and how it is expressed in AL. Our first example illustrates a function. We return to the Euclidean algorithm of Section 1.1, but now we discuss it in recursive terms in contrast to the iterative approach previously taken. EXAMPLE 1

Derive a recursive formulation of the Euclidean algorithm and express it in algorithmic language. Solution The essential formula in our previous derivation of the Euclidean algorithm was Eq. (4), Section 1.1: gcd(m, n) = gcd(n, r1 ),

(1)

where r1 is the remainder when m is divided by n. That is, r1 = m − nm/n. Substituting into Eq. (1), we get gcd(m, n) = gcd(n, m − nm/n).

(2)

Equation (2) expresses the gcd of two integers m and n in terms of two others, n and m − nm/n. In particular, comparing the two second inputs, n > m − nm/n, because the right-hand side is the remainder when m is divided by n and is therefore less than n. So the second argument on the right-hand side of Eq. (2) is less than the corresponding argument on the left-hand side. (How about the two first inputs? [1]) Thus Eq. (2) embodies the essence of the recursive paradigm: reducing to a previous (i.e., smaller) case. Using the recursive paradigm we continue to reduce to the previous case, thereby getting successively smaller but always nonnegative second arguments, until finally we arrive at a case which is obvious from the definition. For the Euclidean algorithm this case is that gcd(m, 0) = m for any m. c Copyright A K Peters 2004. 

For review by instructors only.

1.3

Recursive Algorithms

95

Here’s an example of how Eq. (2) works, for m = 63, n = 27: gcd(63, 27)= gcd(27, 63 − 2763/27) = gcd(27, 9) = gcd(9, 27 − 927/9) = gcd(9, 0) = 9.

[Using Eq. (2)] [Evaluating 63 − 2763/27] [Using Eq. (2) again] [Evaluating 27 − 927/9] [Since gcd(m, 0) = m]

Now, how do we implement the calculation of the gcd via Eq. (2) in our algorithmic language? Algorithm 1.8, Euclid-RecFunc, supplies the answer but needs some explanation. 1. In this algorithm and the discussion of it we distinguish between the greatest common divisor as a mathematical function (gcd) and the function used here to compute it (gcdf). We give them different names because they really are different conceptually: The mathematical function, as defined at the start of Example 4 in Section 1.1, specifies what gcd(m, n) means without giving any method for computing it, whereas gcdf(m, n) specifies a computation without giving any idea what it means. Moreover, as a practical matter, if will avoid confusion to have different names when we give a formal proof in Chapter 2 that the two functions really do have the same values. 2. Focus first on the lines from function to endfunc. Any such sequence of lines are a function definition in our language. In this case the function amounts to an algorithmic representation of Eq. (2) with the input values (m, n) replaced by the variables (i, j), different letters to highlight the different roles, as will be discussed at several points below. To compute gcdf(i, j) you first check to see if j = 0, in which case the gcd is i so gcdf ← i. Otherwise, you call (invoke) the function again, with two new arguments given by the right-hand side of Eq. (2). This second call may make further calls. Somehow all these calls to the same function get unraveled and the correct value is assigned to the original gcdf(i, j). 3. The portion of the algorithm consisting of the line commented “Main algorithm” activates the whole process by calling the function with the given values m and n and assigning the result to answer (so it can be an Output). Figure 1.2 illustrates how Algorithm Euclid-RecFunc works for the same data as above, m = 63 and n = 27. Make sure you understand that the function is called three times (once from the main algorithm and twice more by itself) and that each of these calls is completed (i.e., we get to endfunc) in the reverse order in which the calls were made. Think of it this way: Each time function gcdf is invoked, it is as if a new copy of its definition is made, but one in which the new values for i and j are substituted. The previous copy is interrupted but is still there to be returned to later at the place where it was interrupted. Each such copy is enclosed in a box in Fig. 1.2. c Copyright A K Peters 2004. 

For review by instructors only.

96

Chapter 1

Algorithm 1.8 EuclidRecFunc

Algorithms

Input m, n Output answer Algorithm Euclid-RecFunc function gcdf(i, j) if j = 0 then gcdf ← i else gcdf ← gcdf(j, i − ji/j) endif endfunc answer ← gcdf(m, n)

answer ← gcdf(63, 27) 

[Integers ≥ 0] [ = gcd(m, n)]

[Recursive call]

[Main algorithm]

[Main algorithm call of function]

function gcdf (i ← 63, j ← 27) if 27 = 0 then . . . else gcdf ← gcdf (27, 9)  endif endfunc

[Returns gcdf, still = 9, to function in main call]

function gcdf(i ← 27, j ← 9) if 9 = 0 then . . . else gcdf ← gcdf (9, 0)  endif endfunc

[Returns gcdf, still = 9, to function in previous call]

function gcdf(i ← 9, j ← 0) FIGURE 1.2 Operation of Algorithm EuclidRecFunc for m = 63, n = 27.

if 0 = 0 then gcdf ← 9 else . . .@ endif endfunc

[Assigns 9 to gcdf and returns this value to function in previous call]

Each time endfunc is reached in a box, the value of the variable gcdf at that time is assigned to the expression gcdf (i, j) [or gcdf(m, n)] in the higher level which called that copy. For instance, in the middle box in Figure 1.2, at the end gcdf = 9, and so 9 is assigned to gcdf(27, 9) in the box above it. (Notice that our multisymbol function (and procedure) names are roman, not italic, just as they are roman in traditional mathematics writing, e.g., log x.) c Copyright A K Peters 2004. 

For review by instructors only.

1.3

Recursive Algorithms

97

As this example shows, a function is just a portion of an algorithm which computes a value when called upon by another portion of the algorithm. A procedure is also just a portion of an algorithm that is called upon from some other portion, but whereas a function has one specific task (to compute and return a value), a procedure can do any sort of thing: compute several values, do operations that don’t involve numerical values, etc. In the next example, just to give you the flavor of how a procedure is structured, we give a recursive procedure to compute the greatest common divisor using Eq. (2). In this example, similarly to what we did in Example 1, we use gcdp as the name of the procedure so as not to confuse the procedure with the mathematical function (gcd) that it computes. EXAMPLE 2

Express Euclid’s algorithm as a recursive procedure instead of a recursive function. Solution Since procedures can do any sort of thing, they can return a single value, and thus any function can be rewritten as a procedure. Algorithm 1.9, EuclidRecPro, shows how to do it for Euclid’s algorithm. Note that, unlike in our discussion of functions, the expressions gcdp(m, n; answer) and gcdp(j, i−ji/j; result) in this algorithm do not denote numbers. Rather they represent the process of doing the calculation.

Algorithm 1.9

Input m, n

[Integers ≥ 0]

Euclid-RecPro

Output answer

[ = gcd(m, n)]

Algorithm Euclid-RecPro procedure gcdp(in i, j; out result) if j = 0 then result ← i else gcdp(j, i − ji/j; result ) endif endpro gcdp(m, n; answer)

[Recursive call]

[Main algorithm]

The trace of calls and subcalls is shown in Fig. 1.3. This figure is very similar to Figure 1.2, except that now the value determined by each subcall is returned to the previous call as the value of the variable result instead of under the name gcdp. These returns take place because, in the header line of the procedure definition, the third variable, result, is specified as an out variable so that its value is what is returned (i.e., output) to the previous call of procedure gcdp. Analogously, variables like i, j, which input values to the procedure, are called in (i.e., input) variables. In the main call of the procedure we use answer instead of result because, just as it helps to distinguish the procedure variables i, j from the input values m, n, so also it helps to distinguish the result of each call of the procedure from the final answer. c Copyright A K Peters 2004. 

For review by instructors only.

98

Chapter 1

Algorithms

For instance, look at the middle box of Fig. 1.3. It is the expansion of the internal procedure call gcdp(27, 9; result) from the top box. In the expansion, gcdp(9, 0; result) is called, which results (via the bottom box) in the variable result being created in the middle box with the value 9. (This act of creation is represented by the the arrow coming into the middle box from below.) Since there is no instruction inside the middle box that changes result, it is still 9 when the box’s work is done. Now, the call that created the middle box was made in the top box, and it says to return the computed value to the top box, again with the name result. This is represented by the arrow going into the top box from below. The rules for in, out, and a third possibility, inout, will all be detailed in Section 1.4.

FIGURE 1.3 Operation of Algorithm EuclidRecPro for m = 63, n = 27.

gcdp(63, 27; answer) [Main algorithm call of function] 6 procedure gcdp(i ← 63, j ← 27; answer) COC [Returns value, if 27 = 0 then . . . C of result, else gcdp(27, 9; result) still = 9, CO endif to variable answer C endpro in main call] C C procedure gcdp(i ← 27, j ← 9; result) 6 [Returns variable if 9 = 0 then . . . result, else gcdp(9, 0; result) still = 9, endif CO to previous C endpro call] C C procedure gcdp(i ← 9, j ← 0; result) 1   [Assigns 9 to if 0 = 0 then result ← 9 result and else . . . returns this endif variable with its value endpro to previous call]

Example 2 shows that functions are not necessary in our algorithmic language. We introduce them because they make a common case a little simpler, the case when the result is a single number; no additional variable name needs to be assigned to return the value. (See also [6, Section 1.4] for another advantage of functions.) Indeed, the functions and procedures of our language are both functions in the broadest mathematical sense; they both take input and produce something. When a function or a procedure calls itself, it is said to be recursive and the entire process is called recursion. c Copyright A K Peters 2004. 

For review by instructors only.

1.3

Recursive Algorithms

99

In the next example, we use a procedure when a function could not be used, namely to move pieces in a game. This example will recur many times in later chapters, in a variety of forms. EXAMPLE 3

The Towers of Hanoi ´ The Towers of Hanoi puzzle (TOH) was first posed by a French professor, Edouard Lucas, in 1883. Although commonly sold today as a children’s toy, it is often discussed in discrete mathematics or computer science books because it provides a simple example of recursion. In addition, its analysis is straightforward and it has many variations of varying difficulty. The object of the Towers of Hanoi problem (see Fig. 1.4) is to specify the steps required to move the disks (or, as we will sometimes call them, rings) from pole r (r = 1, 2, or 3) to pole s (s = 1, 2, or 3; s = r), observing the following rules: i) Only one disk at a time may be moved. ii) At no time may a larger disk be on top of a smaller one. The most common form of the problem has r = 1 and s = 3 (Fig. 1.4). 1

FIGURE 1.4 The Towers of Hanoi problem. The problem is shown with the initial pole r = 1 and the final pole s = 3.

n disks

2

3

1 2 3

n−1 n

Solution Our algorithm to solve this problem exemplifies the recursive paradigm. We imagine that we know a solution for n − 1 disks (“reduce to a previous case”), and then we use this solution to solve the problem for n disks. Thus to move n disks from pole 1 to pole 3, we would: 1. Move n − 1 disks (the imagined known solution) from pole 1 to pole 2. However we do this, the nth disk on pole 1 will never be in our way because any valid sequence of moves with only n − 1 disks will still be valid if there is an nth (larger) disk always sitting at the bottom of pole 1 (why?). 2. Move disk n from pole 1 to pole 3. 3. Use the same method as in Step 1 to move the n − 1 disks now on pole 2 to pole 3. Figure 1.5 illustrates these three steps. Even so, this solution may seem a little like sleight of hand. It’s one thing to imagine we can do the previous case. It’s another to do it! But now we’ll show that it works. c Copyright A K Peters 2004. 

For review by instructors only.

100

Chapter 1

Algorithms

Starting with n disks: n−1

n−1

Step 1:

Pole 1

Pole 2

Pole 3

Pole 1

n−1

Pole 2

Pole 3

n−1

Step 2:

Pole 1

Pole 2

Pole 3

Pole 1

Pole 2

n−1

Pole 3

n−1

Step 3:

FIGURE 1.5 The Towers of Hanoi a recursive solution.

Pole 1

Pole 2

Pole 3

Pole 1

Pole 2

Pole 3

Let’s suppose that, being lazy, we don’t want to move the disks ourselves but have contrived a robot arm to do this for us. All we have to do is tell the robot what to do. We assume that our robot understands instructions of the form robot(r → s),

(3)

which means to move the top disk on pole r to pole s. Using this instruction we can express the solution embodied in Steps 1–3 as Algorithm 1.10 Hanoi. Algorithm Hanoi looks short and sweet, but you may not find it all that easy to understand. There is a procedure at the beginning named H and its arguments are n, r, and s. Also like function gcdf in Euclid-RecFunc and procedure gcdp in Euclid-RecPro, procedure H is called from within itself. Once again, the main algorithm starts the execution. It consists of only one line, H(num, Pinit, Pfin), which invokes the procedure H. In effect, the line H(num, Pinit, Pfin) tells the procedure to solve the Towers of Hanoi problem with n = num disks, which start on pole r = Pinit and are to be moved to pole s = Pfin. c Copyright A K Peters 2004. 

For review by instructors only.

1.3

Algorithm 1.10 Hanoi

Recursive Algorithms

101

Input num [Number of disks] Pinit [Initial pole; 1 ≤ Pinit ≤ 3] Pfin [Final pole; 1 ≤ Pfin ≤ 3, Pinit = Pfin] Output The sequence of commands to the robot to move the disks from pole Pinit to pole Pfin Algorithm Hanoi procedure H(in n, r, s) [Move n disks from pole r to pole s] if n = 1 then robot(r → s) else H(n−1, r, 6−r−s) robot(r → s) H(n−1, 6−r−s, s) endif endpro H(num, Pinit, Pfin) [Main algorithm]

One other remark before we give an example of Hanoi: The reason for the use of 6 − r − s is that, if r and s are any two of the three poles 1, 2, and 3, then 6 − r − s is the third pole (e.g., if r = 1 and s = 3, then 6 − r − s = 2). Without this algebraic trick, Hanoi would need all three pole numbers as inputs [8]. To show how Hanoi works, let’s consider what happens when num = 3, Pinit = 1, and Pfin = 3 (i.e., we wish to move three disks on pole 1 to pole 3). Figure 1.6 contains two ways of viewing the process that we’re about to describe. Execution of the algorithm begins in the main algorithm with the call H(3, 1, 3) to the procedure, in which 3, 1, and 3, are assigned, respectively, to the variables n, r, and s in the procedure definition. Since n = 3 = 1, we go initially to the else portion of the if-structure. With the current values of n, r, s this portion becomes H(2, 1, 2) robot(1 → 3) H(2, 2, 3)

(4)

The first invocation of H within H(3, 1, 3), namely, H(2, 1, 2), causes us to interrupt the normal sequential execution of steps of the algorithm and go back to the beginning of a new copy of the procedure (indicated by indenting and by a new level of boxing in Fig. 1.6b), now with n = 2, r = 1, and s = 2. Again, within this copy n = 1, so we go to the else portion, which now becomes H(1, 1, 3) robot(1 → 2) H(1, 3, 2)

c Copyright A K Peters 2004. 

(5)

For review by instructors only.

102

Chapter 1

Algorithms

a) Algorithm Hanoi for num = 3, Pinit = 1, and Pfin = 3. H(3, 1, 3) 1→3

H(2, 1, 2) H(1, 1, 3)

1→2

H(2, 2, 3)

H(1, 3, 2)

H(1, 2, 1)

3→2

2→1

1→3

2→3

H(1, 1, 3) 1→3

b) Trace of H(3, 1, 3). Each call of H(n, r, s) takes the trace one column to the right and each endpro takes it one column to the left. H(3, 1, 3)

[Initial call] H(2, 1, 2) H(1, 1, 3) robot(1 → 3) endpro robot(1 → 2) H(1, 3, 2) robot(3 → 2) endpro endpro robot(1 → 3) H(2, 2, 3) H(1, 2, 1) robot(2 → 1) endpro robot(2 → 3) H(1, 1, 3) robot(1 → 3) endpro

FIGURE 1.6 Operation of Algorithm Hanoi.

endpro endpro

Once more the invocation of the procedure, H(1, 1, 3), causes us to interrupt the sequence and return to the beginning of a new copy, with n = 1, r = 1, and s = 3. Since now n = 1, the then portion applies: H(1, 1, 3):

robot(1 → 3).

We then reach endpro for H(1, 1, 3), which means that we have completed H(1, 1, 3), and so we return to the interrupted execution of (5). The second line of (5) adds robot(1 → 2) to our list of instructions to the robot. Then we execute H(1, 3, 2), whose total activity, since n = 1 again, consists of a single instruction, robot(3 → 2). This then completes the execution of H(2, 1, 2), the result of which is c Copyright A K Peters 2004. 

For review by instructors only.

1.3

Recursive Algorithms

103

robot(1 → 3) robot(1 → 2) robot(3 → 2) You should verify that this sequence of moves solves the problem when n = 2, r = 1, and s = 2. But, for our problem, we must now return to the interrupted execution of (4). Having completed H(2, 1, 2) we add robot(1 → 3) to a list of commands to the robot and then execute the call H(2, 2, 3). Since n = 1, we proceed as above and compute H(1, 2, 1) robot(2 → 3) H(1, 1, 3)

(6)

Since n = 1 in both invocations of H in (6), we get for H(2, 2, 3): robot(2 → 1) robot(2 → 3) robot(1 → 3) Finally, putting all these steps together, we get for H(3, 1, 3):  [Small disk to 3]  robot(1 → 3) [Middle disk to 2] H(2, 1, 2) robot(1 → 2)  [Small disk to 2] robot(3 → 2) robot(1 → 3) [Large disk to 3]  [Small disk to 1] robot(2 → 1)  [Middle disk to 3] H(2, 2, 3) robot(2 → 3)  [Small disk to 3] robot(1 → 3)

(7)

You should verify that the list of instructions in (7) really is a solution. You might take a quarter, a nickel, and a dime and use them as the disks on imaginary poles. Figure 1.6a graphically illustrates the steps in solving this problem. Figure 1.6b is a trace of this algorithm, in which the “depth” of successive calls of H(n, r, s) is illustrated by the indentations from left to right across the page and by the boxes surrounding the successive calls of H. Might self-invocation (recursion) get out of hand? That is, might you dig a hole so deep that is, invoke the computation so many times without ever completing an execution of it that you could never climb out with a solution to the original problem? A necessary condition for avoiding this situation is that there be at least one value of a defining variable for the recursive procedure or function which does not invoke another call. These are j = 0 in Euclid-RecFunc and EuclidRecPro, and n = 1 in Hanoi. But this alone is not enough to ensure that you will be able to “climb out of the hole”, that is, get back to the initial case at the top level of the recursion. For both recursive versions of Euclid it’s rather easy to see that you do, indeed, climb out, but it’s not nearly so easy to see for Hanoi. In c Copyright A K Peters 2004. 

For review by instructors only.

104

Chapter 1

Algorithms

Section 2.4 we’ll prove all these algorithms correct, and thus that they terminate. The proofs will use mathematical induction, which is the usual proof method for recursive algorithms. The use of the recursive paradigm need not lead to a recursive algorithm. Sometimes the implementation of a recursive idea as an iterative algorithm allows a more felicitous presentation of the algorithm than would a recursive algorithm. Additionally, an iterative implementation will often lead to a more efficient algorithm (see Section 1.5 for what we mean by “efficient”) than the recursive implementation. Algorithm Euclid (as given in Section 1.1) is an example of this, and we’ll exhibit another in Section 1.5. When a straightforward iterative approach is available, you will usually understand it more easily. Often, however, there is no straightforward iterative approach. This is the case with the Towers of Hanoi problem, which is naturally recursive. Although it can be implemented iteratively (see [28, Section 2.5]), the iterative form is trickier and not so easy to understand. Understanding Examples 1–3 is worth some effort. Try working through some cases. For the Towers of Hanoi, you’ll find that solving the problem when n > 6 is very tedious. But solving the problem for n ≤ 6 should be fun. Success will surely give you some insight into the Towers of Hanoi problem in particular and recursion more generally.

Problems: Section 1.3 Note: There are more problems about recursive algorithms at the end of Section 1.4. 1. 1 We argued that Eq. (2) fits the recursive paradigm because the second argument is reduced at each stage. But how about the first argument? Isn’t it also reduced at each stage? Explain. 2. 2 a) In Example 4, Section 1.1, we derived another relation besides Eq. (2) which equates the gcd of two different pairs of arguments: gcd(m, n) = gcd(m − n, n) when m ≥ n. Write a recursive algorithm analogous to Euclid-RecFunc which uses this equation. Show how your algorithm works when m = 63 and n = 27 by displaying the calculation and by drawing a figure analogous to Fig. 1.2. Note: The algorithm will have to switch the variables when m − n < n. b) Repeat a) for Euclid-RecPro. 3. 2 Rewrite Algorithm 1.7 from [12, Section 1.1] in the form of

a) a recursive function, b) a recursive procedure. 4. 3 The least common multiple (lcm) of two nonzero integers m and n is the smallest positive integer which is a multiple of both m and n. For example, lcm(15, 24) = 120. Although there is no simple relationship like Eq. (2) or that in [2] for the lcm, we can derive efficient methods for computing the lcm using its relationship to the gcd. a) Show that gcd(m, n) lcm(m, n) = mn if m, n > 0. (This is the conjecture you should have made if you attempted [3b, Supplement, Chapter 0].) Hint : Express both m and n as the products of their prime factors. Thus, 15 = 3 × 5 and 24 = 23 × 3. Then you can find both the gcd and the lcm by comparing the exponents of the same prime in the two factorizations and choosing the maximum for the lcm and the minimum for the gcd. Thus lcm(15, 24) = 23 × 3 × 5 = 120 and gcd(15, 24) = 3. b) Use the relationship in a) and the recursive function in Algorithm Euclid-RecFunc to

c Copyright A K Peters 2004. 

For review by instructors only.

1.3

Algorithmic Language: Procedures and Functions

105

write an algorithm to compute the lcm of two nonnegative integers m and n. c) Repeat b) but this time using Euclid-RecPro and writing a recursive procedure.

problem of finding a solution with the minimum number of moves is quite difficult. But try doing it for a) n = 3 b) n = 4

5. 2 Use the relationship in [4a] to write an algorithm to compute the lcm, using Algorithm Euclid in Section 1.1 for the computation of the gcd.

10. 2 You are given n different rings as in TOH, but now there are only two poles. Your goal is to move them from the smallest-down-to-largest configuration on the start pole to a largest-down-to-smallest on the other pole. (Clearly, larger rings may now go on smaller ones.) There is an obvious way to do this: Just transfer the rings one at a time. a) Describe this solution recursively in ordinary English. That is, use a phrase like “suppose that we already knew how to do this for n − 1 rings”. b) Write your solution as an algorithm using a recursive procedure. You may use the command robot(r→s).

6. 3 a) Write a recursive procedure whose input is two integers as in Euclid and whose output is both the gcd and the lcm of these two integers. b) If only recursive functions (but not recursive procedures) were available to you, could you write an algorithm which calculated both the gcd and lcm but used only a single recursive function? If not, why not? If so, how? 7. 1 List the set of moves in the Towers of Hanoi problem for a) n = 2 b) n = 4. 8. 1 Avoid the use of 6 − r − s by rewriting the procedure H in Hanoi as H(n, Pi, Pf , Pt), where Pi is the initial pole, Pf is the final pole, and Pt is the third pole. 9. 2 In the Towers of Hanoi problem suppose that there are four pegs instead of three. Then the

11. 2 There are actually two different recursive representations of the solution of [10]. In one version, you move a single ring and then do the recursive step; in the other, you move a single ring after the recursive step. Whichever you did in [10], now do the other. (The former solution is an instance of tail-end recursion; the latter, an instance of front-end recursion.)

1.4 Algorithmic Language: Procedures and Functions In Section 1.3 we introduced procedures and functions informally and used them in algorithms. In this section we’ll give you the details of their syntax and semantics (i.e., the meaning of the syntax). We pay special attention to the rules for passing values to and from calls of procedures and functions. Some things that appear to be picky aspects of these rules are crucial to why recursive algorithms work, and why they can be proved correct by induction (as we’ll discuss in Ch. 2).

Procedures Both recursive algorithms with procedures in Section 1.3 had the form Procedure definition Main algorithm with call to procedure

c Copyright A K Peters 2004. 

For review by instructors only.

Suggest Documents