How to Design Programs: An Introduction to Computing and Programming
[Go to
first
,
previous
,
next
page;
contents
;
index
]
Section 26
Designing Algorithms
At first glance, the algorithms
move-until-out
and
quick-sort
have little in common. One processes
structures; the other processes lists. One creates a new structure for the generative step; the other splits up a list
into three pieces and recurs on two of them. In short, a comparison of the two examples of generative recursion
suggests that the design of algorithms is an ad hoc activity and that it is impossible to come up with a general
design recipe. A closer look, however, suggests a different picture.
First, even though we speak of algorithms as processes that solve problems, they are still functions that consume
and produce data. In other words, we still choose data to represent a problem, and we must definitely understand
the nature of our data if we wish to understand the process. Second, we describe the processes in terms of data, for
example, ``creating a new structure'' or ``partitioning a list of numbers.'' Third, we always distinguish between
input data for which it is trivial to produce a solution and those for which it is not. Fourth, the generation of
problems is the key to the design of algorithms. Although the idea of how to generate a new problem might be
independent of a data representation, it must certainly be implemented for whatever form of representation we
choose for our problem. Finally, once the generated problems have been solved, the solutions must be combined
with other values.
Let us examine the six general stages of our structural design recipe in light of our discussion:
Data analysis and design:
The choice of a data representation for a problem often affects our thinking about the process. Sometimes
the description of a process dictates a particular choice of representation. On other occasions, it is possible
and worthwhile to explore alternatives. In any case, we must analyze and define our data collections.
Contract, purpose, header:
We also need a contract, a definition header, and a purpose statement. Since the generative step has no
connection to the structure of the data definition, the purpose statement should not only specify
what
the
function does but should also include a comment that explains in general terms
how
it works.
Function examples:
In our previous design recipes, the function examples merely specified which output the function should
produce for some given input. For algorithms, examples should illustrate
how
the algorithm proceeds for
some given input. This helps us to design, and readers to understand, the algorithm. For functions such as
move-until-out
the process is trivial and doesn't need more than a few words. For others, including,
quick-sort
, the process relies on a non-trivial idea for its generative step, and its explanation requires a
good example such as the one in figure
67
.