Graphic by Keith Ohlfs |
Forms of Iteration |
[CS111 Home Page] [Syllabus] [Lecture Notes] [Assignments] [Labs] [Programs] [Documentation] [Software Installation] [FAQ] [CS Dept.] [CWIS]
while
loops, and for
loops.
We will use the task of reversing a list as an example to
illustrate how different forms of iteration are related to
each other and to recursion. A recursive implementation of
reverse
is given below.
The recursive methodpublic static IntList reverse (IntList L) { if (isEmpty(L)) { return empty(); } else { return postpend(reverse(tail(L)), head(L)); } } public static IntList postpend (IntList L, int n) { if (isEmpty(L)) { return prepend(n, empty()); } else { return prepend(head(L), postpend(tail(L), n)); } }
reverse
above not only calls
itself, but it also must do something to the result it gets
from calling itself. The answer from the recursive call to
reverse
is used as a parameter to postpend
.
We call postpend
a pending operation in the
recursion. Iteration, on the other hand, does not have pending
operations. Each pass through the iteration is a complete set
of calculations. To achieve this, extra variables are usually
necessary to keep track of the state of things during the
iteration and to hold the partial state of the answer we
are putting together.
To solve the problem of reversing a list iteratively, we need
a different reverse strategy. An alternative technique for
reversing a list is to follow the strategy one would use in
reversing a pile of cards: form a new pile by iteratively
removing the top card of the original pile and putting it on
the new pile. When there are no more cards in the original pile,
the new pile contains the cards in reverse order from the original pile.
To implement this iterative strategy, we need to keep track
of the list we are reversing, and the result we
are building. Given a list L1=[1,2,3,4]
,
the iteration table for reverse(L1)
would be
list | result |
---|---|
[1,2,3,4] |
[] |
[2,3,4] |
[1] |
[3,4] |
[2,1] |
[4] |
[3,2,1] |
[] |
[4,3,2,1] |
For the tail-recursive implementation of reverse
,
we see that we need an auxiliary method (which we call
reverseTail
) because reverse
has
one parameter list but the iteration table has two
state variables (list and result). The implementation
with comments is given below.
// main method public static IntList reverse(IntList list) { // returns the result of the auxiliary method // the parameters of the auxiliary method are the // values in the first column of the iteration table return reverseTail(list, empty()); } // tail-recursive auxiliary method // notice there is one parameter for each state variable // (column) of the iteration table public static IntList reverseTail(IntList list, IntList result) { if (isEmpty(list)) { // base case: when to stop return result; // this is the state variable which holds the answer } else { // general case: do a recursive call // notice there are no pending operations! // the next value of list is tail(list) // the next value of result is prepend(head(list), result) return reverseTail(tail(list), prepend(head(list), result)); } }
while
loopswhile
loop is a form of iteration
which does not involve recursion. Instead, the syntax
creates a loop which is a body of code which is
repeated over and over again while some condition is true.
The loop is terminated when the specified condition is false.
The formal syntax for a Java while
loop is
The relationship between awhile (continuation-condition) { loop body statements }
while
loop
and the iteration table and tail-recursive implementation
is as follows:
while
loop involves a
continuation condition. This is the opposite
of the stop condition which is the base case of the
tail-recursive or recursive implementations.
while
loop implementation does not
involve an auxiliary method. Instead, all state variables
in the iteration table which are not parameters of the method
are initialized at the beginning of the method.
while
loop implementation
of a method, we can derive the iteration table by creating
a column for each parameter in the method and
for each state variable which is initialized outside the
loop and updated inside the loop.
Variables which are initialized outside the loop and not
modified within the loop are not needed in the iteration table.
For the while
loop implementation of
reverse
, we see that we need to initialize
one state variable result at the beginning of the method
because reverseWhile
has one parameter list
but the iteration table has two state variables (list and
result). The implementation with comments is given below.
public static IntList reverseWhile(IntList list) { IntList result = empty(); // initialize state variable while (!isEmpty(list)) { // continuation condition is opposite of base case // update state variables in body of loop // must update result before list because // it depends on the original value of list result = prepend(head(list), result); list = tail(list); } // end of loop return result; // answer is returned when loop is finished }
for
loopsfor
loop is a form of iteration which
is just a while
loop written in a more compact
syntax. In computer science, we call this phenomenon syntactic
sugar. So, a for
loop is syntactic
sugar for a while
loop. Every
for
loop can be written as a
while
loop, and vice versa, but it may not
always be easy to do so. for
loops are generally
used with arrays which we will be studying in the near
future. Their syntax is useful in situations in which there is a
counter which is incremented or decremented with each pass
through the iteration. The formal syntax for a Java
for
loop is
The relationship between afor (counter-initialization; continuation-condition; counter-update) { loop body statements }
for
loop
and while
loop implementation is as follows:
for
loop is equivalent to
the following Java while
loop:
counter-initialization while (continuation-condition) { loop body statements counter-update }
for
loop involves a
continuation condition. This is the opposite
of the stop condition which is the base case of the
tail-recursive or recursive implementations. The continuation
condition of the for
and
while
loops can be exactly the same.
for
loop counter. If the counter
is not a parameter of the method, it gets initialized in the
counter-initialization part of the for
loop instead of at the beginning of the method.
for
loop instead of at the end of the
loop body.
for
loop are initialized
at the beginning of the method.
for
loop specifications blank. However, the semicolons must be in
place to identify the three parts. An infinite loop can be created
by the following syntax:
for ( ; ; ) { // no conditions loop body statements // these statements run forever! }
for
loop specifications.
Statements should be separated by commas. For example,
for (int i=0, IntList L=list ; (!isEmpty(L) && (i<5)) ; i=i+1, L=tail(L)) { loop body statements }
for
loop implementation
of a method, we can derive the iteration table by creating
a column for each parameter in the method, for
each counter, and for each state variable which
is initialized outside the loop and updated inside the loop.
Variables which are initialized outside the loop and not
modified within the loop are not needed in the iteration table.
For the for
loop implementation of
reverse
, determining what the counter will
be is a bit tricky since there aren't any numbers which are
incrementing or decrementing. Instead, we pick the IntList
list to be our counter because it is shrinking with each
pass through the iteration. Since list is a parameter
of our method, it doesn't need to be initialized. Therefore,
there will be nothing in the counter-initialization
part of our for
loop.
The implementation with comments is given below.
public static IntList reverseFor(IntList list) { IntList result = empty(); // initialize state variable // no counter-initialization // loop continues while list is not empty // list becomes tail(list) with each pass through iteration for ( ; !isEmpty(list); list=tail(list)) { // update state variables in body of loop result = prepend(head(list), result); } // end of loop return result; // answer is returned when loop is finished }