Introduction To Computer Science
Introduction To Computer Science
COMPUTER IA ©GtraxgOoo:
J
Introduction to
COMPUTER
SCIENCE
A Structured Approach
Second Edition
Digitized by the Internet Archive
in 2011
[Link]
Introduction to
COMPUTER 1
SCIENCE - 1
A Structured Approach
Second Edition 1
|f
Neill Graham
Bibliography: p.
Includes index.
1. Structured programming. I. Title.
QA76.6.G68 1982 uOl.64'2 81-21969
ISBN 0-314-63243-3 AACR2 INTL. ISBN 0-314-69794-2
Preface xi
Computer Software 54
d Selection 108
H Repetition 129
© Arrays 144
H^ Stacks 235
Vl Records 257
13.1 Record Structures 258
13.2 Declarations 261
13.3 More Complicated Records 262
13.4 Arrays of Records 267
13.5 Input, Output, and Assignment 272
Index 545
Preface
XI
xii Pre/ace
There was a time when the word "computer" invariably referred to the
mammoth data processing installations used by large organizations. These
days, however, we can computers almost anywhere: in automobiles,
find
in cameras, in games, in household appliances. There are computers that
fit in your pocket, computers that sit on your desk, and computers that fill
a room. There are computers that cost hundreds of dollars, computers that
cost thousands, and computers that cost millions.
Yet no matter how much computers differ in size, cost, and internal
construction, they all have two characteristics in common:
ax2 + bx ~ c =
o
o
o
Traffic Light
^
>-»
2H 2 - 0; 2H 2
1.1 The Information-Processing machine 3
speech, music, and electrical sensing and control signals for other ma-
chines.
A computerwill manipulate meaningless combinations of symbols just
as readily as meaningful ones. Computer people refer to meaningless data
as garbage; they use the phrase "garbage in, garbage out" to describe what
happens when garbage is fed into a computer.
lates a new set of paths. The process continues until it arrives at a satisfac-
tory design or until the computer gives up because a predetermined num-
ber of attempts have failed to find an acceptable design.
Perhaps because "compute" originally meant "to do arithmetic," when
people think of computers they seem to think of arithmetic first. Computers
were invented to solve mathematical problems, and this remains one of
their important applications. But they can do other jobs, too. Many com-
puter applications involve little or no arithmetic.
Word Processing. You enter the first draft of a letter, term paper, article,
or book into the computer. Then you revise it by directing the computer to
insert, delete, and rearrange specific pieces of material. When the results
meet your expectations, you can order the computer to type out a perfect
copy.
Game Playing. A
computer, particularly one equipped with a television-
like display, a fantastic "gameboard." Computers are now widely
makes
used in home electronic and video games as well as those found in arcades.
Even the traditional pinball machine now has a computer inside. Many
people who own their own personal computers use them, in part, for
game playing.
Nor are computers limited to the popular "space battle" games. There
are computer programs that play checkers and backgammon at the cham-
pionship levels. Chess-playing programs that run on large computers can
challenge expert- and master-level players. Chess-playing programs that
run on small computers, including the special-purpose chess-playing ma-
chines, are good enough to challenge the average chess player.
2. An
algorithm is elective. No instruction may be impossible to carry out
for the person or machine executing the algorithm.
Suppose, for instance, that an algorithm demands that we take the
square root of 2 with perfect precision. The square root of 2 is given by
\fl = 1.4142135623 . . .
where the dots indicate an infinite sequence of additional digits. This un-
ending sequence of digits could never be worked out in a finite amount of
time, could never be written out on a blackboard or a piece of paper,
could never be stored inside any computer. An algorithm that demands we
take the square root of two with perfect precision, then, is not effective.
Another example: we might give an algorithm for solving our energy
problems that calls for a machine that produces more energy than it con-
sumes. But physicists have proved that such a machine, called a perpetual-
motion machine, cannot exist. Therefore, an algorithm that calls for the
use of a perpetual-motion machine cannot be effective.
Note that while the three characteristics just given are necessary for an
1.2 The Instruction-Following Machine 7
The Euclidean Algorithm. Let's take as an example one of the oldest re-
corded algorithms, Euclid's algorithm for finding the greatest common div-
isor of two numbers. To see just what this algorithm is supposed to accom-
plish, let's recall a few elementary properties of numbers.
To begin with, we will be working with the nonnegarive integers, 0,
1, 2, 3, 4, and so on. For short, however, we will usually say number
For any number we can make a list of its divisors all of the other —
numbers that divide it. The divisors of 6, for instance, are 1, 2, 3, and 6.
The divisors of 10 are 1, 2, 5, and 10. The divisors of 7 are 1 and 7. And
so on. Note that the divisors of a number always include 1 and the number
itself.
the divisors 1 and 2 in common. We say that 1 and 2 are the common
divisors of 6 and 8. Another example: The divisors of 18 are 1, 2, 3, 6,
and 9. The divisors of 24 are 1, 2, 3, 4, 6, 8, and 12. The common
divisors of 18 and 24 are 1, 2, 3, and 6.
Notice that any pair of numbers has at least one common divisor,
since 1 is a divisor of every number.
Given the common two numbers, one common divisor is
divisors of
greater than all the others. This is common divisor of the two
the greatest
numbers. Since the common divisors of 6 and 8 are 1 and 2, the greatest
common divisor of 6 and 8 is 2. Since the common divisors of 18 and 24
are 1, 2, 3, and 6, the greatest common divisor of 18 and 24 is 6. Since 1
is the only common divisor of 5 and 7, the greatest common divisor of 5
and 7 is 1.
What we want to construct is an algorithm for finding the greatest com-
mon divisor of two numbers without going to the trouble of finding all the
divisors of each number.
Before we go any further, you might well want to ask to what use we
can put the greatest common divisor once we have found it. There are
many such uses, but one of the most familiar ones is reducing fractions.
To reduce a fraction to its lowest terms, we divide both the numerator and
the denominator by the greatest common divisor of the two. Thus, to re-
duce 18/24 to lowest terms, we divide both the numerator and denomina-
1 Introduction: Computers, Information and Algorithms
tor 6, which is the greatest common divisor of 18 and 24. The result is
by
3/4,which is indeed 18/24 reduced to lowest terms. Any computer pro-
gram that manipulates fractions as fractions (instead of changing them to
decimals) must be able to find greatest common divisors, so it can reduce
the results of its calculations to their lowest terms.
greatest common divisor of the remainder and the smaller number is the
same as the greatest common divisor of the original two numbers.
For example, the greatest common divisor of 24 and 10 is 2. Now di-
vide 24 by 10
2
10)~24
20
4
25 I~35
25
10
by a smaller one, the remainder than either the divisor or the divi-
is less
dend. After each repetition, then, the smaller of the two numbers will be
less than the smaller of the two numbers on the previous repetition. If we
carry out enough repetitions, the smaller number getting less and less with
each repetition, then eventually the smaller number will become 0.
But now we can bring in Property 2. When one of two numbers is 0,
the other number is the greatest common divisor of the two. So when the
smaller of the two numbers we are working with is 0, the larger is the
greatest common divisor of the two. But by Property 1, this is also the
greatest common divisor of the two numbers we started with and so is the
answer we are seeking.
Figure 1-2 illustrates how to calculate the greatest common divisor of
99 and 55 using the Euclidean algorithm. The first step is to divide 99 by
55 and get the remainder, which is 44. By Property 1, the greatest common
divisor of 55 and 44 is the same as the greatest common divisor of 99 and
55.
Therefore, we We divide 55 by 44 and
turn our attention to 55 and 44.
get the remainder, which is 11. By Property 1, the greatest common divi-
sor of 44 and 11 is the same as the greatest common divisor of 55 and 44
and so is the greatest common divisor of 99 and 55.
So we turn our attention to 44 and 11. We divide 44 by 11 and get the
remainder, which is 0. By Property 2, the greatest common divisor of 11
FIGURE 1-2. Using the greatest common divisor algorithm to show that the greatest common
divisor of 99 and 55 is 11.
Step 1: 1
Larger number is 99 55 T99
Smaller number is 55 55
Remainder is 44 44
Step 2: 1
Larger number is 55 44 T55"
Smaller number is 44 44
Remainder is 11 11
Step 3: 4
Larger number is 44 11 )44
Smaller number is 11 44
Remainder is
Step 4:
Larger number is 11
Smaller number is
(Since the smaller numt er is the value of
,
guage that will be developed more fully in later chapters. All the instruc-
tions between WHILE DO and END WHILE are to be carried out re-
. . .
Stepwise Refinement. Xow let's refine our algorithm by translating the En-
glish language description just given into a more precise notation. The
technique of refining an algorithm by replacing English language descrip-
tions by more precise ones is called stepwise refinement.
To state our algorithm more precisely, we must be able to refer to any
of the numbers involved in the calculation. To do this, we will assign the
numbers names. Let's imagine boxes drawn on the blackboard, with the
names beside them, as shown in Figure 1-3. As the execution of the algo-
FIGURE 1-3. The named boxes hold the values that will be manipulated by the greatest com-
mon divisor algorithm. The values in the boxes will change as the execution of the algorithm
proceeds.
LARGER 10
SMALLER
I
REMAINDER
1.2 The Instruction-Following Machine 11
rithm proceeds, we will erase the numbers in the boxes and replace them
with new, updated values. We will need to keep track of three numbers in
this way: the larger number (LARGER), the smaller number (SMALLER),
and the remainder we get when we divide the larger number by the smaller
(REMAINDER).
We need two special signs. MOD is the mathematician's sign
will also
for the remainder of a division. Thus 6 MOD 4 - 2, 20 MOD 7 = 6, 99
MOD 55 = 44, and so on.
The arrow sign <— means that the value on the right is to be copied
into the box named on the left. Thus LARGER <— 5 means that 5 is to be
written in the box labeled LARGER, replacing whatever number was pre-
viously there. LARGER «- SMALLER means that thenumber in SMALLER
is copied into LARGER, replacing whatever number was previously in
LARGER. And
WHILE SMALLER ^ DO
REMAINDER «- LARGER MOD SMALLER
LARGER «- SMALLER
SMALLER <r- REMAINDER
END WHILE
LARGER
SMALLER
REMAINDER
LARGER «- SMALLER
LARGER
SMALLER
SMALLER «- REMAINDER
SMALLER
REMAINDER
FIGURE 1-4. The special signs used in the greatest common divisor algorithm.
LARGER — SMALLER
35 35 14
SMALLER «- REMAINDER
35 14 14
REMAINDER — LARGER MOD SMALLER
35 14 7
LARGER — SMALLER
14 14 7
SMALLER — REMAINDER
14 7 7
REMAINDER «- LARGER MOD SMALLER
14 7
LARGER — SMALLER
7 7
SMALLER «- REMAINDER
7
FIGURE 1-5. A trace of the execution of the greatest common divisor algorithm. The row of
numbers preceding each statement shows the contents of LARGER, SMALLER, and REMAIN-
DER before the statement is executed. The row of numbers following the statement shows the
contents of the same locations after the statement has been executed. Comparing the two rows
reveals the effect of the statement.
We can do a few things to dress up our algorithm. Let's use the state-
ment
to indicate that the input data for the problem —the numbers whose great-
est common divisor we are to find — are to be placed in LARGER and
SMALLER. Also let
OUTPUT LARGER
1.3 Flowcharts
Another way to display an algorithm is with a flowchart. A flowchart con-
sists of boxes containing instructions and connected together by lines. We
follow the lines from box to box, executing the instructions inside each
box as it is encountered. Special symbols mark the starting point and pos-
sible stopping points. A decision symbol directs us to one of two possible
paths; which path we follow depends on whether the condition inside the
decision symbol is true or false.
The Flowchart Symbols. Figure 1-7 shows the various flowchart symbols:
Terminal Symbol. This oval, which contains either the word START or
the word STOP, indicates the starting and stopping points in the flow-
chart. A flowchart can only have one starting point, but it may have many
possible stopping points.
ALGORITHM GREATEST_COMMON_DIVISOR
INPUT LARGER, SMALLER
WHILE SMALLER ^ DO
REMAINDER *- LARGER MOD SMALLER
LARGER «- SMALLER
SMALLER «- REMAINDER
END WHILE
OUTPUT LARGER
END GREATEST_COMMON_DIVISOR
1.3 Flowcharts 15
Terminal (Start/Stop)
Input/Output
Processing
Decision
Collector
FIGURE 1-7. The five flowchart symbols. The use of each symbol is described in the text.
Collector Circle. Collector circles are points at which different paths join
together.
OUTPUT LARGER
;t:p
chart becomes an intricate maze in which it's all too easy to get lost. For
more complex algorithms, we will find our algorithmic language to be a
better method of presentation than flowcharts.
4. Give ten examples of symbols. Avoid obvious ones like the letters of
the alphabet.
7. Give two other terms that can be used in place of information process-
ing to describe what a computer does.
8. What do computer people mean when they refer to garbage?
15. It has been said that (a) "a computer can only do what it's told to,"
and (b) "a computer is an all-purpose machine." To what characteristic of
computers do both of these statements refer?
17. Why do we usually use some formal notation instead of English for
stating algorithms?
20. Define the greatest common divisor of two numbers. What is one com-
mon application of the greatest common divisor?
21. Describe Euclid's algorithm for finding the greatest common divisor of
two numbers.
22. Explain those features of our algorithmic language that we made use of
in presenting Euclid's algorithm.
24. Draw the five types of flowchart symbols and give the purpose of each.
25. What do computer people mean by a ioop? How does the term relate
to flowcharts?
Show that the algorithm will still give the correct answer. (Hint: What will
have happened after the first execution of the repeated statements?)
and output the numerator and denominator of the same fraction reduced to
lowest terms. Thus if the fraction in question is 12/16, the input to the
algorithm will be 12 and 16, and the output will be 3 and 4.
two fractions and output the numerator and denominator of the sum of the
two fractions. The sum is to be reduced to lowest terms. For instance, if
the fractions to be added are 3/4 and 1/12, then the input is 3 and 4 (first
fraction) and 1 and 12 (second fraction). The output is 5 and 6, represent-
ing 5/6.
1.3 Flowcharts 19
two fractions and output the numerator and denominator of their product,
reduced to lowest terms.
two fractions and output the numerator and denominator of their quotient,
reduced to lowest terms.
COMPUTER
HARDWARE
AND
SOFTWARE
Computer
Hardware
and Information
Unn
Representation
The input, output, and auxiliary memory devices are known as pe-
occupy different cabinets than do the central
ripherals because they often
processing unit and main memory. This isn't always the case, however,
so there are computer systems for which some or all of the "peripher-
als" occupy the same enclosure as the central processing unit and main
memory.
23
24 2 Computer Hardware and Information Representation
Central
Main Output Input Auxiliary
processing
memory Device Device Memory
unit
XL ir^r Bus
Iz
FIGURE 2-1. The hardware components of a typical computer system. There can be any num-
ber of auxiliary memory, input, and output devices.
Main Memory. Main memory is used to store two things: the program that
the computer is currently executing and the data that it is currently manip-
ulating. We can think of main memory as a kind of scratchpad or black-
board that holds not only the data the computer is working with but the
instructions it's following as well.
Main memory is divided up into a large number of separate memory
cells or memory locations. Each memory location holds a fixed amount of
data and has an address by which it can be referred to for the purpose of
storing data in it or retrieving data from it. We can picture main memory
as a collection of post office boxes. The boxes correspond to memory loca-
tions and the box numbers correspond to addresses.
Nomatter what job the computer system may be doing, the central
processor is just fetching and executing instructions, one after another.
Clearly, the ability of the system to do any complex job, such as playing
chess, lies with the program and not with the central processor, which is
just following orders. For this reason, we usually give the program credit
for the job rather than the computer. We speak of a program that plays
chess or a program that makes out payrolls rather than a computer that
plays chess or a computer that makes out payrolls.
In recent years, engineers have learned how to construct an entire cen-
tral processing unit on a tiny chip of silicon that can be mass produced at
2.1 The Hardware 25
low cost. A central processing unit constructed on a single silicon chip (or
on a small number of chips) is called a microprocessor. Some other com-
puter components, most notably main memory, can also be constructed
on silicon chips.
The availability of microprocessors and other low-cost computer com-
ponents makes it possible to use computers in many places where they
would have once been out of the question, such as in games, automobiles,
and household appliances. The resulting changes in the ways people use
computers are known as the microprocessor revolution.
Input and Output Devices. Input and output devices allow the computer
system to communicate with the outside world. Looked at another way,
input and output devices translate between symbols convenient for human
beings (such as the letters of the alphabet) and the codes that the computer
hardware needs.
There are many different kinds of input and output devices, corre-
sponding to the many different kinds of data that we want to be able to
process with computers. There are speech synthesizers that let a computer
talk, music synthesizers that let it play music, plotters that let it draw
pictures, and special devices that convert sounds from a microphone or
pictures from a television camera into a form suitable for computer pro-
cessing.
Instead of trying to survey all of these exotic devices, however, we
will confine our attention to the input and output devices you are most
likely to encounter as a student. These are computer terminals, key-
punches, card readers, and high-speed printers.
A computer terminal consists of a typewriterlike keyboard and (de-
pending on the kind of terminal) either a televisionlike display screen or a
typewriterlike printer. The terminal is connected to the rest of the com-
puter system by wires, which may be and often are ordinary telephone
lines.
Data typed on the keyboard is transmitted over the connecting wires to
the computer. Data received over the wires from the computer is (depend-
ing on the kind of terminal) either displayed on the screen or typed out by
the printer.
Instead of data being transmitted directly to the computer as soon as it
the data from the cards by sensing the punched holes. The computer sys-
tem can punch own
cards using an output device known as a card
its
punch. Often a card reader and a card punch are combined in the same
unit.
Often computer systems must produce large amounts of printed out-
put, such as bills for all of a company's customers or checks for all of its
employees. For this purpose, a high-speed printer is used. One widely
used type of high-speed printer is called a line printer, since it prints an
entire line in a single operation. Some high-speed printers can print thou-
sands or even tens of thousands of lines per minute. They may use exotic
technologies such as laser beams.
no off
yes on
Now suppose we have two circuits instead of one. With two circuits
we have four combinations:
off-off on-off
off-on on-on
fall off-off
winter off-on
spring on-off
summer on-on
off-off-off on-off-off
off-off-on on-off-on
off-on-off on-on-off
off-on-on on-on-on
We could use these to represent the seven days of the week, for instance,
and still have one alternative left over:
Sunday off-off-off
Monday off-off-on
Tuesday off-on-off
Wednesday off-on-on
Thursday on-off-off
Friday on-off-on
Saturday on-on-off
Binary Codes. We use the term binary code for any method of representing
information with two-state circuits. The word binary, you may recall from
—
your other studies, refers to two in this case the two possible states of
each circuit.
When we talk about binary codes, we don't want to be worried about
writing the words off and on in complicated combinations such as:
off-on-off-off-on-on-off-on
To avoid this, we
use the symbols and 1 to stand for off and on.
What's more, we can use Os and Is in ways that have nothing to do
with circuits or currents. For instance, we can represent a 1 by a hole
punched in a particular position of a card and a by the absence of a hole
in that position. Or we can represent a by a certain piece of magnetic
tape being magnetized in one direction and a 1 by that piece of tape being
magnetized in the opposite direction.
When and 1 are used in this way, we call them binary digits or bits.
A binary code is a method of representing information using combinations
of bits.
All our previous examples could be rewritten using and 1 instead of
off and on. Thus we could represent the four seasons with two bits:
fall 00
winter 01
spring 10
summer 11
Sunday 000
Monday 001
Tuesday 010
Wednesday 011
Thursday 100
Friday 101
Saturday 110
find that with one bit we can represent 2 alternatives, with two bits we
can represent 2 x 2 or four alternatives, with three bits we can represent
2 x 2 x 2 or eight alternatives, and so on.
Repeated products of a number with itself are called the powers of that
number. Mathematicians have a special shorthand notation for powers
called exponential notation. In exponential notation, 2 x 2 is written 2 2 ,
3 4
2 x 2 x 2 is written 2 2 x 2 x 2 x 2 is written 2
, and so on. By ,
1
convention, 2° represents 1 and 2 represents 2. The raised number repre-
senting the number of 2s to be multiplied together is called an exponent,
from which exponential notation gets its name.
Thus, with one bit we can represent 2 alternatives, with two bits we
1
2 3
can represent 2 with three bits we can represent 2 and so on.
, ,
marks with which we are all familiar. An input device then converts these
characters into binary codes that the computer can manipulate. For output,
an output device converts the computer's binary codes into symbols mean-
ingful to humans.
For this approach to work, we need a character code a standard —
scheme for representing characters by combinations of bits. There is more
than one such code in use. But the most widely used one is the American
Standard Code for Information Interchange, usually abbreviated to ASCII,
which is pronounced as' key.
The ASCII code uses seven each character. Seven bits
bits to represent
7
gives us 2 ASCII can represent 128 characters. This
or 128 alternatives, so
is enough to represent the upper- and lower-case letters, the digits, the
tion. The three bits at the head of the column containing the character are
the leftmost three bits of the code. The four bits to the left of the row con-
taining the character are the rightmost four bits of the code. Thus, the code
for A is 1000001, the code for B is 1000010, and so on.
The two- and three-letter abbreviations represent control characters.
We won't go throughall of them since many are used for specialized tech-
nical purposes. The following three are commonly used: CR, carriage re-
turn, returns the typing mechanism to the left margin; LF, line feed, ad-
vances the paper by one line; BEL, bell, causes a bell or other alarm
device to sound.
Binary Notation. The system for representing numbers that we all learned
about in school makes use of the ten digits through 9. We call this system
the base- 10 or decimal system, and we say that a number represented this
way is in decimal notation.
In a computer we have only two symbols at our disposal: and 1. The
2.2 Information Representation 31
1101 CR GS M ] m }
1110 SO RS . > N A n ~
1111 SI US / ? " DEL
FIGURE 2-2. The ASCII code. The two- and three-letter abbreviations represent control char-
acters. Examples are CR (carriage return). LF (line feed), and BEL (bell).
3, 4, 5, 6, 7, 8. and 9.
2 7 4
That is, 8,274 represents eight thousands, two hundreds, seven tens, and
four units. Arithmetically, we can express this as:
does in the decimal system. Thus 2 enters the binary system in the follow-
ing two ways:
2. The digits of a binary number, taken from right to left, represent units,
twos, fours, eights, and so on. The numbers 1. 2. 4. 8, and so on are the
powers of 2. the numbers we get by starting with 1 and multiplying bv 2
repeatedly.
Thus, the binary number 1101 can be analyzed as:
Eights
That
110is,
Fours Twos Units
1101 represents one eight, one four, zero twos, and one unit.
Arithmetically, we can express this as:
1101 =1x8-1x4+0x2-1x1= 13
We see that 1101 represents the same value in binary notation that 13 does
in decimal notation.
The equation in the previous paragraph could be confusing, since we
might not realize that 1101 is in the binary system and wonder how one
thousand, one hundred and one can equal thirteen. When the possibility
of confusion exists, we use a subscript to indicate the base in which a
particular number is written. Thus we write thirteen in the binary system
as 1101 2 and we can write the equation in the last paragraph more clearly
,
as:
1101 2 =1x8-1x4-0x2-1x1= 13
to the left to advance one place, just as happens with an ordinary counter
when a dial turns from 9 back to 0.
Suppose the counter has four dials. Its initial reading is 0000. The first
count causes it to advance to 0001. The next count causes the rightmost
dial to turn from 1 back to 0. This, in turn, causes the next dial to the left
to advance one position. So after two counts the counter reads 0010. After
three counts it reads 0011; after four counts it reads 0100 (Why?); after five
counts it reads 0101; and so on.
Numbers with fractional parts can be represented in binary notation
using the same approach that we use in decimal notation. The integer and
fractional parts of the number are separated by a "decimal point," hereafter
called a radix point, since its function is independent of any particular
number svstem.
—
In the decimal system, the digits to the left of the radix (decimal)
point, taken from left to right, represent tenths, hundredths, thou-
sandths, and so on. We can analyze 27.45 as:
2 7 4 5
Thus, 27.45 represents two tens, seven units, four tenths, and five hun-
dredths. Arithmetically, we can express this as:
In binary notation the digits to the right of the radix point, taken from
left to right, represent halves, quarters, eighths, and so on. We can ana-
lyze 11.101 2 as:
Twos
111 Units Halves
11.101, =
=
1X2 + 1X1 +
4
111
1X-+0X-+1X-
2
2 + 1 + .5 + .125
= 3.625
+ =
+ 1 = 1
1 + = 1
1 + 1 = 10 (that is, and 1 to carry)
Notice how simple this is compared to the addition table for the deci-
mal system that we all had to learn as schoolchildren. The simplicity of
the addition table leads to a corresponding simplicity in the electrical cir-
cuits in thecomputer that do the additions.
With the help of the addition table, we can easily work out a binary
addition. Throughout this section we will use four-bit binary numbers
as examples. To help you follow the examples, the decimal value of
each binary number will be written in parentheses besides the binary
value:
34 2 Computer Hardware and Information Representation
1001 (9)
+ 0101 (5)
1110 (14)
1001 (9)
- 0101 (5)
0100 (4)
0x0-0
0x1 =
1x0 =
1X1 = 1
This is even simpler than the addition table, since no carries are involved.
For multiplication, we can arrange our work in the same way that we
do in the decimal system:
1010 (10)
x 1101 (13)
1010
0000
1010
1010
10000010 (130)
1101 (13)
011 ) 10010110 (150)
1011
1111
1011
1001
0000
10010
1011
111 (7)
2.3 Operations in Binary Values 35
OR =
OR 1 = 1
1 OR = 1
1 OR 1 = 1
1001 0111
OR 0010 OR 0010
1011 0111
In each case the second bit from the right is set to 1, regardless of whether
it was or 1 initially.
The exclusive or operation XOR is similar to OR except it gives when
both its operands are 1:
XOR =
XOR 1 = 1
1 XOR = 1
1 XOR 1 =
1001 0111
XOR 0010 XOR 0010
1011 0101
1010
XOR 1111
0101
36 2 Computer Hardware and Information Representation
NOT = 1
NOT 1 =
NOT 1010
0101
AND =
AND 1 =
1 AND =
1 AND 1 = 1
1101 0111
AND 1001 AND 1001
1001 0001
SHL 1101
1010
The shift right operation, SHR, shifts all of the bits one place to the
right. A is shifted into the leftmost position:
SHR 1011
0101
SHL 1011
0110
2.4 Octal and Hexadecimal Notation 37
SHL 0110
1100
Next, we take the second value, 0110, and set its two leftmost bits to
to make room for the two bits we obtained from the first value:
0110
AND 0011
0010
1100
OR 0010
1110
110000100011101001001011
Can you copy this number down without making a mistake? Can you
look at it and then copy it down from memory? Can you call it out for
someone else to copy down? Try comparing it with:
110000100011101001011011
Are the two numbers the same? If not, where do they differ?
Chances are that you found the tasks set in the last paragraph difficult
or impossible to carry out. Human
beings find long strings of 0s and Is
tedious or impossible to work with. Some people, impressed with the ex-
treme simplicity of the binary addition and multiplication tables, have
suggested thathuman beings should switch to the binary system. No way!
Who wants to make out a check for $1000001101 instead of $525 or for
$1111101000 instead of $1000?
To avoid the problems of working with binary numbers, programmers
38 2 Computer Hardware and Information Representation
usually use one of two alternative notations, octal and hexadecimal. Each
is so closely related to binary notation that we can convert between octal
110,000,100,011,101,001,001,011
This helps some, butwe can go even further. Let's replace each group
of three bits by the single digit that has the same numerical value. Thus,
we replace 000 by 0, 001 by 1, 010 by 2, and so on. The digits that replace
the three-bit groups are called octal digits. Figure 2-3 shows the correspon-
dence between octal digits and three-bit groups.
Replacing each three-bit group in the example by the corresponding
octal digit, we get:
60435113
This is certainly easier to deal with than the original binary number. You
60435133
Now you should have no difficulty in seeing not only that the two numbers
where the difference lies.
are different but exactly
We can work the process just described in reverse, of course. That is,
given an octal number, we can convert it to binary by substituting the
FIGURE 2-3. The correspondence between octal digits and three-bit groups.
000
1 001
2 010
3 011
4 100
5 101
6 110
7 111
2.4 Octal and Hexadecimal Notation 39
proper three-bit group for each octal digit. For example, to convert the
octal number 5743 to binary, we substitute 101 for 5, 111 for 7, and so
on. This gives us:
101,111,100,011
101111100011
The octal number system represents numbers using the eight digits 0,
1, 2, 3, 4, 5, 6, and 7. Octal notation is a base-8 number system for the
same reasons that binary notation is a base-2 system and decimal notation
is a base-10 system.
Where confusion might result, we can use the subscript 8 to indicate
that a number is in octal notation:
5743 8 = 101111100011 2
1100,0010,0011,1010,0100,1011
Following the same path that we did for octal, we would like to replace
each four-bit group by a single digit.
This idea runs into trouble at once. There are 16 possible four-bit bi-
nary numbers. But we only have the 10 digits 0-9 at our disposal. To put
our plan into effect, we have to come up with six more digits from some-
where.
What we do is this: we use the digits 0-9 for the four-bit groups 0000
through 1001. For the 6 four-bit groups 1010 through 1111, we use the
letters A through F. Using letters for digits may seem strange at first, but
the practice has a long history. The ancient Greeks, Romans, and Hebrews
all used the letters of their alphabets to represent numbers.
Figure 2-4 shows the correspondence between the four-bit groups and
the hexadecimal digits 0-9 and A-F. For each of the digits A-F we have
to bear in mind two things —
the bit pattern it represents and the numerical
value it represents. Thus, we should think of A as representing 1010 and
ten; of B as representing 1011 and eleven; and so on. The need to learn
both the bit patterns and the numerical values for A-F makes hexadecimal
slightly harder than octal for beginners to master.
Replacing the four-bit groups in our example by hexadecimal digits,
we get:
C23A4B
FIGURE 2-4. The correspondence between hexadecimal digits and four-bit groups.
C23A5B
You should again have no trouble seeing both that the two numbers differ
and exactly where they differ.
By using Figure 2-4 in reverse, we can easily convert from hexadeci-
mal to binary. To convert AC9F to binary, for instance, we first replace
each hexadecimal digit by the corresponding four-bit group:
1010.1100.1001.1111
1010110010011111
AC9F 16 = 1010110010011111 2
1 1 1 1 1 1 1
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 Bit Number
simpler and easier to understand than any real computer. In spite of this
computer's simplicity, however, its overall structure is similar to that of
real computers, and it will serve as a good introduction to real machines.
Words. A computer normally works not with individual bits but with
groups of bits called words. The number of bits in a word varies from one
computer to another. Typical word sizes are 8 bits, 12 bits, 16 bits, 32
bits, 36 bits, and 60 bits. Some computers allow words of several different
sizes; others have only one word size.
Our computer will use only one word size, 16 bits. All the data and
instructions that it works with must fit into 16-bit words. Figure 2-5 illus-
trates the 16-bit word of our computer.
We can represent a 16-bit word conveniently by means of four hexa-
decimal digits. Figure 2-6 shows several words of data with their hexade-
cimal representations. Note that if the number of bits in our computer's
words had been a multiple of three instead of four, we would have proba-
bly used octal notation instead of hexadecimal notation. Why?
Data and Instruction Formats. To keep our computer simple, we will al-
low it to manipulate only one kind of data-signed whole numbers in the
FIGURE 2-6. Three examples of how we can represent the contents of a 16-bit word by four
hexadecimal digits.
1 1 1 1 1 11 1 1 1 F3AC
1 1 c 1 1 1 1 1 24AB
1 1 1 1 1 1 1 1 1 E9D1
42 2 Computer Hardware and Information Representation
The rightmost 15 bits of the word represent the magnitude of the num-
15
ber in ordinary binary notation. Note that 15 bits gives us 2 or 32,768
alternatives —
sufficient to represent magnitudes in the range through
32,767.
For example, consider the word:
0000000000000011
1000000000000011
The magnitude the same as before, but the sign bit is now 1 instead of
is
FIGURE 2-7. Our computer stores numbers in the sign-magnitude representation. The left-
most bit of a word represents the sign of the number. The remaining fifteen bits represent the
magnitude of the number.
si gn
magnitude
15 14
2.5 A SimpJe Computer 43
operation
code
1
1
address
15 12 11
FIGURE 2-8. The format for the instructions of our computer. The leftmost four bits of a word
hold the operation code, which tells the computer what operation to carry out. The rightmost
twelve bits usually hold the address of a memory location that the computer will have to refer
to in order to carry out the requested operation.
Memory
Address Location
000
001
002
003
004
005 J
FFA
FFB
FFC
FFD
FFE
FFF
FIGURE 2-9. The main memory of our computer. The address of each location consists of 12
bitsand can be represented by three hexadecimal digits. The addresses, expressed in hexa-
decimal, run from 000 through FFF.
processor has other registers for its own internal use. but since these are
not accessible to the programmer, they are not part of the programming
model.
As we see from Figure 2-10, the central processor of our computer
contains exactly three registers accessible to the programmer: the accumu-
lator, the condition-code register, and the instruction-address register.
The accumuiatoris analogous to the display register of a calculator. It
holds one of the operands for each arithmetic operation, one of the values
on which the operation will be performed. The other operand is in main
memory at the address given in the instruction for the arithmetic operation.
After the operation has been carried out, the result is stored in the accu-
mulator. Since the accumulator must be able to hold any data item the
computer can manipulate, it holds one word or 16 bits. We say that it is
"16 bits wide."'
Most modern computers have a number of accumulators, usually 8 or
16. This means that some of the intermediate results in a calculation can
be stored in the central processor instead of in main memory. When these
results are needed later in the calculation, the central processor doesn't
have to take the time to fetch them from main memory.
The computer contains a compare instruction that compares the con-
tents of the accumulator with the contents of a designated main-memory
location. The comparison can have three possible outcomes: (1) the con-
tents of the accumulator are less than those of the main-memorv location,
2.5 A Simple Computer 45
Accumulator
15 14 13 12 11 10 9 876543210
T
1
Condition Code Register
Instruction Address
Register
11 10 9 8 7 6 5 4 3 2 10
FIGURE 2-10. The central processing unit of our computer contains three registers that the
programmer can manipulate directly. The accumulator holds the data that is currently being
manipulated, serving somewhat the same purpose as the display on a calculator. The condi-
tion code register records the result of comparing the contents of the accumulator with that of
a particular main memory location. The table at the bottom of the figure shows the meaning
of the contents of the condition code register. The instruction address register contains the
address of the next instruction to be executed.
(2) the contents of the two locations are equal, and (3) the contents of the
accumulator are greater than those of the main-memory location.
The condition-code register is a two-bit register that stores the outcome
of a comparison. The outcomes are coded as follows: 00 if the contents of
the accumulator are less than those of the main memory location, 01 if the
contents of the two are the same, and 10 if the contents of the accumulator
are greater. The combination 11 isn't used. The condition codes are sum-
marized in Figure 2-10.
The instruction-address register contains the address of the next in-
struction the computer is to execute. During the fetch part of its fetch-exe-
cute cycle, the central processor fetches the next instruction from the ad-
dress contained in the instruction address register.
As soon as the instruction is fetched, the central processor adds 1 to
the contents of the instruction address register. Therefore, normally, suc-
cessive instructions will come from successive memory locations. How-
ever, certain instructions called jump instructions change the contents of
the instruction address register to a value specified in the instruction, thus
causing the computer to jump to some other part of its program and con-
tinue execution from there.
46 2 Computer Hardware and Information Representation
The Instructions. The most important part of the description of any com-
puter is the description of its Figure 2-11 shows the instruc-
instruction set.
tion set for our hypothetical computer. For each instruction the figure gives
its operation code, which consists of a single hex digit. Also given is a
The Load-and-Store Instructions. These are the instructions that load val-
ues from main memory into the accumulator and store values from the
accumulator into main memory.
In our examples we will write each instruction in two ways: once as it
is actually stored in the computer, with a hexadecimal operation code and
loads the contents of location 074 into the accumulator. The contents of
location 074 remain unchanged.
FIGURE 2-11. The instructions for our hypothetical computer. We will usually refer to the
instructions by their mnemonics, which are easier to remember than the operation codes.
the accumulator; the contents of the memory location always remain un-
changed.
For subtraction, the contents of the memory location are subtracted
from the contents of the accumulator. For division, the contents of the
memory location are divided into the contents of the accumulator.
For example, the instruction
adds the contents of location 402 to the contents of the accumulator. The
result goes into the accumulator; the contents of location 402 remain un-
changed.
The instruction
subtracts the contents of location 3CD from the contents of the accumula-
tor. The result goes into the accumulator; the contents of location 3CD are
unchanged.
The instruction
divides the contents of location 13F into the contents of the accumulator.
The result goes into the accumulator; the contents of location 13F remain
unchanged.
Real computers often have a single instruction that yields both the quo-
tient and the remainder of a division. Because one instruction produces
two results, however, there must be two data registers in the CPU for stor-
ing the two results. Since our computer only has one data register in the
— —
CPU the accumulator each instruction can produce only one result.
Hence we need two division instructions, one for the quotient and one for
the remainder.
Real computers can carry out many data-manipulating operations be-
sides the arithmetic operations. At a minimum, they can do the logical and
48 2 Computer Hardware and Information Representation
The Compare Instruction. The compare instruction and the jump instruc-
tions are crucial for allowing the computer to make decisions to choose —
one another to execute depending on the conditions
set of instructions or
that exist at the time the program is executed. The compare instruction,
CMP, compares the contents of the accumulator with that of the designated
memory location; it records in the condition-code register whether the con-
tents of the accumulator were less than, equal to, or greater than the con-
tents of the main-memory location.
Thus, the instruction
causes the computer to jump to location 431 and continue execution of the
program from there.
JLT, JEQ, and JGT are the conditional jump instructions. For each
one, the jump takes place only if the contents of the condition-code regis-
ter have a particular value. If the contents of the condition-code register do
not have the required value, the jump does not take place, and the com-
puter continues execution with the instruction in the memory location fol-
lowing the one that contains the jump instruction.
JLT jumps only if the contents of the condition-code register are 00
(less than); JEQ jumps only if the contents are 01 (equal to]; and JGT jumps
only if the contents are 10 (greater than).
Thus,
causes the computer to jump to location 305 in the program only if the
contents of the condition-code register are 00 (less than). Otherwise, the
computer continues with the instruction in the memory location following
the one that contained the jump instruction A305.
2.5 A Simple Computer 49
The Input and Output Instructions. The input instruction, IN, transfers
data from the computer's single input device to main memory; the output
instruction, OUT, transfers data from main memory to the computer's sin-
gle output device.
Thus,
D205 IN 205
reads one number from the input device and stores it in location 205. The
instruction
sends the number in location 157 to the computer's output device. The
contents of location 157 remain unchanged.
The halt instruction, HALT, causes the CPU to stop fetching and ex-
ecuting instructions and go into a standby mode. The address part of the
HALT instruction is ignored. Thus,
F000 HALT
causes the central processing unit to stop fetching and executing instruc-
tions.
Location Addre
LARGER OOF
SMALLER 010
REMAINDER Oil
ZERO 012
D00F IN LARGER
D010 IN SMALLER
The next step is to see if the contents of SMALLER are 0; if they are,
the computer will jump to location 00D, which contains instructions for
. . . . .
Instruction
Address or Data Mnemonic Explanation
000 DOOF IN LARGER Input value for LARGER
001 D010 IN SMALLER Input value for SMALLER
002 1010 LDA s:.:alle?. Compare SMALLER . .
FIGURE 2-12. A program for computing the greatest common divisor of two nonnegative in-
The first column gives the addresses
tegers. of the memory locations holding the program. The
second column gives the contents of those locations. The third column gives the mnemonics
for the instructions (locations 000-00E) and for the memory locations used to store data (lo-
cations OOF-012).
outputting the value of LARGER and halting the computer. If the value of
SMALLER is not 0. the computer does not jump but continues with the
following instructions:
Now come the repeated instructions from the algorithm. We divide the
contents of LARGER by the contents of SMALLER and store the remainder
in REMAINDER. Then we store the contents of SMALLER in LARGER and
the contents of REMAINDER in SMALLER:
Now we must arrange for the seven instructions just given to be re-
peated as long as the contents of SMALLER are not 0. We do this by having
Review Questions 51
the computer jump back to location 002, the part of the program that tests
whether or not the contents of SMALLER are 0:
7. What is a bit?
9. What is the ASCII code? How are the characters x , 5, $, and + coded
in ASCII? How is a blank space coded in ASCII?
10. Give two statements that characterize the decimal number system. Give
the corresponding statements for the binary number system.
11. How can we make it clear whether 101 is the binary representation of
five or the decimal representation of one hundred and one?
12. Describe how numbers with fractional parts can be represented in bi-
nary notation?
13. Contrast the addition and multiplication tables for the binary system
with those for the decimal svstem.
52 2 Computer Hardware and Information Representation
14. Describe four logical operations and give one application of each.
20. For thecomputer described in this chapter, what is the purpose of the
accumulator? The condition-code register? The instruction-address regis-
ter?
izmmmm
1. Using the table for the ASCII code given in this chapter, show how a
short message would be coded in ASCII. Don't forget to code punctuation
marks and blank spaces as well as letters and numbers.
10. Write a program for the computer described in this chapter that will
input the numerator and denominator of a fraction and output the numer-
ator and denominator of that fraction reduced to its lowest terms.
©Gaspare
%
Computer
Software
54
3.1 Programming Languages and Language Processors 55
DOOF
D010
1010
8012
56 3 Computer Software
address of the memory locations holding the instructions and the second column gives their
contents. These columns are produced by the assembler, not the human programmer. Mne-
monics, called labels, are defined in the third column. Each label represents the address of
the instruction or data item next to which it appears. Thus LOOP represents the address 002,
FINISH the address 00D, and so on. DW (define word) instructs the assembler to reserve the
indicated number of words of memory. DC (define constant) instructs the assembler to reserve
a word containing the specified constant (zero in this case).
COBOL— Common —
Business Oriented Language is the most widely used
programming language in business data processing. COBOL is oriented to-
ward the processing of the large files of data that occur in business appli-
cations. The language caters to business users by allowing instructions to
be stated in the English-like words and phrases business people prefer
rather than as mathematical formulas.
Interpreter
Interpreter accepts
Data^ Result of program and data to be
executing processed. Output is
Interpreter *" result of processing
program with
data supplied data with program
Program supplied.
Compiler
Compiler translates
Translated program into machine
Compiler
program language.
Data^ Results of
. Translated program must
executing
.
*
Hardware program with ,. .. &
, . . machine to obtain results,
data supplied
Translated-/"'^
program
FIGURE 3-2. An interpreter produces the results of executing the interpreted program. A
compiler produces a machine-language program, which must then be executed by the com-
puter hardware to obtain the desired results.
times slower than a translated one. The reason is that most programs call
for some statements to be executed repeatedly, perhaps thousands of
times. A compiler translates each statement only once, regardless of how-
many times the translated statement will eventually be executed. An inter-
preter, however, must analyze a statement ever}' time it is executed. An
interpreter may analyze the same statement many thousands of times.
Both compilers and interpreters are examples of language processors.
center.
In interactive processing, each user communicates with the computer
system via a computer terminal. Each user engages in a conversation with
the operating system or whatever program the user is running. When the
user gives a command or enters data, the program responds. When the user
gives another command or enters more data, the program responds to that,
and so on. The program's response to a particular data item or command
may determine what data item or command the user will want to enter
next.
3.2 The Operating System 61
The system creates and maintains named data files in auxiliary memory.
The operating system keeps a directory showing where each file is stored
in auxiliary memory, so users can refer to files by their names and leave it
up to the operating system to find them.
The system manages the flow of data from input devices and to output
devices. The operating system can handle input and output devices in the
same way that it does files in auxiliary memory. Thus, a program can be
written without regard to whether its input, say, will come from and input
device such as a card reader or from a file stored on tape or disk.
The system maintains security by making sure that programs and data
files used only by those who are authorized to do so. Computer security
are
becomes more important all the time as more and more personal and finan-
cial data is stored in computer systems.
The system keeps an account of the computer system resources that each
person uses, such as how long that person's jobs occupy the central pro-
62 3 Computer Software
cessor or how much data that person has stored in auxiliary memory. Each
user can then be billed for those resources.
The system arranges for more than one program to execute at the same
time and for these programs to share the system's resources. We will dis-
cuss this function in more detail later in the chapter.
Of course, not all of these functions are appropriate for every com-
puter system. Such functions as accounting and security are essential for a
computer system having many users but would be out of place on a small
system used by a single person.
FIGURE 3-3. A machine structured into levels. The bottom level is the physical machine.
Every other level is a virtual machine realized by means of a program that is executed by the
(Physical machine
only level visible to users. For this reason, we can picture a multilevel
machine as an onion, as shown in Figure 3-3. The top-level machine is on
the outside for all to see. The bottom-level physical machine is hidden
away deep down in the center of the onion.
Figure 3-4 shows the level structure of a modern computer system.
The machine-language level is the one we discussed in Chapter 2. Each of
the other levels has been discussed, or at least mentioned, in this chapter.
For most computers these levels aren't impassable barriers. That is
users can write their own programs, even in machine language if desired.
Some computers even allow users to write microprograms for the bottom-
level physical machine, thus redefining the computer's instruction set. A
level that allows access to the levels below it is said to be transparent.
3.4 Processes
Applications software;
Applications programs
user written programs
Systems software;
Programming languages
sometimes firmware
Systems software; sometimes
Operating system firmware or combination of
software and firmware
The data the program is processing. This data may be in the central pro-
cessor's registers, inmain memory, or in auxiliary memory. If this data
were lost, it would be as if you were in the middle of working a problem
out on the blackboard, and while you were out of the room for a moment,
somebody erased the board.
The address of the next instruction to he executed. This is what keeps
the central processor's place in the program being executed. Since this ad-
dress "points out" the next instruction to be executed, it is often referred
to as the pointer to the next instruction. When a program is actually being
executed, the pointer to the next instruction resides in the central proces-
sor's instruction-address register.
These three components — program, data, and pointer to the next in-
struction — make up a process. Figure 3-5 illustrates the three components
of a process.
The most important property of a process is that its execution may be
stopped at any time and, when restarted later, will proceed exactly as if
nothing had happened. The components of a process that occupy main
memory and the central processor's registers do not have to remain there
while execution is halted. They could be moved to auxiliary memory, for
instance. As long as all three components are restored before execution
resumes, execution will proceed exactly as if it had not been interrupted.
We say that a process is active when it is actually being executed and
inactive otherwise. The components of an active process reside in the cen-
tral processor's registers, in main memory, and perhaps partially in aux-
iliary memory. An inactive process may reside anywhere, but it will usu-
ally be found in either main or auxiliary memory.
A process consists of a program being executed by a machine, and we
already know that this combination defines a new virtual machine. Indeed,
a process has many features reminiscent of a machine or even a living or-
ganism. A process leads an independent existence, interacting with users
through input and output devices or exchanging messages with other pro-
cesses. A process can even create offspring, which will carry out their as-
signed tasks and report back to the parent process. With tongue only
slightly in cheek, people have referred to a process as "an organism that
lives in a computer system."
3.4 Processes 67
Pointer to
next instruction
Program
Next instruction
Data
FIGURE 3-5. The three components of a process: the program, the data it is processing, and
a pointer to the next instruction to be executed.
one process can be active at a time. But there may be many inactive pro-
cesses present in main and auxiliary memory. We can arrange for the cen-
tral processor to switch from one process to another in round-robin fash-
ion, executing a few hundred instructions of one process, then a few
hundred instructions of the next, and so on until each process has had its
turn at the central processor. Almost all large computer systems, and many
small ones, use this principle in one form or another.
If we don't look too closely at what is going on, it will seem that all
the processes are being executed simultaneously. Only when we investigate
the fine details do we notice that the central processor is actually being
switched from one process to the next. Usually, we find it more informa-
68 3 Computer Software
tion that caused the interrupt, it determines whether to reactivate the pro-
cess that was suspended by the interrupt or whether to activate some other
process.
chosen depending very much on the nature of the system and the uses for
which it is intended.
Since peripheral devices are mechanical rather than electronic, they
operate much more slowly than the central processor. It would be very
wasteful to have the central processor stand idle while a process was wait-
ing for a peripheral device to complete its work. Instead, while one process
is waiting on a peripheral, the central processor should be working on
another process.
For this reason, users' processes aren't allowed to control peripheral
devices directly. Requests for input, output, and access to auxiliary mem-
ory must be channeled through the operating system.
When the operating system receives a request for a peripheral device,
it directs the device to initiate the requested operation. At the same time,
it removes the process making the request from those waiting in line for
their turns at the central processor. As long as the process is waiting on the
peripheral device, it loses its turns at the central processor.
When the peripheral device has completed the requested operation, it
notifies the operating system via an interrupt. The operating system puts
the process that made the request back in line so it can resume taking its
turns at the central processor.
A user should get rapid response to any input. This means that the time
quanta must be short, so that each process will be activated frequently
enough to be able to respond to user input without excessive delay.
far more processes present than can be accommodated
There are usually
in main memory. Combined with the requirement for frequent activation,
this means that processes, or parts of them, are constantly being moved
back and forth between main and auxiliary memory.
@\^7 (Qj[U]@g^0(o
2. What is a translator?
3. What is an interpreter?
6. Give three sources from which the operating system can accept com-
mands.
19. What is time sharing? What special features of time sharing distinguish
it from other forms of multiprogramming?
20. What kinds of challengesdo recent hardware advances and likely fu-
ture ones pose for computer science?
[M^TTOS)
ALGORITHMS/
AND
PROGRAMS ITnn"
'
©\sm\^®w Q
1
1 FfT
—
Values and t—'
Expressions i
We now turn to the main object of this book, learning how to construct
algorithms and write computer programs.
An algorithm or program must be written in some language. The ques-
tion of what languages we shall use for this purpose is of first importance.
Languages. What language should we use for our algorithms? From the dis-
cussion in Chapter 3, it might seem that one of the higher level program-
ming languages would be most suitable. But practical higher level lan-
guages suffer from several drawbacks:
75
—
system. The user is not allowed to invent new language features, no matter
how desirable they might be for expressing the solution to a particular
problem.
Programming languages that avoid one or more of these problems have
been devised, but they are not the most widely used or readily available
languages. Some, for instance, will execute only on very large computers.
Because of these drawbacks, we will create our algorithms not in a
computer programming language but in an informal algorithmic language.
The name algorithmic notation, reminiscent of mathematical or chemical
notation, might be more suggestive of its informality and its human orien-
tation. The algorithmic language is for thinking about algorithms. It is for
scribbling on the backs of envelopes, not for typing in at computer termi-
nals or punching on computer cards.
Once we have created an algorithm we will find it straightforward to
translate the algorithm into whatever programming language happens to be
available.
Traditionally, flowcharts have been used as an informal notation for
algorithms. For complicated algorithms, however, flowcharts become in-
tricate and mazelike, hard to draw and hard to follow. For this reason
flowcharts are not emphasized as much now as they once were.
Provided they do not become too complex, however, flowcharts can
give an overview of an algorithm at a single glance. Also, since flowcharts
are still widely used in the data processing industry, the student should
be familiar with them. For these reasons, many of the algorithms in this
book are with flowcharts. Your instructor may wish you to draw
illustrated
a flowchart or two to become familiar with them. But in general you are
not expected to draw flowcharts for the algorithms you create, or to think
in terms of flowcharts when you create an algorithm.
To get our algorithms executed by a computer we must first convert
them from the algorithmic language to one of the standard programming
languages. This book contains a supplement showing how to translate al-
gorithms into the Pascal programming language. The supplement gives Pas-
cal translations for a number of the algorithms we will study in the main
text.
operations we might wish to carry out on it. For instance, numbers are one
—
type of data, and strings of alphabetic characters say, people's names
are another. For numbers we probably want to carry out the usual opera-
tions of arithmetic —
addition, subtraction, multiplication, and division.
We are more likely to be interested in putting people's names in alphabet-
ical order, however, or joining together first, middle, and last names to
form full names. Since these operations are drastically different, we con-
sider numbers and character strings to be different data types.
4.1 Data Types and Values 77
Real Numbers. Numbers are certainly one thing we want to be able to pro-
cess with our algorithms, so we will need a data type consisting of num-
bers. More specifically, the data type will consist of the kind of numbers
mathematicians call real numbers.
For any data type, the data items that belong to it are said to be values
of that type. Thus, 100 and 3.1416 are values of type real number. We will
define a data type informally by illustrating its possible values. We now do
this with the real numbers —
that is, the values of type real number.
The real numbers include the nonnegath'e integers 0, 1, 2, 3, and so
on. Thus,
25 540 87 1000000
3.5E4
The number following the E is called the exponent. If the exponent is pos-
itive, it indicates the number of places the decimal point should be moved
to the right. When moving the decimal point, we supply extra zeros as
necessary. Thus, 3.5E4 is equivalent to
35000.
or simply,
35000
ABCDEFGHIJKLMNOPQRSTUVWXYZ
The digits:
0123456789
Punctuation marks and special signs:
! (a # $ % & * ( )_- + = : ; ,
.?/" and others
•GOOD MORNING'
'3.1416'
'!$%#&(§ !0'
'
'
(one blank space)
• '
(the null string, which contains no
characters at all)
ory is treated just like any other coded character. Thus, all of the following
strings are different:
'
null string
'
'
but the string '315', never. In the same way, OUTPUT is a word having a
specific meaning in the language, but 'OUTPUT' is just another string.
OUTPUT 3. 1416
3.1416
and
When an OUTPUT statement contains more than one data item, the
items are printed one after another on the same line. Thus,
OUTPUT 1,2,3,4,5
prints
. '
12 3 4 5
and
prints
OUTPUT 'HELLO.
OUTPUT 'HOW ARE YOU?'
OUTPUT 'CAN I HELP YOU?'
would print
HELLO
HOW ARE YOU?
CAN I HELP YOU?
+ addition
- subtraction
* multiplication
/ division
** exponentiation
est thing to a multiplication sign that can be found on most computer print-
ers. A slash, /, stands for division; the other division sign, *• is also
,
Expression Valu
3+4 7
6-5 1
3*7 21
3/2 1.5
4**3 64
would print
7 1 21 1.5 64
Note that
would print
3**4 = 81
since '3**4 =' is not an expression, but just a character string. It is not
evaluated but just printed as is.
2 + 3*4
3-4/7**3*5 + 2
2-3*4
2-3*4 =
5*4 =
20
2-3*4 =
2 + 12 =
14
Operators with higher priority are applied before those with lower priority.
Operators with the same priority are applied in left-to-right order as they
occur in the expression.
The following table gives the priorities of the arithmetic operators:
** highest priority
* and /
+ and - lowest priority
Operators on the same line (such as - and - have the same priority. )
Example 1:
2-3*4 =
2+12 = Multiplication first ...
14 ... then addition.
Example 2:
2*3**4 =
2*81 = Exponentiation first . .
Example 3:
4-3**2 =
4-9 = Exponentiation first
13 . then addition.
. .
Example 4:
2-3*5**2
2-3*25 = Exponentiation first . .
Example 5:
3-4-2 =
7-2 = Addition first . . .
Example 6:
12/4*3 =
3*3 = Division first . .
12 12
= 1
4*3 12
Example 7:
(2-3)*4 =
5*4 = Parentheses first . .
Example 8:
(4-3)**2 =
7**2 = Parentheses first . .
Example 9:
((2 + 3)*4)**2 =
(5*4)**2 = Inner parentheses first ...
20**2 = ... then next outer ones . .
4.5 Functions
Not all operations are represented by signs, at least by signs that are avail-
able on computer printers and display devices.
Consider the absolute value operation, which leaves a positive num-
ber unchanged but changes a negative number into the corresponding pos-
itive one. We can indicate this operation as follows:
ABS(5) = 5
ABS( -5) =5
ABS(3.1416) = 3.1416
ABS( -3.1416) = 3.1416
expression whose value is the result of applying the function to its argu-
ment.
The argument of the function may itself be an expression. Since the
argument is in parentheses, it is evaluated before applying the function:
Example 10:
ABS (5 -6*3) =
ABS(5-18) =
ABS (-13) =
13
Example 11:
3 + 2*ABS(7-50) =
3+ 2*ABS(-43) =
3 + 2*43 =
3+86 =
89
would print
5 5 13 89
INT. The INT function discards the fractional part of a number the part —
to the right of the decimal point —
and retains only the integer part:
INT(3.1416) = 3
INT (25) - 25
INT (4. 75) = 4
INT( -3.1416) = -3
INT(-4.75) = -4
SQRT. The SQRT function yields the square root of its argument:
SQRT(25) = 5
SQRT(9) = 3
SQRT (2. 25) = 1.5
ALGORITHM algorithm-name
statements of algorithm
END algorithm-name
For example,
ALGORITHM EXPRESSIONS
OUTPUT '3 + 5 = 3+5 '
,
3+5 = 8
3-5 = -2
3*5 = 15
3/5 = 0.6
SQRT(1.69) = 1.3
In this book, algorithms are printed using all capital letters for easy
readability and to make them stand out from the surrounding text. This is
not necessarily the best way to write out algorithms by hand. A good form
for handwritten algorithms is to and underline key-
use lowercase letters
words such as ALGORITHM, END, and OUTPUT, make them stand
to
out. Figure 4-1 shows the greatest-common-divisor algorithm from Chapter
1 handwritten in this form.
FIGURE 4-1. A convenient handwritten form for the algorithmic language. Underlining the
keywords is optional.
s64*€t
C^®WD®M (5}aO®©£D®Di£
5. What is a value?
10. Any character that indicates the beginning or end of a particular con-
struction is called a delimiter. What is the delimiter for character strings?
12. Name two data types whose values can be printed by an OUTPUT
statement.
13. Name the five arithmetic operators introduced in this chapter, and give
the sign for each.
14. What does the simplest possible arithmetic expression consist of?
15. Explain the use of priorities to determine the order in which operators
are applied in arithmetic expressions.
OUTPUT 3.1416
***
*****
*******
*********
***********
***
***************
H
Variables, a
Assignment, and
Input
In the last chapter we saw how to instruct a computer to carry out arith-
metic calculations. But all we could do with the results was to print them
out. We did not provide for a scratch pad, a means of saving the result of
one calculation to be used in a later one. In this chapter we will remedy
that deficiency.
calculations for use in later ones and recall the results of previous calcula-
tions for use in the current one. These are the kinds of things you or I
would do using a piece of scratch paper, a blackboard, or (these days) a
calculator with a built-in memory.
A computer uses its main memory. We can think of this as being di-
vided up into many individual memory locations. Each location can hold
precisely one real number or string. We can think of the memory as a vast
array of post office boxes or pigeonholes, each holding a single data value.
(The memory locations described here do not necessarily correspond
one-to-one with the hardware locations described in Chapter 2. On some
computers, for instance, a real number may occupy two or four hardware
memory locations. A string almost always occupies more than one hard-
ware memory location. The correspondence between hardware locations
90
5.1 Names, Locations, and Variables 91
tion to help us remember the kind of data that is stored in it. In an algo-
rithm to compute a payroll, for instance, the location named HOURS
WORKED might contain the number of hours a worker put in during a
given week, while the one named HOURLY RATE could hold the amount
the worker earns each hour.
As a rule, we can make up whatever names we please for memory
locations. To prevent names from being confused with other elements of
the language, however, we impose a few minor restrictions on their con-
struction. Names may contain only letters, digits, and the underline char-
acter A name must start with a letter. Thus,
.
are not.
Instead of spaces or hyphens, which are not used in names, we use
the underline character:
EMPLOYEE-NAME 1
MARY JONES
HOURS -WORKED 40
HOURLY_RATE 3.25
I
GROSS-WAGES 130
Variable-Value List
Variable Value
EMPLOYEE-NAME 'MARY JONES
HOURS -WORKED 40
HOURLY-RATE 3.25
GROSS-WAGES 130
FIGURE 5-1. Two equivalent ways of visualizing a computer's memory: at top, named mem-
ory locations and their contents; at bottom, variables and their values.
longer but more precise "the value of HOURLY RATE is greater than
zero."
5.2 Assignment
The Assignment Operator. One of the simplest operations a computer can
carry out is to store a certain value in a certain memory location. Now the
memory location is and the value of the variable is the value
a variable,
stored in the location. The effect of storing a new value in the location,
then, is to assign a new value to the variable. For this reason, the opera-
tion of storing a value in a location is called assignment.
We indicate the assignment with the assignment operator, <— To the .
sion. The value of the expression on the right is stored in the location
named on the left (or, the value of the expression on the right is assigned
to the variable on the left). Thus,
HOURS-WORKED 45
HOURLY_RATE 4.25
HOURS .WORKED 41
[Link] 5.15
94 5 Variables, Assignment, and Input
FIRST_L0CATI0N 50
SEC0ND_L0CATI0N 75
FIRST_L0CATI0N 50
SEC0ND_L0CATI0N 50
FIGURE 5-3. Copying data from one memory location into another.
Effect of assignment:
SEC0ND_L0CATI0N «- FIRST_L0CATI0N
FIRST_L0CATI0N @
SEC0ND_L0CATI0N ft
\ 50
. .
5.3 Expressions 95
SEC0ND_L0CATI0N FIRST_LOCATION
SECOND LOCATION 50 Dereference
FIRST_LOCATION
Assign 50 to
SECOND LOCATION
5.3 Expressions
When we defined assignment, we said that an expression could appear on
the right-hand side of the assignment operator. So far, we have examined
two special cases in which the expression was (1) a value and (2) a vari-
able. Now let's turn to assignments involving more complicated expres-
sions.
The expression is always evaluated before making the assignment. We
can think of the assignment operator as having a lower priority than any
arithmetic operator. Thus,
AREA 8*5
is processed as follows:
AREA 8*5
AREA 40 Evaluate expression
Assign 40 to AREA.
FIRST_L0CATI0N l^®
SEC0ND_L0CAT£tfN fo 50
Dereferencing
A 5
B 10
C 15
D 20
D «- A~B*C
as follows:
D «- A-B*C
D <— 5*10*15 Dereference variables on right side ...
D <— 5-150 . multiplication next
. . . . .
A 5
B 10
C 15
D 155
A <- A + l
we have
A «- A + l
A <— 5 + 1 Dereference A ...
A <— 6 ... do addition . .
. and assign 6 to
. . A.
¥ D *- A + B*C
1
W D <- 5 + 10*15
i_J
M D «- 5 + 150
FIGURE 5-5. An assignment statement containing an expression on the right hand side spec-
ifies (a) a calculation to be carried out, (b) the memory locations containing the data for the
calculation, and (c) the memory location in which the result of the calculation is to be stored.
A 6
B 10
C 15
D 155
FIGURE 5-6. Adding 1 to the contents of a memory location. This operation is frequently
carried out for the purpose of counting; the memory location holds a running count, which
is increased by 1 each time an item is counted.
A+ l
A — 5 +
A<-(?
Replaced by 6
when assignment is
executed
98 5 Variables, Assignment, and Input
LENGTH +- 7
WIDTH «- 5
OUTPUT LENGTH*WIDTH, 2* LENGTH + WIDTH ( )
35 24
LENGTH <- 7
WIDTH «- 5
AREA *- LENGTH*WIDTH
PERIMETER <- 2* LENGTH + WIDTH
( )
The expressions are evaluated the same whetheF they appear in an OUT-
PUT statement or on the right side of an assignment statement.
In the same way, we can define an INPUT statement, which obtains a
value from an input device, such as a card reader or a terminal, and as-
signs the value to a variable.
The word INPUT is followed by a list of variables:
Each variable is assigned a new value, just as if it had appeared on the left
side of an assignment statement. But the value comes from the input de-
vice, and not from the result of evaluating an expression.
An INPUT statement, unlike an OUTPUT statement, can contain only
variables. We cannot use an expression in an INPUT statement any more
than we could use one on the left side of an assignment statement.
Now consider the sequence of statements:
OUTPUT PERIMETER =
' PERIMETER ' ,
4, 3
Then, after the INPUT statement has been executed, we will have the var-
iable-value list:
LENGTH 4
WIDTH 3
5.5 Three Examples 99
AREA
PERIMETER
where the dashes indicate that AREA and PERIMETER have not yet been
assigned values. After the two assignment statements have been carried
out. we get the variable-value list:
LENGTH 4
WIDTH 3
AREA 12
PERIMETER 14
AREA = 12
PERIMETER = 14
Units Conversion. This algorithm inputs a length in feet and inches and
converts it to centimeters:
ALGORITHM CONVERT
INPUT FEET, INCHES
TOTAL_INCHES «- 12*FEET + INCHES
CENTIMETERS «- 2 54*T0TAL_INCHES
.
6, 4
6 FEET 4 INCHES -
193.04 CENTIMETERS
ALGORITHM WAGES
INPUT NAME, HOURS, RATE (Get data)
) .
( „ 1
TOTAL INCHES «-
12*FEET - INCHES
I I
CENTIMETERS *-
2.54*T0TAL_INCHES
/
OUTPUT FEET, 'FEET'
'INCHES =' /
/
r OUTPUT CENTIMETERS.
•CENTIMETERS' /
/
i
( - )
f START
J
7
// INPUT NAME, j
1 HOURS, RATE /
/
1!
GROSS WAGES
*- HOURS*RATE
1!
7
/ OUTPUT 'NAME: '
. 1
'
NAME /
/
1
OUTPUT 'PAY: 7
/ ' ,
/
/ GROSS WAGES /
I
1
( STOP )
ALGORITHM PURCHASE
(Input list price, discount rate, and tax rate)
102 5 Variables, Assignment, and Input
( START )
/ INPUT PRICE. /
/ DISC0UNT_RATE. TAX_RATE /
DISCOUNT «- PRICE
*DISCOUNT_RATE
'
PRICE «-
PRICE-DISCOUNT
TAX «-
PRICE*TAX_RATE
PRICE *-
PRICE + TAX
f STOP
J
'
(Compute discount)
(Subtract discount from price)
(Compute tax)
(Add tax to price)
(Output price)
END PURCHASE
Review Questions 103
ALGORITHM PURCHASE
(Input list price, discount rate, and tax rate)
INPUT PRICE, DISCOUNT_RATE, TAX_RATE
(Compute discount)
DISCOUNT «- PRICE*DISCOUNT_RATE
(Subtract discount from price)
PRICE «- PRICE-DISCOUNT
(Compute tax)
TAX <- PRICE*TAX_RATE
(Add tax to price)
PRICE <- PRICE + TAX
(Output price)
OUTPUT 'PLEASE PAY', PRICE, 'DOLLARS'
END PURCHASE
The comments may then be omitted if they are not needed to explain the
algorithm:
ALGORITHM PURCHASE
INPUT PRICE, DISCOUNT_RATE, TAX_RATE
DISCOUNT <- PRICE*DISCOUNT_RATE
PRICE <- PRICE-DISCOUNT
TAX <- PRICE*TAX_RATE
PRICE «- PRICE + TAX
OUTPUT 'PLEASE PAY', PRICE, 'DOLLARS'
END PURCHASE
9. What is dereferencing?
10. Is dereferencing ever applied to the variable on the left side of an as-
signment statement?
11. Describe the action carried out by an assignment statement when there
is a single value to the right of the assignment operator.
12. Describe the actions carried out by an assignment statement when there
is a single variable to the right of the assignment operator.
13. Describe the actions carried out by an assignment statement when there
is an arithmetic expression to the right of the assignment operator.
14. Illustrate with diagrams what happens when the following statement is
executed:
17. What are comments or remarks? How are they written in the algo-
rithmic language?
18. Languages vary tremendously in the clarity with which they can ex-
press an algorithm. For what kinds of languages are comments most nec-
essary?
19. Explain how a judicious choice of variable names can eliminate the
need for some comments.
20. Explain how comments can be used to outline an algorithm before fill-
J "_\ r
;
--
A 10
B 20
C 30
D 40
A <- D
D «- B
B <- C
C «- D
1
2
3
D <- C
C <- B
B <- A
INPUT A
D <- C
C «- B
INPUT B
D <- C
INPUT C
A <- B
B <- C
and
B «- C
A «- B
have the same effect? Comment on whether or not we can interchange the
order of assignment statements without changing their effect.
contents of —
A and B. (Hint: Another location say, T will be needed for—
temporary storage.)
106 5 Variables, Assignment, and Input
C = 1{F - 32)
diagonal.
per item, and the sales tax rate and to output the amount the customer
must pay.
10. One can check an automobile speedometer for accuracy by noting the
time required to travel a "measured mile" while maintaining a certain in-
dicated speed. Write an algorithm that will input the time, in minutes and
seconds, required to travel between two milestones, and output the speed
the car was traveling.
12. The diameter of a circular pool and the depth to which it is filled are
both given. Write an algorithm to calculate how many liters of water are
needed to fill the pool to the specified depth. The diameter and depth are
given in meters.
We can calculate the volume of water needed as follows:
2
, 3.14 x depth x diameter
volume = •
This formula gives the volume in cubic meters. Each cubic meter contains
1000 liters, so
13. The length of a rectangular object is its longest dimension; the girth of
the object is the distance around it, measured perpendicular to the length.
The combination Jength-pJus-girth occurs in postal regulations; for in-
stance, a package cannot be sent by first class mail if its length-plus-girth
exceeds 100 inches. Write an algorithm to input the length, width, and
height of a package and print its length-plus-girth.
14. A bank account pays interest at the rate of i percent each year, com-
pounded monthly. Let a be the amount currently in the account,and sup-
Exercises 107
pose that no further deposits are made. After n months, the amount c cur-
rently in the account is given Dy
n
c = a(l + r)
i
r =
1200
15. Suppose the situation is the same as for Exercise 14 except that an
amount d is deposited in the account at the beginning of each month. With
this change, the formula for the amount currently in the account becomes:
= d (! + ~
r) 1
c ^ 1 + r) ^ a(1 + r)»
r
©\sm\oftm
— p
Selection
—^
i
^
6.1 Conditions
INPUT P, Q
R *- FALSE
OUTPUT Q, P, R
108
.
If the input is
TRUE, FALSE
relation holds, the value yielded is TRUE. Otherwise, the value is FALSE.
The following relational operators apply to real numbers:
= is equal to
^ is not equal to
< is less than
> is greater than
«£ is less than or equal to
5* is greater than or equal to
The result of applying one of these operators to two real numbers will
be TRUE or FALSE, depending on whether or not the corresponding rela-
tion holds:
Expression Value
3 = 5 FALSE
2^3 TRUE
5^5 TRUE
4^4 FALSE
7 < 7. 5 TRUE
14 > 3. 1416 FALSE
9-3*2 > 5
9-6 > 5 Multiplication first ...
3 > 5 ... then subtraction . .
110 6 Selection
2**3 + 1 = 3**2
8+1 = 9 Exponentiations first ...
9=9 ... then addition . .
= is equal to
^ is not equal to
< precedes in alphabetical order
> follows in alphabetical order
< precedes or is equal to
25 follows or is equal to
Thus:
Expression Value
'BILL' < 'JACK' TRUE
'TOM' < 'DICK' FALSE
'LARRY' 55 'JANE' TRUE
'TOM' =£ 'TOD' FALSE
FALSE. If one string forms the initial part of another, then the shorter one
precedes the longer. Thus 'JACK' < 'JACKSON' is TRUE.
IF condition THEN
statements
END IF
Ifthe condition is TRUE, then the statements between IF and END IF are
executed, after which execution continues with the statement following
END IF. If the condition is FALSE, the statements between IF and END IF
) )
are skipped, and execution continues immediately with the statement fol-
lowing END IF.
Example 1:
ALGORITHM WAGES
(Input data)
(Compute GR0SS_WAGES without extra pay for
overtime
IF HOURS > 40 THEN
(Compute extra pay for overtime)
(Add extra pay for overtime to GR0SS_WAGES
END IF
(Output results)
END WAGES
ALGORITHM WAGES
INPUT NAME, HOURS, RATE
GR0SS_WAGES *- H0URS*RATE
IF HOURS > 40 THEN
EXTRA_F0R_0VERTIME <- 5* (H0URS-40 *RATE .
)
' , GR0SS_WAGES
END WAGES
If the value of HOURS not greater than 40, then the statements be-
is
tween IF and END IF will be skipped. But if the value of HOURS is greater
than 40, then the 50% extra for the overtime hours is computed and added
to GROSS_WAGES. Note that if the IF and END IF statements were omit-
ted, then the algorithm would impose a 50% penalty for each hour less
—
than 40 that was worked obviously not what was intended.
Figure 6-1 shows the flowchart version of the IF construction.
The decision symbol corresponds to the "IF condition THEN," and the
collector circle corresponds to the "END IF." The two branches that leave
the decision symbol rejoin at the collector circle. This corresponds to the
fact that we always end up at the statement following the END IF, whether
the condition is TRUE or FALSE.
2
112 6 Selection
The ELSE Statement (Two-Way Selection). With IF and END IF, we can
cause a group of statements to be either executed or not executed, depend-
ing on whether a condition is TRUE or FALSE. By adding the ELSE state-
ment, we can select one group of statements for execution when the con-
dition is TRUE, and another when it is FALSE. Here is the construction:
IF condition THEN
statements- 1
ELSE
statements-
END IF
Example 2:
The following algorithm inputs two strings and outputs them in alphabeti-
cal order:
ALGORITHM ALPHABETIZE
INPUT FIRST, SECOND
IF FIRST s£ SECOND
OUTPUT FIRST, SECOND
6.2 One- and Two-Way Selection 113
EXTRA «- 0.5*(H0URS-40)*RATE
GROSS «- GROSS + EXTRA
( STOP
J
ELSE
OUTPUT SECOND, FIRST
END IF
END ALPHABETIZE
'TOM', 'DICK'
FALSE TR'JE
statements-2 statements-1
DICK TOM
If the input is
'JACK', 'JOE'
JACK JOE
Example 3:
STOP
IF condition-1 THEN
IF condition-2 THEN
statements-1
ELSE
statements-2
END IF
ELSE
FALSE TRUE statements-3
END IF
FALSE TRUE
to ALGORITHM and END. And we will find still more uses for indentation
as we go further. In every case, the purpose of indentation is to render the
structure of an algorithm visible at a glance.
programming languages, indentation is optional. In the algo-
In most
rithmic language, however, it is required. The object of the algorithmic
IF condition-1 THEN
statements-1
ELSE IF condition-2 THEN
statements-2
ELSE IF condition-3 THEN
statements-3
ELSE
statements—4
END IF
tions are TRUE, then all the groups of statements are skipped and execu-
tion continues with the statement following END IF.
Example 4:
The algorithm letter grade in Figure 6-7 inputs a numerical grade and out-
puts the corresponding letter grade, using the following scale:
A 90-100
B 80-89
C 70-79
D 60-69
F below 60
The fact that the conditions are tested in top-to-bottom order is essential to
the correct functioning of this algorithm. If. for instance. NUMBER
GRADE s* 60 were tested first, then anyone making 60 or over would get
a D, which is certainly not what is intended.
Figure 6-8 is a flowchart of LETTER_GRADE.
TRUE
statements-1
TRUE
statements-2
TRUE
statements-3
FALSE
statements-4
TRUE
OUTPUT 'A
TRUF
NGRADE 2* 80 > *~t OUTPUT '
TRUE
^ -
TRUE *
>
FALSE
OUTPUT 'F'
STOP
120 6 Selection
CASE SWITCH OF
1:
statements-1
2:
statements-2
3:
statements-3
ELSE
statements-4
END CASE
cases, then the entire CASE construction is skipped, and execution con-
tinues with the statement following END CASE.
Figure 6-9 shows the flowchart of the CASE construction. Again we
have more than two branches coming together at a collector circle, a sure
sign of multiway selection.
Example 5:
The LETTER_GRADE algorithm can be rewritten to use the CASE con-
struction with the help of the following expression
100 5
90-99 4
80-89 3
70-79 2
60-69 1
0-59 or negative
SWITCH ==
1
statements-1
SWITCH == 2
statements-2
SWITCH -= 3
statements-3
ELSE
statements-4
The logical operators OR, AND, and NOT correspond directly to these
English connectives. We use them to form expressions such as
A < B AND C = 25
The value of A is less than the value of B, and the value of C equals 25.
The expression
P OR Q
122 6 Selection
CASE RANGE OF
1:
OUTPUT 'D'
OUTPUT 'C
OUTPUT '
B'
OUTPUT 'A*
OUTPUT 'A'
ELSE
OUTPUT 'F'
END CASE
END LETTER GRADE
is TRUE if P is TRUE or Q is TRUE or both are true. Since the only possible
values of P and Q are TRUE and FALSE, we can list every possible case of
the expression P OR Q:
Expression Value
FALSE OR FALSE FALSE
FALSE OR TRUE TRUE
TRUE OR FALSE TRUE
TRUE OR TRUE TRUE
The expression
P AND Q
is TRUE if and only if both P and Q are TRUE. Again we can write out all
possible cases:
Expression Value
FALSE AND FALSE FALSE
FALSE AND TRUE FALSE
TRUE AND FALSE FALSE
TRUE AND TRUE TRUE
The expression
NOT P
INPUT NGRADE
R = 1
OUTPUT 'D'
R = 2
OUTPUT '
C
R = 3
OUTPUT '
B'
R = 4
OUTPUT 'A'
R = 5
OUTPUT 'A'
ELSE
OUTPUT 'F'
( STOP
J
FIGURE 6-11. Flowchart of the algorithm LETTER_GRADE using the CASE construction.
123
124 6 Selection
Expression Value
NOT TRUE FALSE
NOT FALSE TRUE
The logical operators have lower priorities than either the relational or
arithmetic operators. This means that in a general logical expression,
Example 6:
is clearer than
Thus,
is evaluated
As before, parentheses can save much head scratching over the original
expression:
Review Questions 125
4. The symbols TRUE and FALSE denote the two possible logical values.
Give some examples of similar value denotations for other data types.
5. Distinguish between TRUE and FALSE on one hand and 'TRUE' and
'FALSE' on the other.
6. Give the six relational operators that apply to real numbers and the
relation corresponding to each.
11. Give the form of the IF construction that causes one of two alternative
groups of statements to be executed.
15. When more than two branches come together at a collector circle, this
is a sure sign of what?
126 6 Selection
18. Defineeach of the logical operators by giving a table showing the value
of the expressionformed with that operator for every possible value of its
operands. Why could this technique not be used for defining the operators
on real numbers?
19. What are the relative priorities of (a) the logical operators, (b) the re-
lational operators, and (c) the arithmetic operators?
nz%?'z:£%*
In Exercises 1,2, and 3, assume the following variable-value list
1. Evaluate:
(a) NOT Q
(b) P OR Q
(c) P AND Q
(d) P AND Q OR R
(e) (B > A) AND (B > C)
(f) (B > A) OR (B > C)
(g) NOT (A = B) OR (A = C)
( )
i
Exercises 127
HOURS*RATE
40*RATE + 1.5*(H0URS-40)*RATE
(for hours at regular rate) (for hours at overtime rate
7. Write an algorithm to input two numbers and output the smaller of the
two. The algorithm should use only one OUTPUT statement.
10. Write an algorithm that inputs the length, width, and height of a box
as well as the diameter and height of a cylindrical jar. The algorithm
should print whether or not the jar will fit inside the box. The jar can sit
upright in the box, or it can lie on its side with its top parallel to one of
the sides of the box.
11. A is equilateral if all three sides have the same length, isos-
triangle
celes only two of its sides have the same length, and scalene if no two
if
sides have the same length. Write an algorithm to input the lengths of the
three sides of a triangle and print whether the triangle is equilateral, isos-
celes, or scalene.
12. The cost of a certain item depends on the quantity ordered, as given
by the following table:
0-99 $5.95
100-199 $5.75
200-299 $5.40
300 or more $5.15
128 6 Selection
Write an algorithm to input the quantity ordered and output the total cost
of the order. Use the IF construction.
1 year PROGRAMMING BS
1 year PROGRAMMING MS
1 year ENGINEERING MS
1 year ENGINEERING Ph.D
5 years PROGRAMMING BS
5 years ENGINEERING BS
5 years ENGINEERING MS
5 years ENGINEERING Ph.D
Write an algorithm, using nested IF constructions, to input a person's ex-
perience, field, and degree and to indicate whether or not this company
should consider him or her for hiring.
15. Rewrite the algorithm of Exercise 14 using OR and AND but not nested
IF constructions.
©DnsofpOc^F H
Repetition
All the algorithms we have studied so far have a certain air of triviality
about them. You may well have asked why it was necessary to use a com-
puter to do the things the algorithms were written to accomplish. Would it
not be just as easy to do these things by hand as it would be to program a
computer to do them?
The reason these algorithms seemed was that each instruction
trivial
was used only once. If an instruction is be carried out only once, then
to
it isprobably just as easy to carry it out by hand (perhaps with some aid
such as a calculator) as it is to program a computer to carry it out. If a
computer program is to justify its existence, some of the instructions must
be executed repeatedly.
Of course, this repetition can come about because the entire program
is executed more than once. But more commonly some instructions will be
129
130 7 Repetition
WHILE condition DO
statements
END WHILE
the condition is FALSE when the computer first arrives at the WHILE state-
ment. This is a distinguishing feature of the WHILE construction.
Notice that in Figure 7-1 the flowchart of the repetition forms a loop.
As a result, programmers often use the word "loop" interchangeably with
"repetition."
FIGURE 7-1. Flowchart for the WHILE construction. Notice that the condition is tested before
any of the statements are executed.
FALSE
TRUE
statements
7.1 The WHILE Construction 131
ALGORITHM AVERAGE
SUM «-
COUNT «-
INPUT NUMBER
WHILE NUMBER ^ DO
SUM «- SUM + NUMBER
COUNT <- COUNT -rl
INPUT NUMBER
END WHILE
IF COUNT > THEN
OUTPUT SUM/COUNT
ELSE
OUTPUT 'NO NUMBERS WERE ENTERED'
END IF
END AVERAGE
number to indicate the end of the sequence. (A data value used to signal
the end of a sequence is called a sentinel.)
A possible sequence might be
1
2
3
-1
1 +2+3
= 2
3
We will use SUM and COUNT to keep a running total and a running
count of the data values inputted. Every time we input a new NUMBER,
we will update SUM and COUNT as follows:
When all the values have been inputted, the average is calculated as
SUM/COUNT.
Figure 7-3 shows the flowchart for AVERAGE.
Notice that we input the first value before starting the repetition. Each
succeeding value is inputted after the preceding one has been processed.
The purpose of arranging things in this way is so that the sentinel will not
be processed as if it were a valid data value. Immediately after a value is
inputted, before any processing of it is done, it must be checked to see if
it is the sentinel. In Figure 7-3, note that after each INPUT NUMBER state-
ment is executed the computer goes directly to the decision diamond that
checks whether the value just inputted is the sentinel. If it is, the repeti-
tion terminates, and the value just inputted is not processed.
132 7 Repetition
( START
J
SUM «-
COUNT *-
FALSE
INPUT NUMBER
FALSE
^COUNT > <N TRUE
OUTPUT 'NO
NUMBERS ENTERED' OUTPUT SUM/COUNT
f STOP
J
REPEAT
statements
UNTIL condition
FIGURE 7-4. Flowchart for the REPEAT construction. Notice that the statements are executed
before the condition is tested. Because of this, the statements are always executed at least one
time even if the condition is initially true.
(S
V
statements
FALSE
<^condi tion^>
trueT
—
134 7 Repetition
ALGORITHM BONUS
REPEAT
INPUT NAME, SALES
UNTIL SALES > 10000
OUTPUT 'THE BONUS GOES TO', NAME
END BONUS
FALSE
7.3 Iteration 135
7.3. Iteration
FOR I «- 1 TO 5 BY 1 DO
statements
END FOR
The statements will be executed five times. The first time, I will have the
value 1; the second time, I will have the value 2; and
the third, fourth,
fifth times, I will have the values 3, 4, and 5. The statements can use the
value of I as part of any calculation they do.
This construction is equivalent to
I <- 1
WHILE I > 5 DO
statements
I «- I + 1
END WHILE
FOR I ^ 1 TO 5 BY 1 DO
statements
END FOR
to
FOR I «- 1 TO 5 DO
statements
END FOR
We can use the BY phrase to count by increments other than 1. For in-
stance,
136 7 Repetition
FOR I <- 5 TO 25 BY 5
statements
END FOR
again causes the statements to be executed five times, but now with I tak-
ing the values 5, 10, 15, 20, and 25.
We can even count backwards if we want to:
FOR I ^ 5 TO 1 BY -1 DO
statements
END FOR
Again we get five repetitions, but with I now taking the values 5, 4, 3, 2,
and 1.
Here are three examples of the iterative construction.
Example 2:
Find the sum of all the integers from 1 through 1,000.
ALGORITHM INTEGER_SUM
SUM «-
FOR N <- 1 TO 1000 DO
SUM +- SUM + N
END FOR
OUTPUT SUM
END INTEGER_SUM
Example 3:
Find the sum of all the odd integers from 1 through 999.
ALGORITHM 0DD_INTEGER_SUM
FOR N «- 1 TO 999 BY 2 DO
SUM <- SUM + N
END FOR
OUTPUT SUM
END ODD_INTEGER_SUM
Example 4:
Input a sequence of numbers and find their average. The first number in-
putted gives the number of values to be averaged.
For instance, the input data
3
1
2
3
7.4 Five Algorithms 137
tells the algorithm that there are three values to be averaged, namely, 1,
2, and 3.
ALGORITHM AVERAGE
INPUT COUNT
SUM «-
FOR N <- 1 TO COUNT DO
INPUT NUMBER
SUM ^- SUM + NUMBER
END FOR
OUTPUT SUM/COUNT
END AVERAGE
GRADES. For each student in a class, input name and number grade. The
sentinel a student name of 'END OF DATA'. For each student, output
is
name and letter grade. (Use the grade scale given in Chapter 6.) After all
138 7 Repetition
ALGORITHM PAYROLL
TOTAL «-
INPUT NAME, HOURS, RATE
WHILE NAME ^ "END OF DATA' DO
GROSS_WAGES «- HOURS*RATE
IF HOURS > 40 THEN
GROSS_WAGES «- GROSS_WAGES * 0.5*(H0URS-40)*RATE
END IF
TOTAL «- TOTAL -GROSS_WAGES
OUTPUT NAME, GROSS_WAGES
INPUT NAME, HOURS, RATE
END WHILE
OUTPUT 'TOTAL GROSS WAGES:'. TOTAL
END PAYROLL
students have been processed, output the "grade distribution": the number
of As, the number of Bs, and so on. Figure 7-7 shows the algorithm
GRADES.
GUESS. Now that computers have become popular with hobbyists, there
has been a tremendous upsurge of interest in computer games. Many of
these are quite complex. The algorithm GUESS, Figure 7-9, is a very sim-
ple game in which the player tries to guess a number the computer is
"thinking of." The algorithm uses the function RANDOM, whose value is
a random integer between 1 and its argument. (So the value of
RANDOM(IOO) is a random integer between 1 and 100. The limits 1 and
100 are included in the range.) Since the value is generated by an algo-
rithm, it is not really random, but pseudorandom — seemingly random.
INTEREST. We are given the amount currently in a bank account, the de-
posit made at the beginning of each month, and the yearly interest rate (in
7.4 Five Algorithms 139
ALGORITHM GRADES
A COUNT «-
B COUNT «-
C COUNT «-
D COUNT «-
F COUNT «-
INPUT NAME. NUMBER GRADE
WHILE NAME ? 'END OF DATA' DO
IF NUMBER GRADE & 90 THEN
LETTER GRADE «- 'A'
A COUNT «- A COUNT -1
ELSE IF NUMBER GRADE 5* 80 THEN
LETTER GRADE «- 'B'
B COUNT «- B COUNT + 1
ELSE IF NUMBER GRADE 5= 70 THEN
LETTER GRADE «- 'C
C COUNT «- C COUNT -1
ELSE IF NUMBER GRADE 3= 60 THEN
LETTER GRADE 'D'
D COUNT «- D COUNT +1
ELSE
LETTER GRADE «- F '
F COUNT «- F COUNT + 1
END IF
OUTPUT NAME, LETTER GRADE
INPUT NAME. NUMBER GRADE
END WHILE
OUTPUT 'GRADE DISTRIBUTION'
OUTPUT 'A: A COUNT. 'B:
' . B COUNT. ' , 'C :
' . C_COUNT
OUTPUT 'D: D COUNT. 'F:
' , F _COUNT ' .
END GRADES
ALGORITHM HIGH_AND_LOW
INPUT TEMPERATURE
CURRENT_LOW «- TEMPERATURE
CURRENT_HIGH «- TEMPERATURE
WHILE TEMPERATURE ? - 100 DO
IF TEMPERATURE < CURRENT_LOW THEN
CURRENT_LOW «- TEMPERATURE
ELSE IF TEMPERATURE > CURRENT_HIGH THEN
CURRENT_HIGH «- TEMPERATURE
END IF
INPUT TEMPERATURE
END WHILE
OUTPUT 'LOW:', CURRENT_LOW
OUTPUT 'HIGH:', CURRENT_HIGH
END HIGH AND LOW
140 7 Repetition
ALGORITHM GUESS
OUTPUT 'I AM THINKING OF A NUMBER BETWEEN 1 AND 100'
OUTPUT 'YOU ARE TO TRY TO GUESS THE NUMBER I WILL TELL'
OUTPUT 'YOU WHETHER YOUR GUESS IS RIGHT, OR WHETHER'
OUTPUT 'IT IS TOO LARGE OR TOO SMALL.
REPEAT
NUMBER «- RANDOM! 100)
OUTPUT 'I HAVE MY NUMBER. WHAT IS YOUR GUESS?'
REPEAT
INPUT YOUR_GUESS
IF YOUR_GUESS > NUMBER THEN
OUTPUT 'YOUR GUESS IS TOO LARGE. GUESS AGAIN'
ELSE IF YOUR_GUESS < NUMBER THEN
OUTPUT 'YOUR GUESS IS TOO SMALL. GUESS AGAIN'
END IF
UNTIL YOUR_GUESS = NUMBER
OUTPUT 'YOUR GUESS IS RIGHT'
OUTPUT 'WOULD YOU LIKE TO PLAY AGAIN (YES OR NO)?'
INPUT PLAY_AGAIN
UNTIL PLAY_AGAIN ^ 'YES'
OUTPUT 'I HAVE ENJOYED PLAYING WITH YOU'
END GUESS
amount in the account at the beginning of this month, the amount at the
beginning of next month is calculated by:
The first statement adds to AMOUNT the deposit made at the beginning of
the month. The second adds the interest earned during the month. If we
repeat the calculation for the number of months we are interested in, we
amount in the account
will obtain the after that many months. Figure 7-10
shows the algorithm INTEREST.
[^WD(§\^7 ©Qfl@©i}D®G^
1. Why must some of the statements in an algorithm be executed more
than once if the algorithm is to justify its existence?
5. Explain why two INPUT statements are needed in the algorithm AV-
ERAGE.
6. Give two differences between the WHILE and REPEAT constructions.
Review Questions 141
ALGORITHM INTEREST
INPUT AMOUNT. DEPOSIT, YEARLY_INTEREST_RATE NUMBER_OF_MONTHS ,
YEARLY_INTEREST_RATE «- YEARLY_INTEREST_RATE/100
MONTHLY_INTEREST_RATE *- YEARLY_INTEREST_RATE/12
FOR N <- 1 TO NUMBER_OF_MONTHS DO
AMOUNT «- AMOUNT + DEPOSIT
AMOUNT «- AMOUNT - MONTHLY_INTEREST_RATE*AMOUNT
END FOR
OUTPUT 'AMOUNT IN ACCOUNT AFTER'. NUMBER_OF_MONTHS
OUTPUT 'MONTHS IS', AMOUNT
END INTEREST
FOR I <- L TO M BY N DO
statements
END FOR
11. In
FOR I <- 3 TO 15 BY 3 DO
FOR I «- 9 TO 1 BY -2 DO
14. What problems would arise from the use of each of the two following
FOR statements?
18. Explain in words the differences in the flowcharts of WHILE and RE-
PEAT.
19. What is a pseudorandom number? What are the possible values of
RANDOM(25)?
20. The algorithm GUESS uses two REPEAT statements. Explain for each
why REPEAT was used instead of WHILE.
~:.v:- i.^
month will be the number of pairs at the beginning of this month plus the
number at the beginning of last month. Since a newborn pair takes a month
to become fertile, only those alive at the beginning of last month can have
offspring during this month. Throughout the calculation, then, you must
keep track of two values: the number of pairs at the beginning of the cur-
rent month and the number at the beginning of the month before that. How
can you express the fact that the original pair is fertile?)
Exercises 143
10. Some banks advertise that they compound interest daily rather than
monthly. Modify INTEREST to compound interest daily.
12. What will the algorithm BONUS do if no salesperson has sales in ex-
cess of $10,000? Modify the algorithm to output an appropriate message in
this case. (Hint: The easiest solution is to use a sentinel consisting of a
particular name and a particular sales.)
13. Write an algorithm to input a series of numbers and to check whether
or not the numbers are in nondecreasing order. Specifically, the algorithm
should print any number that is less than the number that precedes it in
the series. If no such number is found, the algorithm should print a mes-
sage to that effect.
n
r
is defined by
(r + l)(r + 2) (n-l)n
. . .
1-2 .. . (n-r-l)(n-r)
algorithm to input values for n and r, then print the value of the binomial
coefficient.
—
©fasp&SD3 ®
1
Arrays _.
(
Each of the algorithms in the last chapter had this feature in common: The
algorithm would input a few data items, process them, output the results,
input a few more data items, process those, output the results, and so on.
By continuing in this way, a large amount of data could be processed. But
only a small amount would be stored in the main memory of the computer
at any one time.
For many applications, however, we need to store large lists or tables
of data in main memory. The computer can then refer to any entry in the
list or table whenever it happens to need that information for the job at
144
8.1 One-Dimensional Arrays 145
LIST
20
5
17
83
45
FIGURE 8-1. LIST is a one-dimensional array whose elements are the numbers 20, 5, 17,
83, and 45.
LIST, which contains the real numbers 20, 5, 17, 83, and 45.
LIST refers to the whole array, how do we refer to the individual
If
data items? —
something we must surely be able to do if the entire concept
is to be useful.
Each data item, or element, of the array has a number. We put the
number of the element we wish to refer to in parentheses after the name of
the array. Thus, LIST(l) is the name of the first element of LIST, and its
value is 20; LIST(2] is the name of the second element of LIST, and its
value is 5; and so on. Figure 8-2 shows LIST again, with the elements
named as LIST(l). LIST(2], LIST(3). LIST(4), and LIST(5).
The value in parentheses that determines which element we are refer-
ring to is called the subscript. "Subscript" means "written below," and the
term comes from mathematical notation. Mathematicians would write
LIST(l), LIST(2), LIST(3), and so on as LIST,, LIST 2 LIST 3 and so on. , ,
Most computer printers cannot print some characters below the level of the
others, and so computer programmers must use the parenthesis notation.
This is just as well, since the parenthesis notation is easier to read anyway.
LIST(l), LIST(2), LIST(3), and so on are called subscripted variables.
LIST itself, without a subscript, is called an array variable.
So far, it is not obvious what we have gained by using subscripts. Are
LIST(l), LIST(2), LIST(3), and so on really better than any other sequence
of names, such as say, FIRST_VALUE, SECOND_ VALUE, and so on?
FIGURE 8-2. The elements of LIST are named LIST (1), LIST (2), LIST (3), LIST (4), and
LIST (5).
LIST
LIST(l) 20
LIST(2) 5
LIST(3) 17
LIST (4) 83
LIST(5) 45
146 8 Arrays
LIST(I)
SUM <-
FOR I «- 1 TO 5 DO
SUM «- SUM + LIST(I)
END FOR
AVERAGE «- SUM/5
(We do not make this a complete algorithm since, for the moment, we do
8.2 Elements of Array Processing 147
I 1 I 4
LIST LIST
LIST(I) 20 * 20
5 5
17 17
83 LIST(I) 83 m
45 45
I 2
LIST
20
LIST(I) 5
17
83
45
I 3 I 5
LIST LIST
20 20
5 5
LIST(I) 17 17
83 83
45 LIST(I) 45
FIGURE 8-3. The value of I determines which element of LIST is referred to by LIST (I).
not wish to worry about such matters as how the values of LIST got into
memory in the first place.)
The statement
will be repeated five times. On the first repetition, I will have the value 1,
on the second repetition the value 2, and so on. Thus, the foregoing is
equivalent to:
SUM +-
SUM <- SUM + LISTd
148 8 Arrays
If LIST has the values given in the last section, then the successive values
of SUM and 170, as shown in Figure 8-4. The
will be 0, 20, 25, 42, 125,
value of AVERAGE will be 170/5 or 34.
Notice how well the FOR statement works for array processing. This is
one of its main uses.
Finding the Largest and Smallest Value in an Array. This works like our
algorithm for finding the highest and lowest temperatures, but again we
use a FOR statement to step through the elements of an array:
FIGURE 8-4. We can add up the elements of LIST by causing the statement SUM
SUM + LIST (I) to be repeated with the value of I varying from 1 to 5.
LIST
20
5
17
83
45
SUM «-
SUM
SUM «- SUM + LIST(l)
SUM 20
SUM 25
SUM <- SUM + LIST(3)
SUM 42
SUM «- SUM + LIST (4)
SUM 125
SUM «- SUM + LIST(5)
SUM 170
2
SMALLEST «- LIST(l)
LARGEST «- LIST(l)
FOR I ^ 2 TO 5 DO
IF LIST(I) < SMALLEST THEN
SMALLEST <- LIST(I)
ELSE IF LIST(I) > LARGEST THEN
LARGEST <- LIST(I)
END IF
END FOR
These statements use both the methods we have discussed for referring to
an array element. In the first two statements, we specify the element ex-
plicitlywhen we write LISTfl) in the algorithm. In the repeated state-
ments, we use LIST(I) to refer to an element that will be determined at
execution time.
Assigning Values to an Array. So far. we have said nothing about how the
elements of an array get their values in the first place. One way is an ele-
ment-by-element assignment, where each array element appears on the left
side of an assignment statement. Thus, we could assign LIST its values by:
LIST(l) *- 20
LIST i
<— 5
LIST(3) «- 17
LIST(4) «- 83
LIST(5) <— 45
FOR I ^- 1 TO 5 DO
LIST(I) «- 5*1
END FOR
One way to get the required values would be to copy them from an-
other array. For instance.
FOR I ^
1 TO 5 DO
LIST(I) «- AN0THER_LIST(I+3)
END FOR
150 8 Arrays
Before Assignment
LIST
20
5
17
83
45
Assignment Statement
LIST(2:4) «- (-1, -2, -3)
After Assignment
LIST
20
-1
-2
-3
45
Input and Output of Arrays. As usual, input and output are similar to
assignment, except that the source or destination for a value is an input or
output device rather than an expression or a named location.
We can input values using an iterative construction:
FOR I <- 1 TO 5 DO
INPUT LIST(I)
END FOR
In the same way, we can output an array using either an iterative con-
struction
FOR I <- 1 TO 5 DO
OUTPUT LIST(I)
END FOR
1 ) (
OUTPUT LIST(1:5)
NUMBER_GRADE I
50-59 1
60-69 2
70-79 3
80-89 4
90-99 5
100 6
This calculation puts 100 in a class by itself, which accounts for the
arrays having six entries instead of five and 'A' being treated as a special
case on output. Can you think of another way of handling the "100 prob-
lem"?
8.3 Searching
One way to store a table in memory is to use a separate Jist- -one dimen-
sional array — for each column.
FIGURE 8-6. The algorithm GRADES.
ALGORITHM GRADES
LETTER_GRADE(1:6)^ ('F', D* . 'C
COUNT 1:6) «- (0,0.0,0.0.0
(
END FOR
END GRADES
)
) '' , )) ) '
'
152 8 Arrays
Name Number
Jane 742- -8319
Jim 591- -4872
Larry 984- -1265
Mary 135- -0465
Sue 491- -2031
NAME(1:5) <
'JANE 'JIM'
1
—
Sequential Search. The simplest though not the fastest way to search —
an array is to start at the beginning and examine the elements one by one
until we find the one we are looking for. Like this:
FIGURE 8-7. Parallel arrays are arrays that, because of the way they are used, can be thought
of as positioned side by side, like the columns in a telephone directory.
NAME NUMBER
NAME (
1 'JANE' NUMBER ( 1 '742-8319'
NAME 2 ( •JIM' NUMBER(2) ' 591-4872
NAME 3 ( ' LARRY NUMBER 3 ( '984-1265'
NAME(4) ' MARY NUMBER(4) * 135-0465
NAME(5) 'SUE' NUMBER 5 ( 491-2031*
8.3 Searching 153
INPUT DESIRED_NAME
I <r- 1
WHILE NAME(I) ^ DESIRED_NAME DO
I *- 1 + 1
END WHILE
OUTPUT NUMBER(I)
INPUT DESIRED_NAME
NAME(6) «- DESIRED_NAME
I <- 1
WHILE NAME(I) f DESIRED_NAME DO
I +- 1 + 1
END WHILE
IF I < 5 THEN
OUTPUT NUMBER(I)
ELSE
OUTPUT 'THE NAME YOU REQUESTED IS NOT IN THE DIRECTORY'
END IF
—
The second statement installs the sentinel in position 6 the first free
position beyond the end of the list. After the search, if the value of I is
1-5, then the sought-after item was found. But if the value of I is 6, the
item was not found, and the search was prevented from running off the
end of the list by the sentinel (see Figure 8-9).
154 8 Arrays
DESIRED_NAME •MARY'
I 1 I 4
NAME ( I
'JANE'
'JANE'
•JIM' 'JIM'
' LARRY ' LARRY
'MARY' NAME ( I ' MARY
•SUE' 'SUE'
NAME(I) = DESIRED_NAME? NAME(I) = DESIRED_NAME?
No. Continue search Yes. Stop search. NAME(I)
contains name found, and,
NUMBER(I) contains
rnrre?nnnHincr nnmher
I 2
'
JANE
NAME ( I 'JIM'
' LARRY A
'MARY*
'SUE*
1 ^AME(I) - DESIRED_NAN E?
1 vlo . Continue search
I 3
' JANE
'JIM'
NAME ( I ' LARRY
' MARY
'SUE'
1 ^AME(I) = DESIRED_NAN E?
1 slo . Continue search
FIGURE 8-8. Sequential search. Since the value of I designates a particular element of the
array, we can think of I as pointing to that element. The arrow notation shown here is widely
used.
DESIRED_NAME ('JACK')
/ I 6
'
JANE '
/ 1
JANE
'JIM' 'JIM'
J
' LARRY '
/ ' LARRY
1
MARY '
/ MARY
•
SUE '
/
*
•SUE'
Sentinel
'JACK' position •JACK'
Before search begins Even if item was not found
item being searched for in list proper, search
is placed in last position \ will terminate when item
of list to serve as sentinel. is "found" in sentinel
]
position
FIGURE 8-9. In this sequential search, the sought-after item was not found. The sentinel
prevented the search from running of the end of the list.
ALGORITHM DIRECTORY
INPUT N (N is size of directory)
INPUT NAME(1:N)
INPUT NUMBER! 1:N)
INPUT DESIRED_NAME
WHILE DESIRED_NAME ± 'STOP' DO
NAME(N + 1) «- DESIRED_NAME (Install sentinel)
I <- 1
WHILE NAME(I) ± DESIRED_NAME DO
I «- 1 + 1
END WHILE
IF I « N THEN
OUTPUT NUMBER(I)
ELSE
OUTPUT 'THE NAME YOU REQUESTED IS NOT IN THE DIRECTORY'
END IF
INPUT DESIRED_NAME
END WHILE
END DIRECTORY
—
156 8 Arrays
and keeping it that way when changes are made in it entails some work. —
On the other hand, a sequential search is very inefficient compared to
any search that takes alphabetical (or numerical or any other) order into
account. Looking up a name in a telephone directory using sequential
search would mean starting with the As and going through the entire direc-
tory until we found the name we were looking for —
even if the name was
"Zellman." Needless to say, no person would ever look up a telephone
number that way.
The simplest algorithm that takes alphabetical order into account is
binary search. "Binary" refers to "two." At each step, a binary search di-
vides the part of the list that remains to be searched into two parts. One
part contains the entry we are looking for; the other part does not, and
need not be searched further.
Figure 8-11 illustrates binary search. LOW and HIGH are pointers to
the beginning and end of that part of the list remaining to be searched.
Initially, LOW is set to 1 and HIGH to the subscript of the last entry in the
list.
The name being sought is compared with the entry NAME (MIDDLE), the
entry pointed MIDDLE. If
to by the sought-after name precedes
NAME(MIDDLE), then that name is in the first half of the part of the list
being searched (and therefore we can confine all further searching to the
first half). If the sought-after name follows NAME(MIDDLE), then that
name is in the second half of the part of the list being searched (and there-
fore, we can confine all further searching to the second half). This process
is repeated until the part of the list remaining to be searched closes down
—
on a single name the one we are looking for.
The preceding assumes that the sought-after name is actually on the
list. If it is not, then eventually the pointers LOW and HIGH will pass each
other, indicating that none of the list remains to be searched (and the
sought-after name has not been found). Figure 8-12 illustrates this situa-
tion.
Here are the statements for searching NAME:
LOW «- 1
HIGH «- N
REPEAT
MIDDLE «- INT( (LOW + HIGH) /2 )
DESIRED^NAME •JIM'
NAME
LOW 1 'JANE'
'JIM'
NAME
LOW 2 ^^ •JANE'
//
' MARY
HIGH 2 •SUE'
FIGURE 8-11. Binary search. LOW and HIGH are pointers to be beginning and end of the part
of the list that remains to be searched. MIDDLE points roughly to the middle of this part of
the list.
158 8 Arrays
DESIRED_NAME 'JEB'
L~
NAME
LOW 1 *
JANE
'JIM'
MIDDLE 3 ' LARRY
' MARY
HIGH 5 'SUE'
NAME
LOW 1 JANE
'JIM'
MIDDLE 1 ' LARRY *
HIGH 2 •SUE*
NAME
LOW 'JANE'
JIM'
MIDDLE LARRY'
MARY
HIGH SUE 1
NAME
LOW JANE'
JIM' LOW and HIGH
have "crossed"
1
MARY terminates
HIGH SUE'
FIGURE 8-12. In a binary search, if the sought-after value is not on the list, the pointers
LOW and HIGH will eventually pass one another: the value of LOW will become greater than
the value of HIGH.
If, after the search, LOW =s HIGH, then the sought-after name was
a directory with 1,000,000 entries (an extreme case if the directory was
8.4 Internal Sorting 159
ALGORITHM DIRECTORY
INPUT N
INPUT NAME(1:N)
INPUT NUMBER) 1:N)
INPUT DESIRED_NAME
WHILE DESIRED_NAME ^ 'STOP' DO
LOW «- 1
HIGH *- N
REPEAT
MIDDLE ^ INT( (LOW + HIGH /2 ) )
stored as an array in main memory, but not if it were stored on some aux-
iliary memory device). With sequential search we would, on the average,
—
have to examine half the entries 500,000 before finding the one we —
were searching for. For binary search, the average number of entries that
we would have to examine is 19! Quite a difference.
lists in computer memory so that the computer can search them more effi-
ciently. We print out lists in alphabetical order so that human beings can
search through the printout more easily.
In this section, we will discuss techniques for sorting arrays stored in
main memory. This is known as internal sorting. Sorting of data stored on
auxiliary memory devices is called external sorting and uses quite different
techniques.
The Bubble Sort. We begin with a very simple sort. As with sequential
search, the bubble sort is known more than its efficiency.
for its simplicity
The idea bubble sort is this. We go through a list comparing
of the
adjacent items and exchanging those that are out of order. During such a
compare-and-exchange pass, an item moves forward in the list until it
"bumps up against" a larger item (see Figure 8-14). This behavior is analo-
gous to that of a bubble rising in a liquid, and so the name "bubble sort."
160 8 Arrays
7 «- 4 4 4 4 4 4 4 4
4 «- 7 «- 3 3 3 3 3 3 3
3 3 «- 7 «- 2 2 2 2 2 2
2 2 2 «- 7 - 7 7 7 7 7
9 9 9 9 - 9 - 5 5 5 5
5 5 5 5 5 - 9 - 1 1 1
1 1 1 1 1 1 - 9 - 8 8
8 8 8 8 8 8 8 - 9 «- 6
6 6 6 6 6 6 6 6 *- 9
FIGURE 8-14. A bubble sort compare-and-exchange pass. We compare adjacent items (indi-
cated bv arrows) and exchange those that are out of order.
Remember that for REPEAT the condition is checked after the repeated
statements have been executed, so NO EXCHANGES is checked after
each compare-and-exchange pass has been done.
We now turn to the compare-and-exchange pass. N is the number of
elements on the list, and TEMP is a temporary location used during an
exchange:
8.4 Interna] Sorting 161
4 3 2 3 3 1 2 2
3 2 4 4 1 3 3 3
2 7 5 1 4 4 4 7
9 5 1 5 5 5 5 5
5 1 7 6 6 6 6 6
1 8 6 7 7 7 7 7
8 6 8 8 8 8 8 8
6 9 9 9 9 9 9 9
No exchanges
take place on final
pass, confirming that
list is in order.
FIGURE 8-15. The bubble sort consists of repeating the compare-and-exchange pass until the
list is in order. Notice how many passes are required just to get 1 in the right place.
Putting the parts of the bubble sort together and making provisions
for input and output of the list to be sorted gives us the algorithm in Fig-
ure 8-16.
The Shell Sort. As already mentioned, the bubble sort is noted more for
simplicity than for efficiency. The trouble is that the bubble sort can only
exchange adjacent elements of the list being sorted. If an element is far
from its proper position, many exchanges are necessary to bring it to the
proper position.
We can avoid this difficulty using a technique named after its inven-
tor, Donald Shell. Figure 8-17 illustrates the principle of the Shell sort.
We start with the list to be sorted, which is shown in Figure 8-1 7a.
162 8 Arrays
We choose a gap that, to begin with, is equal to one-half the size of the
list. Since the list in the example contains eight elements, we start with a
gap of four.
We group into sublists those elements of the list to be sorted that are
separated by the chosen gap. In Figure 8-17a we have four sublists, each
consisting of two elements. One sublist consists of the first and fifth ele-
FIGURE 8-17. The Shell sort. For each part of the figure, the first line shows the list being
sorted, with the sublists marked. The second line shows the result of sorting the sublists.
(a) GAP == 4
1
1 1 1
83 25 38 49 10 52 30 List being
i
I
7 1 sorted
17 10 38 30 83 25 52 49 Result of
sorting
sublists
(b) GAP = = 2
l
i 1
1
17 10 38 30 83 25 52 49 List being
i i i
l
sorted
17 10 38 25 52 30 83 49 Result of
sorting
sublists
(c) GAP = 1
17 10 38 25 52 30 83 49 List being
sorted
10 17 25 30 38 49 52 83 Result of
sorting entire
list
8.5 Two-Dimensional Arrays 163
merits of the list to be sorted; another sublist consists of the second and
sixth elements; another of the third and seventh; and another of the fourth
and eighth.
Each of the is sorted independently of the others, with the
sublists
results shown second line of Figure 8-1 7a. Since the sublists are
in the
short, the sorting proceeds rapidly. And since the gap between the ele-
ments on each sublist is large, out-of-place elements make giant strides
toward their final positions.
The next step, illustrated in Figure 8-1 7b, is to divide the gap in half
and repeat the process just described with a gap of two. Now we have two
sublists, one consisting of all the odd-numbered elements of the list being
sorted, and the other consisting of all the even-numbered elements. Again
we sort each sublist independently, obtaining the results shown in the sec-
ond line of Figure 8-1 7b.
Figure 8-1 7c shows the final step. Dividing the gap in half again gives
us a gap of one. Now we have only one "sublist," the list being sorted.
Sorting this single "sublist" gives us our final result, shown in the second
line of Figure 8-1 7c.
The earlier sorts proceed rapidly because the sublists are short. As the
gap becomes smaller, the sublists become longer, but they are also easier
to sort because of the preliminary sorting that has already been done. For
this reason, the entire sequence of sorts called for by the Shell sort take
much less time than a single bubble sort applied to the original list.
So far we have said nothing about the method used to sort the sublists.
Different methods give different versions of the Shell sort. We will look
here at a version of the Shell sort that uses a bubble sort to sort the sublists.
Let the value of GAP be the gap used to form the sublists. If we carry out a
bubble sort, but compare and exchange A(I) and A(I + GAP) instead of A(I)
and A(I + 1), we will sort all the sublists whose elements are separated by
GAP. We can outline this version of the Shell sort as follows:
Figure 8-18 shows the algorithm SHELL SORT. Other, faster sorting al-
gorithms are known, but they are often complex to program. The Shell sort
is a good compromise between speed and simplicity.
ALGORITHM SHELL_SORT
INPUT N
INPUT LIST(1:N)
GAP «- INT (N/2)
WHILE GAP ^ DO
REPEAT
NO_EXCHANGES «- TRUE
FOR I «- 1 TO N-GAP DO
IF LIST(I) > LIST(I+GAP) THEN
TEMP «- LIST(I)
LIST(I) «- LIST(I+GAP)
LIST(I + GAP) <- TEMP
NO_EXCHANGES «- FALSE
END IF
END FOR
UNTIL NO_EXCHANGES
GAP «- INT (GAP/2)
END WHILE
OUTPUT LIST(1:N)
END SHELL SORT
TABLE(3, 2)
TABLE(2, 4)
C C C C
1 1 1 1
u u u u
m m m m
n n n n
1 2 3 4
TABLE * * *
Row 1 -» 28 31 75 99
Row 2 -*- 43 19 25 33
Row 3 -»- 15 81 60 87
Row Column
TABLE!
X I, j)
Name Value
/ TABLEfl, i) 28
k TABLEfl, 2) 31
Row 1 <
|
TABLEd, 3) 75
^ TABLEd, 4) 99
/ TABLE(2, 1) 43
|
1 TABLE(2, 2) 19
Row 2 <
| TABLE(2, 3) 25
^ TABLE(2, 4) 33
< TABLE(3, 1) 15
|
TABLE(3, 2) 81
Row 3 <
|
TABLE(3, 3) 60
I
^ TABLEd, 4) 87
166 8 Arrays
Input Statement
?R "^1 7^ QQ 4"^ 1Q 60 87
28 31 75 99 ^ J
43 19 25 33 — '
15 81 60 87
FOR I «- 1 TO 3 DO
FOR J «- 1 TO 4 DO
INPUT TABLEd, J)
END FOR
END FOR
Each value of I specifies a particular row. With the value of I fixed, the
value of ] ranges from 1 to 4, filling in the elements of a particular row.
The value of I is then increased by 1 and a new row is filled in.
In the following, we will abbreviate these statements to
FOR I «- 1 TO 3 DO
FOR J ^
1 TO 4 DO
OUTPUT TABLEd, J)
END FOR
END FOR
EXAMPLE 1:
We wish to compute the average grades of college students having partic-
ular classifications and major fields. The classifications are freshman,
sophomore, junior, and senior; the major fields we are interested in are
English, history, and mathematics. In our data, each student's classifica-
tion and major field is coded as follows:
sophomore 2 history 2
junior 3 mathematics 3
senior 4
bered by the classification codes, and the columns by the major field
codes. Thus, the data for a junior history major will go in row 3 and col-
umn 2.
LIST(3), and so on, would arrays have any advantages over our previous
system of naming? Why or why not?
168 8 Arrays
Freshman math
majors
Freshman
[Link]
J ;:.:::
.3 e r. i z r
INPUT A(l:10)
OUTPUT A(1:N)
Review Questions 169
ALGORITHM AVERAGES
FOR CLASS <- 1 TO 4 DO (Set totals and counts to 0)
FOR MAJOR «- 1 TO 3 DO
TOTAL (CLASS. MAJOR) *-
COUNT (CLASS, MAJOR) —
END FOR
END FOR
INPUT CLASS, MAJOR, GRADE (Read data, accumulate
counts and totals)
WHILE CLASS ^ —1 DO
TOTAL (CLASS, MAJOR) «~ TOTAL (CLASS, MAJOR) + GRADE
COUNT (CLASS, MAJOR) «- COUNT (CLASS, MAJOR) + 1
INPUT CLASS, MAJOR, GRADE
END WHILE
FOR CLASS <- 1 TO 4 DO (Compute averages)
FOR MAJOR «- 1 TO 3 DO
IF COUNT (CLASS, MAJOR) ± THEN
AVERAGE (CLASS, MAJOR) «- TOTAL (CLASS, MAJOR)
/COUNT (CLASS, MAJOR)
ELSE
AVERAGE (CLASS, MAJOR) « 1
END IF
END FOR
END FOR
OUTPUT AVERAGE* 1:4, 1:3) (Print results)
END AVERAGES
12. Explain sequential search, using the analogy of running your finger
down a column of data.
13. After a sequential search, how can the algorithm determine whether or
not the value searched for was found in the array?
15. What feature of the data being searched does the sequential search ig-
nore and the binary search take into account?
18. How is the bubble sort extended to give the Shell sort?
19. Resolve the apparent paradox that although a Shell sort consists of
many bubble-sort-like passes, it is actually faster than a single bubble sort.
21. Though we did not discuss it in this chapter, what kind of structure
do you think a three-dimensional array might have?
tSmPGX&M
[Link] of an algorithm to find the largest, the smallest, and the average
of all of theelements in a one-dimensional array. The algorithm should
make only one pass over the array.
2. Write an algorithm to input an array of numbers and find their average.
The algorithm will then output each element and one of the words
ABOVE, AVERAGE, or BELOW, depending on whether the value in ques-
tion is greater than, equal to, or less than the average.
3. Modify the algorithm GRADES handle the grade 100 in the same
to
way that grades less than 50 are handled.
4. The price list for a certain business consists of two columns. One col-
umn contains stock numbers; the other contains the corresponding prices.
Write an algorithm to input the price list and then until stopped by a —
sentinel (which —
you should devise) input stock numbers and output the
corresponding prices. Use sequential search.
5. Modify the algorithm of Exercise 4 so that it will input the stock num-
bers of the items ordered by a particular customer, and output an itemized
statement — the number and price of each item and the total cost of all the
items.
10. Five candidates are running for a certain office. A political pollster
Exercises 171
11. To compute the median of a list of numbers, we first arrange the val-
ues in numerical order. If the number of values is odd, then the middle
value on the sorted list is the median. If the number of values is even, then
the median is the average of the two middle values. Write an algorithm to
input a list of numbers and output the median.
12. The percentile rank of a student in a class
is the percentage of students
14. A magic square is a square array of numbers such that the numbers in
each row, column, and diagonal have the same sum. Write an algorithm
to input a square array of numbers and to determine whether or not it is a
magic square.
15. A company has four salespeople and five products. Let the salespeople
be denoted by numbers from 1 to 4 and the products by numbers from 1 to
5. Suppose we are given as data the yearly sales of each product by each
3, 5, 750
(3) the people who sold the largest and smallest amounts of each prod-
uct; and
(4) the products for which each person sold the largest and smallest
amounts.
.
©\sm0m?
Functions
and
Procedures
173
,
then the program, or whether we write the program first and then the func-
tions and procedures. In the next chapter, we will see there are good ar-
guments for writing the program before the functions and procedures.
9.1 Functions
We are already familiar with predefined or built-in functions such as INT
and SQRT. We know that a function is invoked by using it in an expression
and that it returns a value computed from the values of its arguments.
Thus the statement
X «- 3 + SQRT (16)
causes the function SQRT to be invoked. SQRT takes the square root of its
argument, 16, obtaining 4, and returns 4 as its value. The expression on
the right-hand side of <— is evaluated using 4 in place of SQRT(16). The
value of the expression is 7, and this is the value assigned to X.
Now we want to learn how to define our own functions, instead of
having to rely on predefined ones like INT and SQRT. Figure 9-1 shows the
general form of a function definition.
Every function definition begins with a function header having the fol-
lowing form:
tion. When the function is invoked, the values of the arguments are sub-
stituted for the formal parameters in the body of the function that is, in —
FIGURE 9-1. The general form of a function definition. The body of the function must contain
at least one assignment to the function name.
function-name «— expression
END function-name
9.1 Functions 175
the statements that lie between the first line and the last line of the defini-
tion. The arguments are often called actual parameters since they represent
the actual values that will be substituted for the formal parameters when
the function is invoked.
We need some way of indicating what value the function is to return.
One widely used convention is to assign the value to be returned to the
function name:
We can think of the function name as also naming a special memory loca-
tion used to hold the value of the function. When the statements in the
body have been executed, the value stored in this special
of the function
memory locationreturned
is as the value of the function.
A function definition may contain more than one assignment to the
function name; the last such assignment that is executed determines the
value that the function returns. A function definition must always contain
at least one assignment to the function name, since otherwise there is no
way of knowing what value the function should return.
As our example, let's define a function to calculate the diagonal
first
SQRT(LENGTH**2 + WIDTH**2)
FIGURE 9-2. The function DIAGONAL is used to illustrate the parts of a function definition.
X <- 3
Y «- 4
Z ^- DIAGONAUX, Y)
Thus the value 5 is assigned to DIAGONAL. This is the value that the func-
tion returns and the value that is assigned to Z.
Note that the definition of DIAGONAL invokes another function,
SQRT. For a function definition to invoke other functions is not only per-
FUNCTION MAX(M, N)
IF M > N THEN
MAX <- M
ELSE
MAX «- N
END IF
END MAX
P <- 8
Q «- 9
R <- MAX(5*P, 4*Q + 3)
The values of the actual parameters are 40 and 39; these values are
substituted for M and N. In effect, the following statements are executed:
IF 40 > 39 THEN
MAX «- 40
9.1 Functions 177
ELSE
MAX «- 39
END IF
FUNCTION FACTORIAL! N)
F <- 1
FOR I ^
1 TO N DO
F «- F*I
END FOR
FACTORIAL «- F
END FACTORIAL
X 5^
Y <- FACTORIALS ) + 10
F <- 1
FOR I ^ 1 TO 5 DO
F <- F*I
END FOR
FACTORIAL <- F
Figure 9-3 shows a version of the algorithm PAYROLL that uses a func-
tion WAGES(HOURS, RATE] to compute a worker's gross wages from the
hours worked and the rate of pay. Note that by splitting up our task in this
way, we separate the statements that calculate gross wages from those that
read data and print results. If the rules for calculating wages change, then
we only have to change the function WAGES; we don't have to make any
changes in the main algorithm.
The names used for the parameters and variables of a function have
nothing to do with names in other functions, procedures, or algorithms
that might be spelled the same way. In Figure 9-3, for example, the names
HOURS and RATE in the algorithm have nothing to do with the names
HOURS and RATE in the function. In the algorithm, HOURS and RATE
name variables; in the function, they name formal parameters.
9.2 Procedures
A function can only return a single value. When the calculation that we
wish to do yields more than one result, we can write it as a procedure,
which can return any number of results. What's more, a procedure can
manipulate some variables of the invoking algorithm in arbitrary ways, so
ALGORITHM PAYROLL
TOTAL «-
INPUT NAME. HOURS, RATE
WHILE NAME ^ 'END OF DATA' DO
GROSS_WAGES «- WAGES (HOURS, RATE
TOTAL «- TOTAL + GROSS_WAGES
OUTPUT NAME, GROSS_WAGES
INPUT NAME. HOURS. RATE
END WHILE
OUTPUT 'TOTAL GROSS WAGES', TOTAL
END PAYROLL
that, for instance, the same variables whose values provide the data for
the calculation may also be used to store the results.
Figure 9-4 shows the general form of a procedure definition, which is
similar to that of a function definition. But note that a procedure does not
contain any assignment to the procedure name. The formal parameters,
rather than the procedurename, are used for returning values.
The outstanding difference between functions and procedures is the
way in which
their formal parameters are used. For functions, the values
of the actual parameters are substituted for the formal parameters. For this
reason, we refer to the formal parameters of functions as value parameters.
For procedures, the actual parameters must be variables, and these vari-
ables (not their values) are substituted for the formal parameters. For this
reason, we refer to the formal parameters of procedures as variable param-
eters.
We invoke a procedure with a call statement, which has the following
form:
Var-1, var-2, var-n are the actual parameters of the procedure, and
. . .,
This procedure computes the area and diagonal of a rectangle from its
length and width. The formal parameters LENGTH and WIDTH provide the
data for the calculation; the formal parameters AREA and DIAGONAL are
used to return the results.
Suppose we invoke the procedure with the following statements:
W *- 12
X «- 5
CALL RECTANGLE(W, X, Y, Z)
END procedure-name
180 9 Functions and Procedures
with the actual parameters W, X, Y, and Z substituted for the formal pa-
rameters LENGTH, WIDTH, AREA, and DIAGONAL. Thus, invoking
RECTANGLE has the same effect as executing the following statements:
Y *- W*X
Z «- SQRT(W**2 + X**2)
After the subroutine has been called and has returned, the values of
W and X remain unchanged, while Y has been assigned the value 60 and
X the value 13.
As with functions, we sometimes use the formal parameters of a pro-
cedure to refer to its actual parameters. Thus, we may say that "RECTAN-
GLE computes the values of AREA and DIAGONAL from the values of
LENGTH and WIDTH." We sometimes go even further and use the formal
parameters to refer to the values of the actual parameters. (The actual pa-
rameters have to be variables, remember.) Thus, we may say that "REC-
TANGLE computes AREA and DIAGONAL from LENGTH and WIDTH."
Procedures can take array variables as actual parameters. For example,
Figure 9-5 shows a procedure EXTREMES(A, N, MAX, MIX] that finds
the largest and smallest elements of the array A. N is the number of ele-
ments in the array. The formal parameters MAX and MIN are used to return
the values of the largest and smallest elements, respectively. Note that as-
signments are made to MAX and MIN throughout the execution of the pro-
cedure. Therefore, the actual parameters corresponding to MAX and MIN
are used not only to return results but to provide temporary storage during
the execution of the procedure.
As mentioned before, the same parameters can be used both for pro-
viding data to a procedure and for returning its results. Figure 9-6 shows a
procedure SORT(LIST, N) for sorting the N elements of the array LIST us-
ing a bubble sort. Note that the formal parameter LIST is used both to gain
— —
access to the data the unsorted list as well as to return the results the —
sorted list. Put another way, the formal parameter LIST provides the pro-
cedure with access to the actual parameter A so that the procedure can
manipulate the elements of A in whatever manner is needed.
END IF
END FOR
END EXTREMES
9.3 Local and Global Variables 181
REPEAT
NO EXCHANGES «- TRUE
FOR J «- 1 TO N-l DO
IF LIST(J) > LIST(J + 1) THEN
TEMP <- LIST(J)
LIST(J) — LIST(J + 1)
LIST(J + 1) «- TEMP
NO EXCHANGES «- FALSE
END IF
END FOR
UNTIL NO EXCHANGES
END SORT
instead of
In writing your own algorithms, you can include or omit the word CALL
as you wish. I have included it in the algorithms in the book (despite some
suggestions that it be omitted) since its presence unmistakably signals a
procedure invocation.
The use of value parameters is often referred to as call by value, since
values are passed from the invoking algorithm to the function. The use of
variable parameters is often referred to as cali-by-re/erence or call-by-loca-
tion, since variables —
references to or locations of values —
are passed from
the invoking algorithm to the procedure.
Most modern programming languages make use of either call-by-value
or call-by-reference; however, languages vary widely in the circumstances
under which each method of parameter passing may be used. Some lan-
guages restrict the programmer to a single method; others allow each pa-
rameter in a function or procedure to be designated individually as a value
parameter or a variable parameter.
global variables:
Global variables are not without their critics. Some people maintain
that it is clearer to require that all variables to which a function or proce-
dure has access be listed as actual parameters. That way, we can see at a
glance which variables affect or are affected by a particular invocation.
Global variables let data in and out the back door, so to speak, and some-
—
one who is only watching the front door the actual parameters may —
have difficulty understanding what is going on.
These concerns suggest that we use global variables with caution.
However, the reasons for using global variables often seem stronger than
the reasons for avoiding them, so they are widely used, and we will use
them later in this book.
The methods used for declaring variables to be global vary widely from
one programming language to another. In our algorithmic language, we
will declare global variables by listing them in a GLOBAL statement. Thus,
GLOBAL P, Q, R
GLOBAL X
9.3 Local and Global Variables 183
while A does not. Then X refers to the same variable whether it appears in
the algorithm or in one of the functions or procedures. On the other hand,
A refers to different variables in the algorithm and in each function and
procedure.
To illustrate the use of a global variable, let's write a function to gen-
erate pseudorandom numbers. These, you recall, are numbers that seem
to have been chosen at random, even though they were computed by a
function or procedure.
Pseudorandom numbers provide the unpredictability needed by game-
playing programs; few computer games would remain fun very long if the
computer always made the same moves in each particular situation. In
computer simulation pseudorandom numbers are important for simulating
unpredictable events. Still another application is in cryptography, where
messages are rendered secret by manipulating their characters in seemingly
random ways.
There are many ways of generating pseudorandom numbers, some of
which are adapted to the characteristics of particular computers. Since we
don't have time to go deeply into the subject of pseudorandom number
generation, we will be content with a "quick and dirty" method that is
satisfactory for undemanding uses such as game playing.
Our pseudorandom number generator will work with a real number in
the range 0-1 (not including 1). This number is called a seed, and we
assign it to the global variable SEED. The starting value of SEED is supplied
by the user. Thereafter, each time the pseudorandom number generator is
invoked, it computes a new value of SEED from the old value of SEED.
The successive values of SEED provide a sequence of pseudorandom num-
bers, all of which are greater than or equal to and less than 1. If we need
pseudorandom numbers in some other range, we can derive them from the
successive values of SEED.
We compute a new value of SEED from its old value as follows:
result and retaining only the fractional part that makes the resulting series
of numbers appear to be random.
Now let's write a function that takes no arguments and yields a pseu-
dorandom fractional value each time it is invoked:
FUNCTION RND
GLOBAL SEED
SEED «- (SEED + 3 1415927 **2 . )
(Note that when a function or procedure has no parameters, the entire pa-
rameter list, including the enclosing parentheses, is omitted.)
Each time RXD is used in an expression, it computes a new value for
SEED and yields that value as the value of the function. SEED must be a
global variable, since its value has to be retained from one invocation of
RXD to the next.
The following algorithm uses RXD to print a series of 50 pseudoran-
dom numbers:
ALGORITHM CHAOS
GLOBAL SEED
SEED «- .8159327
FOR I ^ 1 TO 50 DO
OUTPUT RND
END FOR
END CHAOS
Note that the algorithm that uses RXD has to provide a starting value
for SEED. It is from this starting value that SEED gets its name; the starting
value is the seed from which grows the entire sequence of pseudorandom
numbers.
We often need pseudorandom numbers that are integers in a particular
range. For instance, suppose we need pseudorandom integers in the range
1-100. How can we compute these from the values of RXD?
We can reason as follows. Suppose our computer stores real numbers
with seven-place accuracy. Then the values of RXD will range from
through .9999999. The values of 100*RXD will range from through
99.99999, so the value of IXT(100*RXD) is an integer in the range 0-99. If
INT(100*RND) + 1
INT(6*RND) + 1
INT(36*RND) + 1
FUNCTION RANDOM! N)
GLOBAL SEED
SEED *- (SEED + 3 . 1415927 **2
)
' '
FACTORIAL(l) = 1
FACTORIALS) = 2*1
FIGURE 9-7. The algorithm GUESS. This algorithm invokes the function RAXDOM, which
is defined in the text. The global variable SEED is accessible to both GUESS and RAXDOM.
ALGORITHM GUESS
GLOBAL SEED
OUTPUT ENTER A NUMBER BETWEEN
' AND 1
INPUT SEED
OUTPUT I AM THINKING OF A NUMBER BETWEEN 1 AND 100'
OUTPUT YOU ARE TO TRY TO GUESS THE NUMBER. I WILL TELL'
OUTPUT YOU WHETHER YOUR GUESS IS RIGHT, OR WHETHER'
OUTPUT IT IS TOO LARGE OR TOO SMALL.
REPEAT
NUMBER «- RANDOM (100)
OUTPUT 'I HAVE MY NUMBER. WHAT IS YOUR GUESS?'
REPEAT
INPUT YOUR_GUESS
IF YOUR_GUESS > NUMBER THEN
OUTPUT 'YOUR GUESS IS TOO LARGE GUESS AGAIN
ELSE IF YOUR_GUESS < NUMBER THEN
OUTPUT 'YOUR GUESS IS TOO SMALL GUESS AGAIN
END IF
UNTIL YOUR_GUESS = NUMBER
OUTPUT 'YOUR GUESS IS RIGHT'
OUTPUT 'WOULD YOU LIKE TO PLAY AGAIN (YES OR NO)?'
INPUT PLAY_AGAIN
UNTIL PLAY_AGAIN ^ 'YES'
OUTPUT 'I HAVE ENJOYED PLAYING WITH YOU'
END GUESS
186 9 Functions and Procedures
FACTORIALS) = 3*2*1
FACTORIALS) = 4*3*2*1
FACTORIALS) = 5*4*3*2*1
and so on.
Now notice that, since FACTORIAL! 1) equals 1,
FACTORIALS) = 3*FACT0RIAL( 2 )
FACTORIALS) = 4*FACT0RIAL( 3 )
FACTORIALS) = 5*FACT0RIAL(4
and so on.
We can, in fact, define the FACTORIAL function by the following two
statements:
FACTORIALS) = 1
FACTORIAL(N) = N*FACTORIAL( N- 1 ) , N greater than 1
FACTORIALS) = 5*FACT0RIAL(4)
This doesn't help much, since we don't know the value of FACTORIAL^).
But we can go back to the definition and find that
FACTORIALS) = 4*FACT0RIAL(3
Hence,
FACTORIALS) = 5*FACT0RIAL( 4 )
= 5*4*FACT0RIAL( 3 )
FACTORIALS) = 5*4*3*FACT0RIAL( 2
FACTORIALS) = 5*4*3*2*FACT0RIAL( 1
FUNCTION FACTORIAL(N)
IF N = 1 THEN
FACTORIAL <- 1
ELSE
FACTORIAL «- N*FACTORIAL( N- 1
END IF
END FACTORIAL
Note carefully the two ways in which the word FACTORIAL is used. When
FACTORIAL appears on the left-hand side of *—, we are returning a value
by assigning it to the function name. When FACTORIAL appears in the
expression on the right-hand side of <—, we have a new invocation of the
function FACTORIAL, called a recursive invocation since FACTORIAL is
being invoked by itself.
Suppose this function is invoked to compute FACTORIAL^). During
the computation of FACTORIAL^) the function is invoked again to com-
pute FACTORIAL^). During the computation of FACTORIAL^), the func-
tion is invoked again to compute FACTORIAL^), and so on. Eventually
the function is invoked to compute FACTORIAL(l).
FACTORIAL(l) can be computed without any further function invoca-
tions. (Why?) With the value of FACTORIAL(l) at hand, the computation
of FACTORIAL^) can be completed; with the value of FACTORIAL^) at
hand; the computation of FACTORIAL^) can be completed. Proceeding in
this way the computations of FACTORIAL^) and, finally, FACTORIALS)
are completed.
When a function calls itself, the new invocation must not change
the contents of any memory locations that the old invocation is still using.
This means that for each invocation of the function, a separate memory
area must be set aside for holding the values of parameters and local vari-
ables.
Recursion is not always the most efficient way
to solve a problem. For
instance, our previous version of FACTORIAL
using repetition is more
efficient than the recursive version. The recursive version takes more
memory because of the need for a separate memory area for each invo-
cation. Also, for each function invocation the computer must waste a
certain amount of time passing parameters to the function, setting up a
new memory area for it, and returning its result after it has finished exe-
cuting.
Nevertheless, some problems are inherently recursive in nature, so
that the easiest and most natural way of presenting their solutions is as
recursive functions or procedures. For these kinds of problems, it is worth
using recursion for the sake of clarity even if some efficiency is sacrificed.
We will see examples of such problems in Chapter 15.
188 9 Functions and Procedures
u^®wd(M7 ©an@©GD®[Ju©
[Link] some everyday objects that are built out of simpler parts,
whose parts are built out of still simpler parts, and so on.
2. What two properties do functions and procedures possess that are not
enjoyed by the parts of which physical machines are made?
7. How does a function definition specify the value that the function is to
return?
11. What kinds of actual parameters can be substituted for value parame-
ters? For variable parameters?
i::¥:'Y -
For each of the following you should write not only the function or proce-
dure requested but also an algorithm that "exercises" the function or pro-
cedure by invoking it.
4. We can round a value to the nearest integer by adding 0.5 to its abso-
round
lute value, then discarding the fractional part of the result. Thus, to
3.72, we add Dropping the 0.22 gives us the rounded
0.5 getting 4.22.
value of 4. To round -71.63, we add 71.63 (the absolute value of -71.63)
to 0.5 getting 72.13. Dropping the 0.13 gives 72 and restoring the minus
sign gives the final rounded value of -72. Write a function ROUND(X)
whose value is its argument rounded to the nearest integer. ROUND should
work for both positive and negative arguments.
5. Modify the procedure EXTREMES so that it returns not only the largest
and the smallest values in the array A but also the subscripts of the element
containing the smallest value and the element containing the largest value.
(If the smallest value occurs more than once, the subscript of any element
containing that value may be returned. The same is true for the largest
value.)
11. A
few programming languages do not provide the operator ** for rais-
ing numbers to powers. For use in such languages, define a function
POWER(X, N) that for any real number X and nonnegative integer N re-
turns X raised to the Nth power. Thus POWER(X, 0) = 1; POWER(X, 1)
= X; POWER(X, 2) = X*X; POWER(X, 3) = X*X*X; and so on.
12. The POWER function described in Exercise 11 can be defined recur-
sively as follows:
POWERU, 0) = 1
P0WER(X, N) = X*P0WER(X, N-l), N greater than 1
Justify this definition, and use it to write a recursive version of the func-
tion POWER.
13. Write a function GCD(M, N) whose value is the greatest common div-
isor of the positive integers M and N. Use the technique for computing the
greatest common divisor given in Chapter 1.
14. The function GCD(M, N) for computing the greatest common divisor
of M and N can be defined recursively as follows:
GCD(M, 0) = M
GCD(M, N) = GCD(N, II MOD N) , N greater than
The two numbers in the sequence are and 1. Each remaining number
first
FIBONACCI(l) =
FIBONACCI (2) = 1
FIBONACCI(N) = FIBONACCI(N-l) + FIBONACCI ( N-2 ) ,
N greater than 2
Justify these statements and use them to write a recursive function defini-
tion for FIBONACCI(N).
3
©GospBcgo 'O®
JD
Algorithm Design
and Testing
191
192 10 Algorithm Design and Testing
exploration, there was much talk of the "command module," the "lunar
module," and the "reentry module."
When we think about the functioning of any complex system, we almost
invariably think in terms of the modules that make it up. We often call these
modules "systems." Thus, we think of an automobile not as just a big jumble
of parts, but as consisting of an electrical system, a cooling system, a steering
system, a braking system, a drive system (engine and transmission), and so
on. Each of these "systems" is an example of a module.
When designing or repairing a car, we invariably concentrate our at-
tention on one of these modules to the exclusion of the others. Thus, if the
engine is running too hot, we would not spend much time worrying about
the battery. We would focus our attention on the cooling system. And if a
tire is flat, we would not even bother to raise the hood to check the car's
electrical or cooling or fuel systems. We would have the trouble localized
in one small module; we could concentrate on repairing that module and
no other.
Bottom-level modules
FIGURE 10-1. A hierarchy of modules. The top-level module is the entire algorithm. The
bottom level modules only make use of built in operators and functions; they do not call any
other user-written modules.
©
Module
A-l
0J
Module
£ Module
©.
Module
0.
Module Module
C-l C-2 C-3 C-4 C-5
FIGURE 10-2. Top-down design. The numbers show the order in which the modules are de-
signed.
Thus, we would start out by writing the main algorithm. But whenever
the need arose to perform an operation of any complexity, we would write
a function or procedure perform that operation. We would, of
call to
course, have to make a note of exactly what each of these functions or
procedures is supposed to do, since we would have to write it later.
The procedures and functions called by the main algorithm would
form the second-level modules. When writing these, we would again call
on procedures and functions to perform complex operations. These proce-
dures and functions would form the third-level modules. Eventually we
will reach the bottom level. This is made up of those functions and proce-
dures that can be expressed entirely in terms of the built-in operators and
functions of the language.
As an example of top-down design using procedures we will write an
algorithm to play craps with the user. The entire algorithm, called CRAPS,
will form the top level of the module hierarchy, as shown in Figure 10-3.
We want to express the top-level module in terms of calls to the pro-
cedures that will form the second-level modules. A good strategy at this
stage is to leave all details of the calculations to the procedures and con-
centrate on the overall data flow. Bearing this in mind, we come up with
the following second-level modules:
. .
CRAPS
correct.
196 10 Algorithm Design and Testing
ALGORITHM CRAPS
CALL INITIALIZE (AMOUNT)
REPEAT
CALL ACCEPT_BET(BET, AMOUNT)
CALL PLAY (WON)
CALL UPDATE (BET, AMOUNT, WON, FINISHED)
UNTIL FINISHED
OUTPUT 'I ENJOYED PLAYING WITH YOU.'
OUTPUT "LET US DO IT AGAIN REAL SOON.'
END CRAPS
FIGURE 10-4. The algorithm CRAPS. This top-level module calls four second level modules,
the procedures INITIALIZE, ACCEPT_BET, PLAY, AND UPDATE.
CRAPS
FIGURE 10-5. The top and second level modules for the algorithm CRAPS.
INPUT AMOUNT
WHILE AMOUNT ^ DO
OUTPUT 'YOU CANNOT PLAY WITH a SERO OR MEGATIVE' ; 1
OUTPUT 'AMOUNT'
INPUT AMOUNT
END WHILE
END INITIALIZE
10.1 Algorithm Design 197
ACCEPT BET, Figure 10-7, accepts the amount that the player
wishes to bet on this game. This bet must be less than the value of
AMOUNT; the player cannot play on credit.
The module PLAY, Figure 10-8, causes the dice to be rolled and de-
termines whether the player wins or loses according to the rules of craps.
Those rules are:
If the player rolls a 7 or 11 on his first roll, he wins. If he rolls a 2, 3,
R0LL_DICE( VALUE)
FIGURE 10-8. The procedure PLAY. This second-level module calls one third-level module,
the procedure ROLL DICE.
FIGURE 10-10. The procedure ROLL_DICE, our only third-level module. RANDOM is as-
sumed to be a built-in function. If it were written by the user, it would be a fourth-level
module.
CRAPS
R0LL_DICE
FIGURE 10-11. The complete module hierarchy for the algorithm CRAPS.
We could do the same each of the other comments. But since the
for
refinements of the comments same as the bodies of the procedures
are the
already given, we will not repeat each refinement separately. Instead, Fig-
ure 10-13 gives the result of inserting the refinement below each comment
(retaining the comments for documentation).
The call to the procedure ROLL DICE has been retained. Since
ROLL DICE is called twice, it is best to make it a procedure and call it
twice rather than repeating the statements for ROLL DICE twice. If this
consideration had not intervened, a comment would have been used in
place of each call to ROLL DICE. On the next refinement, each such com-
ment would have been replaced by the statements from the body of
ROLL DICE.
FIGURE 10-12. To construct the algorithm CRAPS by stepwise refinement, we start with an
outline in which the lower-level modules are represented by comments.
ALGORITHM CRAPS
(Accept initial value for AMOUNT)
REPEAT
(Accept BET and see that it does not exceed AMOUNT)
(Play a game and set WON to TRUE or FALSE to
indicate the result)
(Update AMOUNT according to results of last
game; set FINISHED to TRUE or FALSE depending
on whether or not more games are to be played)
UNTIL FINISHED
OUTPUT 'I ENJOYED PLAYING WITH YOU'
OUTPUT 'LET US DO IT AGAIN REAL SOON'
END CRAPS
10.1 Algorithm Design 201
ALGORITHM CRAPS
(Accept initial value for AMOUNT)
OUTPUT 'HOW MUCH MONEY DO YOU HAVE TO PLAY WITH?'
INPUT AMOUNT
WHILE AMOUNT s DO
OUTPUT 'YOU CANNOT PLAY WITH A ZERO OR NEGATIVE'
OUTPUT 'AMOUNT OF MONEY. PLEASE ENTER A POSITIVE'
OUTPUT 'AMOUNT'
END WHILE
REPEAT
(Accept BET and see that it does not exceed AMOUNT)
OUTPUT 'HOW MUCH MONEY DO YOU WISH TO BET ON THIS GAME?'
INPUT BET
WHILE BET > AMOUNT DO
OUTPUT 'YOU CANNOT BET MORE THAN YOU HAVE"
OUTPUT 'PLEASE ENTER ANOTHER BET'
INPUT BET
END WHILE
(Play a game and set WON to TRUE or FALSE to
indicate the result)
CALL ROLL_DICE( VALUE)
IF (VALUE = 7) OR (VALUE = 11) THEN
WON — TRUE
ELSE IF (VALUE = 2 OR (VALUE = 3 OR (VALUE = 12) THEN
) )
WON «- FALSE
ELSE
POINT «- VALUE
REPEAT
CALL ROLL_DICE( VALUE)
UNTIL (VALUE = POINT) OR (VALUE = 7)
IF VALUE = POINT THEN
WON «- TRUE
ELSE
WON «- FALSE
END IF
END IF
(Update AMOUNT according to results of last
game. Set FINISHED to TRUE or FALSE
depending on whether or not more games are
to be played.
IF WON THEN
OUTPUT 'CONGRATULATIONS, YOU WON!'
AMOUNT «- AMOUNT + BET
ELSE
OUTPUT 'TOO BAD. YOU LOSE!'
AMOUNT — AMOUNT -BET
END IF
OUTPUT 'YOU NOW HAVE', AMOUNT. 'DOLLARS.'
IF AMOUNT = THEN
FINISHED *- TRUE
ELSE
OUTPUT 'DO YOU WANT TO PLAY ANOTHER GAME?'
INPUT ANSWER
IF ANSWER = 'YES' THEN
FINISHED «- FALSE
ELSE
FINISHED «- TRUE
END IF
END IF
UNTIL FINISHED
OUTPUT 'I ENJOYED PLAYING WITH YOU'
OUTPUT 'LET US DO IT AGAIN REAL SOON'
END CRAPS
FIGURE 10-13. We refine the outline of the algorithm CRAPS by replacing each comment
with statements that carry out the operation described. Instead of actually replacing the com-
ments, we can retain them to document the algorithm.
202 10 AJgorithm Design and Testing
archical relationships among modules and have said little about the design
of individual modules. There is a limit to what we can say. The design of
a module is programmer;
a creative act of the it cannot be completely ana-
lyzed. Nevertheless, two points can be made:
to any of these three. The same result can be obtained- with the unrestricted
use of flowcharts. These do-it-yourself control structures sometimes seem
to be slightly better than the standard ones for the particular problem at
hand. But since they are inevitably more complex than the standard control
structures, and since they have not been studied as extensively, their ef-
fects are less predictable and their use more risky. Confining oneself to the
control structures in the algorithmic language will go a long way toward
simplifying the design of reliable modules.
the program a few pieces of test data, and if the answers "look
on right,"
the program pronounced ready for use. This is the kind of testing that
is
gives rise to the adage that there are no debugged programs, only those in
which the bugs have not yet been encountered!
By far the best way to test any system, be it a program or a complex
mechanical or electronic device, is to test it part by part as it is con-
structed. That is, we test each module separately as well as various mod-
ules in combination.
The most obvious way to do this is known as bottom-up testing. We
those modules on the bottom level of the hierarchy, the ones that
first test
do not call on any other modules. When we are sure that these work, we
move up to the next level and test those modules that are built from the
10.2 Program Testing 203
called by the module that will actually call it in the finished program.
Top-down testing solves both problems. In top-down testing, we start
with the top-level module and test it first. Then we test the second-level
modules, and so on, until the bottom-level modules are tested (see Figure
10-15).
Now modules can be tested in the same order in which they are de-
signed and constructed. We can design and test the top-level module before
we even begin work on the second-level modules.
And when the second-level modules are tested, the already-tested top-
level module provides an ideal test harness. Each module is tested in ex-
FIGURE 10-14. Bottom-up testing. The numbers show the order in which the modules are
tested.
Q_
Q_ © .
G)_
204 10 Algorithm Design and Testing
FIGURE 10-15. Top-down testing. The numbers show the order in which the modules are
tested. Notice that this order is the same as for top-down design.
actly the same environment in which it will operate in the finished pro-
gram.
But wait —
how can we test the modules on one level when the lower
level modules they must call have not been written? The answer is that we
replace the unwritten modules with program stubs. A program stub is a
module that prints out the fact that it has been called and prints any data
values relevant to the call. By studying this printout, we can see that the
higher level module is invoking the correct lower level modules under the
correct circumstances and is passing them the correct arguments. Figure
10-16 illustrates the use of program stubs.
Already
tested
L r r r 1 i r i
J n L J L. J L L . J
FIGURE 10-16. In top-down testing, not-yet-written modules are replaced by program stubs,
which are shown here as boxes enclosed by broken lines.
206 10 Algorithm Design and Testing
ALGORITHM PAY
INPUT NAME, HOURS, RATE
WHILE NAME ± 'END OF DATA' DO
CALL COMPUTE_PAY( HOURS, RATE, WAGES)
OUTPUT NAME, WAGES
INPUT NAME, HOURS, RATE
END WHILE
END PAY
WAGES «- 999.99
END COMPUTE_PAY
When this program stub is invoked, it will announce itself and print
out the values that were passed to it. Also, it assigns a dummy value
(999.99) toWAGES so we can check that the value which COMPUTE_
PAY assigns to WAGES is being properly used by the rest of the program.
With the aid of this program stub, we can test PAY rather thoroughly.
In particular, we can test that
COMPUTE PAY is invoked once for each group of data, until a group
with employee name equal to 'END OF DATA' is encountered.
For each group of data, the values of HOURS and RATE are correctly
passed to COMPUTE_PAY.
FIGURE 10-17. Ideally, we should use enough test cases to cause a program to traverse every
possible path through its flowchart.
208 10 Algorithm Design and Testing
tions in its algorithm), then there can exist as many as a billion paths
FIGURE 10-18. In practice, often the best we can hope to do is to test every branch leaving
each decision symbol. This does not test every branch through the entire flowchart, as we can
see by comparing Figures 10-17 and 10-18.
Review Questions 209
using a different counter for each branch, (see Figure 10-19). On exit from
the module, the values of all the counters are printed out.
If the value of any counter is when it is printed out, then the corre-
sponding branch has not been tested. For the testing to be minimally thor-
ough, the value of each counter must be at least 1. For greater confidence
in the results of the test, the value for each counter should be greater than
1. The exact value we should hold out for will depend on the complexity
of the program, the use to which it will be put, the consequences of its
failing, and the cost of testing.
u^®WD@W (2te@GD®[JK
1. Give some additional examples of complex systems whose construction
2. Do complicated systems usually work correctly the first time they are
tested?
3. How is the amount of time and effort spent in designing a system likely
to be related to the amount that will be needed to debug it?
4. What is a module?
5. Give some examples of systems that can be decomposed into modules,
telling what the modules are in each case.
6. What is the advantage of modularity when we are designing, testing,
or repairing a system?
bottom-level modules?
10. At any stage of a top-down design, on what will our attention be fo-
cused? What are some of the things we can forget about for the moment?
12. What are the disadvantages of using functions and procedures as mod-
ules?
210 10 Algorithm Design and Testing
COUNT.. 1 <-
C0UNT_1 + 1 C0UNT_2 + I
1 1
. ( \ „
) '
I
! II
COUNT 3 «—
C0UNT_3 * 1 C0UNT_4 + 1
1
i
1 f
. ( \ m
'
I
\
FIGURE 10-19. A flowchart with software counters inserted to make sure that each branch is
tested at least once. After initializing the counters to zero, the segment shown is executed
repeatedly with different sets of data. Then the values of the counters are displayed to show
how manv times each branch was tested.
Problems 211
13. Compare stepwise refinement with the use of functions and procedures
as modules.
18. What are two difficulties of bottom-up testing that are not present in
top-down testing?
22. How can software counters be used to assure that every branch leaving
a decision symbol is tested at least once?
language and test it on the computer. Use program stubs for unwritten
modules needed by the module being tested.
(d) In testing each module, use software counters to verify that each
212 10 Algorithm Design and Testing
branch in the flowchart has been tested at least once (and preferably
more than once).
(e) It is interesting to make this problem a team effort, with the modules
DATA
STRUCTURES
©fegpfeF ^
Character
Strings
Beginning with this chapter, we shift our emphasis from algorithms ways —
of manipulating data —
to data structures —
ways of organizing data. Of
course, we will still be concerned with algorithms, since the reason for
organizing data is to make it convenient to manipulate. But we will be
applying the principles of algorithm construction we have already learned.
What will be new will be the techniques for organizing the data.
We have already taken up two data structures so far: arrays and char-
acter strings. Arrays were discussed thoroughly in Chapter 8. Although we
will find new uses for arrays as we go along, we will not devote another
chapter to arrays in general.
On the other hand, we have only been using character strings in the
simplest possible ways— inputting them, outputting them, and comparing
them with one another. There are many more things we can do with char-
acter strings, and this chapter will explore some of them.
215
'
1000001
0010000
1010011
The characters
are actually
stored as 1010100 . or like this
binary codes but for ease of reading
like this . . we will usually repre- A S T R : N 3
sent a string in memory
1010010 like this . . .
1001001
1001110
1000111
FIGURE 11-1. A character string is normally stored with the characters in adjacent memory
locations.
FIGURE 11-2. One character string location is made up of many physical memory locations.
A STRING
—A T R
1
S I N G
i 1
A character string location can be of fixed length, that is, it can con-
sist of a fixed number of character locations. If a shorter character string is
must be "padded" with
stored in a fixed-length location, the shorter string
blanks to out the location. The padding blanks are usually added to the
fill
would reserve space for 20 characters and give that 20-character block the
name STRING (see Figure 11-4). Throughout the program, the variable
STRING would always refer to this 20-character block. If a 15-character
string was stored in STRING, would be padded with five blanks. If one
it
Fixed-Length Locations
T
Unused character positions
filled with blanks
T G E T H E R
Variable-Length Locations
T G E T HE R
218 11 Character Strings
FIGURE 11-4. Storing strings in a fixed-length location. Short strings are padded with blanks
to fill out the location; long strings are truncated to fit.
will vary depending on the data the program is processing. There are two
ways to do this:
represented by "6."
Some languages require the user to specify the maximum size of a var-
iable-length character string. Thus,
would make STRIXG the name of a location that could hold from to 20
characters, but no more than 20. In this case, memory space would be set
aside for 20 characters. Either a preceding character count or a trailing end-
of-string character would be used to indicate the number of characters cur-
rently in use (see Figure 11-6).
In some languages, no limit is placed on the size of a character string
location. A variable such as STRIXG can be assigned a string of anv length.
11.2 Character String Operations and Functions 219
STRING 2 T STRING T
1
—
STRING 3 T G E|T H E R STRING T G e|t H E R
STRING 12 T G E T H
—
STRING T G E T H E R N E S s
FIGURE 11-5. Two methods for storing variable-length character [Link] method uses a
character count to keep track of the length of the string; the other method uses an end-of-
string sentinel.
When such an assignment is made, the system must find a block of mem-
ory of the required size and store the assigned string in that block. Since
the variable STRING can refer to different blocks of memory at different
times, the system must keep track of which block STRING currently refers
to (see Figure 11-7).Because of all these things the system must do each
time a string assignment is made, strings of unlimited length are less effi-
cient than those having a maximum length. But they are more convenient
for the programmer to use.
Since the emphasis in our algorithmic language is on convenience for
the programmer, it uses variable-length strings with no maximum length.
STRING 2 T
mmwM STRING T
W/AWM
Unused
ST RING «- 'TOGETHER'
STRING 8 T G E T H E R STRING T G E T H E R
STRINC «- 'TOGETHERNESS'
,
STRING 8 T G E T H E R STRING T G E T H E R
\ /
Size of location determines length of longest
string that can be stored. If one attempts to
store a longer string, characters will be lost.
FIGURE 11-6. Storing variable-length character strings in a location of fixed length. Only part
of the location is used for strings of less than the maximum length.
character strings, so we will appropriate the plus sign for the concatena-
tion operator. The following examples illustrate concatenation:
Expression Value
'FOR' + 'GET' 'FORGET'
'TO' + 'GET' + 'HER' 'TOGETHER'
•GOOD' + 'DAY' •GOODDAY'
'GOOD + 'DAY'
'
'GOOD DAY'
'G00D' + + 'DAY'
' '
'GOOD DAY'
'GOOD' + + 'DAY'
' '
'GOODDAY'
duced. Also, in the last example, concatenating a string with the null
string does not change it in any way. The null string is ignored in a con-
catenation.
Variables as well as values may occur in concatenations. If S, T, U,
and V have the values
'FOR' TO'
'GET' HER'
STRING-2 unused
STRING-2 'TOGETHER'
STRING-3 STRING 3
unused STRING-2
1
1
I?
I
I
I unused
i
I
I
FIGURE 11-7. A variable-length location of unlimited length will correspond to different
physical memory locations at different times as the computer system finds space in different
parts of memory to store strings of different lengths.
Expression Value
S+T FORGET'
U+T+V TOGETHER'
U+ '
+T+ ' '
+S+ ' '
+V TO GET FOR HER'
OUTPUT S + T
, '
U <- U + T + V
would assign U the value 'TOGETHER'. The values of T and V would not
be changed.
Expression Value
MID( ' TOGETHER ' , 1 2) 'TO'
MID( 'TOGETHER' , 3, 3) 'GET'
MID( 'TOGETHER' , 4, 5) ' ETHER
MID( 'TOGETHER' , 6, 3) 'HER'
The function MID canextract any substring from a string. Since sub-
strings that begin at the beginning of the string or end at the end of the
string are often needed, however, some languages provide additional func-
tions LEFT and RIGHT that are more convenient for extracting these special
substrings.
The function LEFT(STRING, LENGTH) has as its value the substring
extracted from the left end of STRING whose length is specified by the
Expression Value
LEFT( 'TOGETHER' 2) , 'TO'
LEFT 'FORGET'
(
3) , 'FOR'
RIGHT 'TOGETHER'
(
3) , 'HER'
RIGHT 'TOGETHER'
(
5) , ETHER
The LEFT, MID, and RIGHT functions can be combined with conca-
tenation to form more complex string expressions. For instance, the state-
ments
11.2 Character String Operations and Functions 223
N u|m B |
E R I N G F C H A R A C T E R P S I T I N |
S
123456789
T T t T T T T T T T t T t T T T T T t T
10 1112 13 14 15 16 17 18 19 20 2122 23 24 25 26 27 28 29 30
T T t T T T t t t T T
3132
T
S ^- 'TOGETHER'
T ^
LEFT(S, 2) + '
'+MID(S, 3, 3) + '
'+RIGHT(S, 3)
Expression Value
P0S( 'TOGETHER' 'GET' 3
P0S( 'TOGETHER' 'TO '
1
'ATE' 'ATE'
'CAT' first oc surrence second occurrence
\ 1
C N C A T E N A T E
123456789 1011
Substring Position
CAT '
*
4
first occurrence of 'ATE' 5
Second occurrence of 'ATE' 9
224 11 Character Strings
If the substring occurs in the string more than once, POS yields the
position of the first occurrence:
Expression Value
P0S( 'CONCATENATE' ATE' 5 (not 9
P0S( 'CONCATENATE' N' ) 3 (not 8
POS ('ERROR', 'R') 2 (not 3 or 5
P0S( 'TO GET HER' 3 (not 7
Figure 11-10 shows how the search for the substring is carried out. An
attempt is made to match the substring with the string starting at position
1. If match fails, then the substring is shifted to position 2 and the
this
match attempted again, and so on. When a match is found, the current
is
POS.
Often the substrings we wish to extract are separated, terminated, or
delimited by other substrings. For instance, words in a sentence are sepa-
rated by spaces, a sentence is terminated by a period, and a quotation is
delimited by quote marks. It is these delimiting substrings that we usually
locate with POS. We use their positions to extract the delimited substrings.
c N C A T E N A T E
No match
A T E
C N C A T E N A T E
No match
A T E
C N C A T E N A T E
No match
A T E
C N C A T E N A T E
No match
A T E
c N C A T e| N A T E
Match. Value of
A T E P0S( 'CONCATENATE' ' ATE '
)
is 5
) ) ) ) )
For example, to extract the first word from the value of STRING, we
start by finding the first blank:
Extracting the first sentence is similar, except that we include the period
that ends the sentence in the extracted sentence:
Expression Value
LEN 'FORGET'
(
) 6
LEN 'TOGETHER'
(
) 8
Blanks are always counted in finding the length of a string. Thus, the value
of LEN('TO GET HER') is 10.
With the LEN function we can extract a quotation a substring —
bounded by quote marks. We begin by locating the first quote mark:
Now we extract all the string following the first quote mark:
Remembering that the values of I and J are the positions of the two quote
marks, we could have also extracted the quote with
For instance, in
is:
Previous chapters have stressed that real numbers such as 3.1416 and
strings such as '3.1416' are different kinds of data, represented differently
inside the computer and subject to different operations. Sometimes it is
desired to change a string such as '3.1416' into the corresponding real num-
ber, and vice versa. The VAL and STR functions accomplish this data con-
version:
Expression Value
VAL( '3.1416' 3.1416
VAL ('-25') -25
STR(3.1416) '3.1416'
STR (-25) '-25'
Effectively, VAL removes quote marks from around a number and STR
places quote marks around a number. But what goes on inside the com-
puter is more complicated than this. Inside the computer real numbers are
normally represented in binary notation, whereas strings such as '3.1416'
are in decimal notation, with each decimal digit represented by a character
code. Thus, what is actually involved is decimal-to-binary conversion for
VAL and binary-to-decimal conversion for STR.
A match is possible only if L2 < Ll. In that case, STRING has L1-L2 + 1
11.3 Examples of String Processing 227
ter— say, % —is used wherever the city is to be inserted. A computer then
Dear #,
As a person who needs to stay well informed, you, #,
cannot afford to be without a subscription to
YESTERDAY'S NEWS. If you subscribe, then as you walk
down the main street of % people will say, "There goes
#, the best-informed person in %." Wouldn't you like
that? Please, #, send me your subscription to
YESTERDAY'S NEWS right away.
J. S. Hardsell
Circulation Manager
Neither of these
Each of these characters characters could
could be the first character be the first character
of a substring of length 3 of a substring of length 3
II
c N C A T E N A T E
7 8 9 10 11
Expression Value
LI 11
L2 3
L1-L2 + 1 9
FIGURE 11-11. In a string of length Ll, there are Ll L2 + 1 possible substrings of length
L2.
N0T_F0UND «- FALSE
ELSE
I <- 1 + 1
END IF
END WHILE
IF N0T_F0UND THEN
POS *-
ELSE
POS «- I
END IF
END POS
) ) , ' '
IF I ji THEN
L <- LEN(LINE)
LINE «- LEFT (LINE, I- -1) + NAME + RIGHT(LINE, L-I)
END IF
J ^- POS(LINE, '%'
IF J ^ THEN
L «- LEN(LINE)
LINE +- LEFT(LINE J- -1) + CITY + RIGHT(LINE, L-J)
END IF
OUTPUT LINE
INPUT LINE
END WHILE
END FORM LETTER
Expression Value
REPLACE ( ' FORGET 'GET, '
*
, 'GIVE )
' FORGIVE
REPLACE (
' UNDISGUISED , DISGUIS '
' UNDISCOVERED
'DISCOVER'
RIGHKSTRING, L-I-Ll + 1)
STRING 1
\ f f
1 I 1 +l: L L
\ /
V
SUB_1
FIGURE 11-14. The substring SUB 1, which starts at position I and has a length Ll, divides
the string into three parts. The first part, the part that precedes SUB 1, has the length I
-
1. The second part, SUB 1 itself, has length Ll. The third part, the part that follows SUB
1, has length L - I - Ll - 1. where L is the length of the entire string.
Suppose that WORD contains a word that forms its plural by adding
8.
'S'. Write an assignment statement that will form the plural of the value of
WORD and store the result back into WORD.
Exercises 231
12. Describe the action of the function MID and give several examples of
its use.
13. Describe the actions of the functions LEFT and RIGHT. Give several
examples of the use of each.
14. Show how each of the examples with LEFT and RIGHT could also be
written using MID.
15. Describe the operation of the POS function and give several examples
of its use.
16. What does POS return if the string does not contain the sought-after
substring?
17. If the sought-after substring occurs more than once in the string being
searched, which occurrence does POS return the position of?
18. Give several examples of the LEN function, using strings that differ
only by the presence or absence of blank spaces.
1. Suppose a programming language has MID and LEN, but does not have
LEFT and RIGHT. Write the functions LEFT and RIGHT using MID and
LEN.
'3.5 + 2.61'
7-5'
'4.25*5'
'3.5/2'
command and translate it into two code numbers, one giving the position
of the verb in the list of all possible verbs and the other giving the position
of the object in the list of all possible objects. If either verb or object cannot
be found on the appropriate list, the procedure should inform the player
that it doesn't know the word in question.
10. Modify the algorithm of Exercise 9 so that the list of words produced
is in alphabetical orderand each word appears on the list only once no
matter how many times it occurs in the line.
SCHOLZNE
Next, write down the remaining letters of the alphabet in their normal
order, but omit any letters that are already in the key:
SCHOLZNEABDFGIJKMPQRTUVWXY
This is our cipher alphabet. Modify the algorithm of Exercise 12 to accept
a key and generate the cipher alphabet in the manner just explained.
14. A polyalphabetic substitution cipher uses more than one cipher alpha-
234 11 Character Strings
ABCDEFGHIJKLMNOPQRSTUVWXYZ
BCDEFGHIJKLMXOPQRSTUVWXYZA
CDEFGHIJKLMXOPQRSTUVWXYZAB
XYZABCDEFGHIJKLMXOPQRSTUVW
YZABCDEFGHIJKLMNOPQRSTUVWX
ZABCDEFGHIJKLMXOPQRSTUVWXY
To encipher, a key is written repeatedly above the plaintext. If the key is
15. In Exercise 14, the sequence in which the different cipher alphabets is
used repeats itself throughout the plaintext. This repetition provides a
method of breaking the cipher. One way to avoid this problem is to use a
pseudorandom number generator to determine which cipher alphabet will
be used for each plaintext character. Suppose the 26 cipher alphabets given
in Exercise 14 are numbered 1 through 26. For each character to be enci-
phered or deciphered, we can use the value of RAXDOM(26) to select the
cipher alphabet. Write an algorithm to encipher and decipher in this way.
You can use the implementation of RAXDOM given in Chapter 9, although
practical cipher programs use much more complex ways of generating
pseudorandom numbers. The starting value of SEED will serve as a key;
the same starting value must be used for deciphering a message as was
used for enciphering it.
©Cm^sf ft n
L
1 1
1 1
1 1
Stacks
is accessible. When a plate is added, the plates already on the stack are
"pushed down."
The cafeteria analogy gives rise to the terminology for adding an item
to or removing an item from the top of the stack. When an item is placed
on top of the stack, we say that it is pushed onto the stack. When an item
is removed from the top of the stack, we say that it is popped off the stack.
Figure 12-1 illustrates a stack and the PUSH and POP operations.
This analogy is faulty in one respect, however. When an item is
pushed on or popped off a stack, the remaining items on the stack do not
move, as the cafeteria plates do. The only item affected is the one pushed
on or popped off.
Items are popped off a stack in the reverse of the order in which they
were pushed on.
235
236 12 Stacks
7
8
3
PUSH (10)
POP
-i
""*
POP operation removes
item currently on top
7 of stack
8
FIGURE 12-1. A stack. PUSH places a new item on top of the stack; POP removes the top
top element of the stack (see Figure 12-2). A pointer, remember, is a vari-
able whose value designates a particular element of an array. The element
pointed to can be accessed by using the pointer as a subscript.
STACK
TOP 8
«§
5 7
H
m mm
Currently
unused. Will
be used when
additional
items are
m
m WM<
wm w.
wb
pushed on stack.
WMmmm.
WWw<
mmW>
wt. WA
w/////Mm//A
FIGURE 12-2. Representing a stack in memory. TOP points to the top item on the stack. Note
that the stack in this diagram is upsidedown compared to the one in Figure 12-1.
pops the top value off the stack and assigns it to ITEM.
Let the array STACK as well as TOP and SIZE be global variables. TOP
is the pointer to the top of the stack. SIZE is the number of elements in the
array STACK or, alternatively, the pointer to the last element of the array
STACK.
For the procedure PUSH, we have:
238 12 Stacks
Empty Stack
STACK
r:?
mmmm>,
to^^^
W////////////////A.
^^^^
W//////////////M
m^^^
ta^^^
mmy///////////,
W/////////////////,
W///////////////A
Full Stack
STACK
5
TOP
2
10 3
8
7
-I
17
4
12
9
FIGURE 12-3. Full and empty stacks. Attempting to add an item to a full stack causes over-
flow. Attempting to remove an item from an empty stack causes underflow.
+ 35
This is called prefix notation.
We can place the operator between the numbers:
3+5
3 5 +
240 12 Stacks
3-4*5
3+(4*5)
or
(3+4)*5
3 (4*5) +
3 4 5* +
(3+4) 5 *
and finally
3 4 + 5*
Notice two things:
12.2 Evaluating Arithmetic Expressions 241
first, since an operator can apply only to two immediately preceding num-
345*+ 34-5*
3 20 + 7 5 *
23 35
Here are some more examples of infix expressions and their RPX trans-
lations:
Infix RPN
3*5**2 3 5 2***
(2+4)*(5-3) 2 4 - 5 3 - *
3**2-2*3*5-5**2 32**23*5*+52**+
2-3*(4-5*(6~7) 234567 + + + * *
23-4*5 + 6*7 +
)
( (2 + 3)*4 + 5)*6-7
234567 + * + * +
2345 13*-*+
2 3 4 65 + * +
2 3 69 * +
2 207 -
209
Evaluation Using a Stack. The rule for evaluating an RPX expression using
a stack is this: Scan the expression from left to right. When an operand is
encountered, push it on the stack. When an operator is encountered, ap-
ply it to the top two elements of the stack. Replace those elements by the
result of the operation.
This is really the same as the rule previously given. We are just using
the stack to hold everything to the left of the next operator to be applied.
242 12 Stacks
are ignored.
3* 5*' '2 *
Expression— Infix RPS 3 5 2 •
Stack Expression
3 5 2**
3 5 2 ••
3 5 2 »«
3 5 2 "
3 25
75
Expression — Infix (2 - 4 1
• ( 5 - 3) - PN 2 4 - 5 3 - •
Stack Expression
2 4-5 3 -
2 4-5 3 -
2 4 - 5 3 -
6 5 3 -
6 5 3 -
6 5 3 -
6 2
12
** * - * *
RPS 3 2 2 3 £ 5 2
Stack Expression
3 2 »• 2 3 * 5 * - 5 2 » * -
3 2 • •
2 3 * 5 * - 5 2 » +
+
3 2 " 2 3 * 5 * - 5 2 •• -
9 2 3 * 5 * - 5 2 " +
9 2 3 * 5 * - 5 2 * * -
9 2 3 * 5 * - 5 2 •• -
* - *
+
9 6 5 5 2
9 6 5 * - 5 2 •• -
- ** -
9 30 5 2
39 5 2 " -
39 5 2 " -
39 5 2 •• -
39 25 +
64
244 12 Stacks
ALGORITHM EVALUATE
INPUT EXPRESSION
TOP «- (Stack is initially empty)
FOR I «- 1 TO LEN( EXPRESSION) DO
CHAR «- MID (EXPRESSION, I, 1)
IF (CHAR S= '0' AND (CHAR s£ '9') THEN
) (CHAR is ; i digit)
TOP <- TOP + 1
STACK (TOP) *- VAL CHAR (
'
the operands are in the same order in the RPN expression as they were in
the infix The order of the operators, however, has been
expression.
changed, so that the operators follow their operands and so that they are
in the order in which they will be applied.
Our job, then, is to reorder the operators. It turns out that we can do
this by using a stack. Each operator from the infix expression is pushed on
the stack before being placed in the RPN expression. But before an operator
is pushed on the stack, any operators having higher priorities are popped
off the [Link], the operators are reordered into the order in which
they will be applied, as dictated by the priorities. (We are forgetting about
parentheses for the moment.)
More explicitly, the rules for translating an infix expression into an
RPN expression are as follows (still ignoring parentheses for the moment):
Scan the infix expression from left to right. When an operand is encoun-
tered, move it immediately to the RPN expression. When an operator is
encountered, first remove operators from the stack and place them in the
RPN expression, until either the stack is empty or the priority of the top
operator is than the priority of the operator encountered in the expres-
less
sion. Then push the operator just encountered onto the stack.
When the entire infix expression has been processed, remove any re-
maining operators from the stack and place them in the RPN expression.
Figure 12-6 illustrates these rules. The following examples will clarify
them further:
12.3 Translating Arithmetic Expressions 245
4 2 + * 3-5
4 2 3 + * -5
4 7 3 2 4. * ** *c
4 7 ** *
3 2 _|_
4 7 3 2 ** * + *5
4 7 3 2 ** * - * 5
3 2 5 4 -j- * *
3 2 5 4 + *
4 ** * _j_
3 2 5
3 2 5 4 * * A.
FIGURE 12-6. The rules for translating infix expressions into RPN, where the infix expres-
sions do not contain parentheses.
246 12 Stacks
and placed in the RPX expression before - can be pushed on. Thus,
again, the higher priority * comes first in the RPX expression, and the
lower priority - comes second.
Xow for parentheses. An expression in parentheses is to be evaluated
independently of anything outside the parentheses. Only when the expres-
sion inside the parentheses has been completely evaluated can its value be
used to evaluate the expression outside the parentheses. This means that
when a left parenthesis is encountered, the evaluation of the current
expression must be suspended, to be continued only after the expression
inside the parentheses has been evaluated.
To our translation rules, then, we add the following: When a left pa-
renthesis is encountered, push it on the stack. When unstacking operators
with greater or equal priority than the operator encountered in the infix
expression, if a left parenthesis comes to the top of the stack, terminate
the unstacking. When a right parenthesis is encountered in the expression.
unstack operators until a matching left parenthesis is found on the stack.
Discard both parentheses and continue.
When a left parenthesis is put on the stack, a new ministack is started
whose bottom is at the left parenthesis. The expression inside the paren-
theses is translated using this ministack. When the matching right paren-
thesis is found, the ministrack is emptied and the parentheses are dis-
carded.
Figure 12-7 illustrates these rules.
The following is an example of a translation of an infix expression
containing parentheses:
RPh r
Stack Infix
4 *
(3-2)
4 * (
3-2)
5. When unstacking operators as a result of Rule 2,
if a left parenthesis is encountered on the stack.
stop the unstacking and push the operator encountered
in the infix expression onto the stack. (Note that
the left parenthesis is treated as if it were the bottom
of the stack . )
4 3 2 4 _ |
* ** -c
4 3 2 4 ** - * -5i
(
4 3 2 '4 ** * - ( + 5)
4 3 2 4 ** * - +
I 5)
6. When a right parenth esis is encountered in the infix
expression, unstack oper ators and place them in the RPN
expression until a 1 eft parenthesis is encountered.
Discard both parenth eses
2 3 4 5 * < + * 1-6
4 * +
2 3 5 * ( )+6
2 3 4 5 * + * 1 1-6
2 3 4 5 * - * -6
FIGURE 12-7. The additional rules needed to handle parentheses when translating infix
expressions into RPN"
2 3 (
+4*5 )*6
2 3 (
+ 4*5 )*6
2 3 4 (
+ *5)*6
2 3 4 (
+ * 5)*6
2 3 4 5 (
+ * )*6
2 3 4 5 (
+ )*6
2 3 4 5 (
)*6
2 3 4 5 *6
2 3 4 5 *6
248 12 Stacks
2 3 4 5*
2 3 4 5*
2 3 4 5*
Notice that the parenthesized expression 3 -4*5 is translated on a min-
istack extending from the left parenthesis to the top of the operator stack.
The * below the left parenthesis remains undisturbed until the entire pa-
renthesized expression has been translated. The left parenthesis shields
higher priority operators such as the * from lower priority operators such
as the ~ preventing the higher priority operators from being unstacked
,
too soon.
Now let us write an algorithm to translate from infix notation to RPX.
As before, we will assume that operands are single digits, and we will
ignore the possibility that the infix string may contain errors. These simpli-
fications will prevent the fundamental algorithm from being buried in a
wealth of removing these limitations makes a good exercise.
detail. Also,
Figure 12-8 shows an outline of the algorithm IXFIX-TO-RPX.
Before filling in the details in Figure 12-8. we must think a moment
about assigning numerical priorities to the operators. Let us assign priori-
ties to characters in the infix expression as follows (remember that in the
algorithms we are using * in place of **):
ALGORITHM INFIX-TO_RPN
(Input the infix expression INFIX; initialize
the stack to be empty and the reverse Polish
expression, RPN, to be the null string)
FOR I ^ 1 TO LEN( INFIX) DO
(Set CHAR to the Ith character of INFIX)
IF (CHAR is a digit) THEN
(Append CHAR to RPN)
ELSE IF (CHAR is an operator) THEN
(Unstack operators and append them to RPN
until (a) the bottom of the stack is
reached, (b) a left parenthesis is
encountered, or (c) an operator is
encountered whose priority is less than
the priority of CHAR)
(Push CHAR onto stack)
ELSE IF CHAR = then '
(
'
ELSE IF CHAR = )
THEN » '
END IF
END DO
(Unstack all remaining operators and append them
to RPN)
(Output RPN)
END INFIX TO RPN
)
t 4
* and. / 3
+ and - 2
through 9 1
other
ALGORITHM INFIX_TO_RPN
INPUT INFIX
TOP «-
RPN — '
'
T0P<^ T0P-1
END WHILE
TOP «- T0P + 1
STACK (TOP) «- CHAR
ELSE IF CHAR = THEN '
(
'
TOP «- T0P + 1
STACK (TOP) «- '( '
TOP «- T0P-1
END WHILE
TOP «- T0P-1
END IF
END FOR
WHILE TOP > DO
RPN «- RPN*' + STACK (TOP) '
TOP *- T0P-1
END WHILE
OUTPUT RPN
END INFIX TO RPN
250 12 Stacks
before C can return, and C must return before B can return (see Figure 12-
11).
Thus, return addresses are used in exactly the reverse of the order in
FIGURE 12-10. Subalgorithm (function and procedure) calls can be nested. One subalgorithm
can invoke another, which can in turn invoke still another, and so on.
ALGORITHM A
point
END A
PROCEDURE B
PROCEDURE C
PROCEDURE D
END D
12.4 Stacks and SubaJgorithms 251
Flow of Control
FIGURE 12-11. The order in which subalgorithms return is the reverse of the order in which
they are called.
which they were saved. Since items are popped from a stack in the reverse
of the order in which they were pushed on, a stack can be used to store
subalgorithm return addresses. Figure 12-12 illustrates this use of a stack.
In some systems, storage for the values of the local variables of a sub-
algorithm is allocated when the algorithm is called and freed when the
algorithm returns. This scratch pad storage can be organized as a stack.
When an algorithm is called, a block of storage called a stack frame is
created on top of the stack. The stack frame contains storage for:
After D returns
After B is called
After C returns
After C is called
(empty stack)
After B returns
After D is called
^©wn®\^7 ©(iQdgiferag)
1. Explain the behavior of a stack in terms of a stack of physical objects,
such as papers, books, or cards.
3. What do the words push and pop refer to in connection with stacks?
Review Questions 253
FIGURE 12-13. A stack frame contains the storage needed during a particular call to a subal-
gorithm.
6. Describe how a stack is represented in memory. How are the PUSH and
POP operations implemented?
12. In translating from infix to RPN, which are reordered, the operands or
the operators?
13. Give the rules for translating into RPN an infix expression that does
not contain parentheses.
Stack Stack
frame frame
for for
C C
Stack Stack
frame frame
for for
B B
Stack Stack
frame frame
for for
A A
FIGURE 12-14. When a subalgorithm is called, its stack frame is pushed onto the stack.
When it returns, its stack frame is popped off the stack.
Exercises 255
17. What property of subalgorithms allows a stack to be used for their re-
turn addresses?
19. When is a stack frame created? When is it destroyed (that is, no longer
used)?
20. Make a general statement about the uses of stacks. Give two examples
that illustrate the general statement.
I2z%?®\mm
1. In evaluating an RPN expression, the stack may overflow if the expres-
sion is too complex. If the expression is incorrectly formed, the stack may
underflow, as for
3 4 2 + * +
Or, when the evaluation is finished, there may be more than one value on
the stack, as for:
3 4 2 +
CHARACTER RANK
i i
4
i * i
3
'/' 3
*
+ '
2
i i
2
'0' 1
1' 1
'2' 1
'3' 1
'4' 1
'5' 1
'6' 1
'7' 1
'8' 1
'9' 1
( sentinel
256 12 Stacks
Records
So far, we have studied two kinds of data items: (a) those that can be
broken down into smaller parts, and (b) those that cannot be broken down.
Arrays and strings are examples of the first kind of data item. A one-
dimensional array is made up of elements. A two-dimensional array is
made up of rows and columns, and each row and column is made up of
elements. A string is made up of characters. These data items are called
composite.
Real numbers and characters, on the other hand, are examples of data
items of the second kind. Neither of these can be decomposed into any
smaller parts. Such data items are called elementary or atomic, the latter
coming from the Greek word for "indivisible."
(What is elementary and what is composite depends on the level at
which we are working. A machine-language programmer might consider
characters and real numbers as composite, since both can be decomposed
into bits. But this decomposition is not made in most higher level lan-
guages. Higher level language programmers are "unaware of" the bit struc-
ture of characters and real numbers.)
An array is a uniform data structure. That is, its elements are all sim-
ilar toone another. Each element is of the same data type. The elements
are distinguished only by their positions in the array; otherwise, none
stands out from the others. Arrays are often processed in such a way that
the same operations are carried out on each element. The same remarks
apply to characters in a character string.
A record is also a composite data item, but it may be nonuniform. The
257
258 13 Records
piece of information.
For instance, consider the student record shown in Figure 13-1. We
can display its structure in outline form as follows:
1 STUDENT
2 NAME
2 GPA
2 CLASS
then STUDENT will have the value shown in Figure 13-2. On the other
hand, if we make the assignments
STUDENT
NAME
GPA
CLASS
13.1 Record Structures 259
Assignments
GPA ^ 3.5
CLASS «- 'JUNIOR'
STUDENT
FIGURE 13-2. Assignments to the components of STUDENT and the resulting value of STU-
DENT.
260 13 Records
Assignments
GPA ^2.8
CLASS «- 'FRESHMAN'
STUDENT
NAME 'JACK JONES'
GPA 2.8
CLASS ' FRESHMAN
FIGURE 13-3. Three more assignments to the components of STUDENT and the resulting
value of STUDENT.
1 EMPL0YEE_REC0RD
2 NAME
2 HOURS
2 RATE
1 PAYR0LL_REC0RD
2 NAME
2 HOURS
2 RATE
2 GROSS_WAGES
names a component of only one record. But what about NAME, HOURS,
and RATE? When we make an assignment to NAME, do we refer to NAME
in EMPLOYEE_RECORD or NAME in PAYROLL_RECORD? When
HOURS occurs in an expression, should the value from EMPLOYEE REC-
ORD or the value from PAYROLL_RECORD be used?
When a name appears as a component more than one record,
of
that name must be qualified by the name of the record. The record name is
13.2 Declarations 261
written first and the component name second; the two are separated by
a dot.
Thus, instead of NAME we must write either EMPLOYEE
[Link] orPAYROLL_RECORD.XAME; instead of HOURS we
must write either EMPLOYEE_RECORD.HOURS or PAYROLL_
RECORD. HOURS, and so on. But we can write just plain GROSS_
WAGES, GROSS_WAGES occurs in only one record (though PAY-
since
ROLL_RECORD.GROSS_WAGES is legal if we wish to remind the reader
that GROSS_WAGES is a component of PAYROLL_RECORD).
Qualified names tend to be long and clumsy to write, a fact that dis-
courages using the same name as a component of more than one record.
Note that the word "record" can be used in two different ways. In the
first usage, "record" refers to a form or structure. Thus, the "record"
1 STUDENT
2 NAME
2 GPA
2 CLASS
gives the form or structure that a value of STUDENT must have. On the
other hand, we can
use "record" to refer to a particular set of data. Thus,
('MARY JONES', 3.5, 'JUNIOR'] is the "student record" for Mary Jones.
To be precise, we could call the form of a record a record structure or
a record type and the data for a particular individual a record vaiue. But to
keep from being so long-winded, we will usually just speak of a record
and let the context show whether we are speaking of a structure or a value.
13.2 Declarations
(The exact form of the statement would vary from one language to another.)
Also, we are usually required to declare the sizes of arrays and the
data types of their elements. Thus,
So far, we have
not required such declaration statements in the algo-
rithmic language. For one thing, it is usually obvious what kind of values
a variable can have from the words that make up the variable name and the
context in which the variable is used. EMPLOYEE NAME surely has
string values, and HOURLY RATE surely has real-number values. Decid-
ing on the number of elements in an array is a meaningless exercise when
we are composing an algorithm and have yet to decide on how much data
is to be processed or even exactly what the array is to be used for.
DECLARE 1 STUDENT
2 NAME
2 GPA
2 CLASS
DECLARE 1 STUDENT
2 NAME: STRING
2 REAL
GPA:
2 CLASS: STRING
Most programming languages require this data type specification. But, fol-
lowing the philosophy just given, we will usually omit the data types,
letting context or comments in the text clarify the data type of each com-
ponent.
DECLARE 1 STUDENT
2 NAME
3 FIRST
3 INITIAL
3 LAST
2 ADDRESS
3 STREET
3 CITY
3 STATE
3 ZIP
2 GPA
2 CLASS
13.3 More Complicated Records 263
STUDENT
FIGURE 13-4. The name STUDENT refers to the entire record. On level 1, the record is con-
sidered as a whole and is not divided into parts.
STUDENT
NAME
ADDRESS
GPA
CLASS
264 13 Records
vided into FIRST, INITIAL, and LAST; and ADDRESS can be further sub-
divided into STREET, CITY, STATE, and ZIP, as shown in Figure 13-6.
The level numbers designate different levels of subdivision. Level 1
where the entire record is considered
refers to the situation of Figure 13-4,
as a whole and no subdivision whatever is done. Level 2 refers to the sub-
divisions of the entire record. Level 3 refers to subdivisions of level 2
items. Higher level numbers refer to still further subdivisions.
Group items such as NAME and ADDRESS are records in their own
right. That they are composite data structures that can be subdivided
is,
STUDENT
STUDENT. NAME
STUDENT. NAME. FIRST
STUDENT . NAME INITIAL
.
FIGURE 13-6. On level 3, some of the level-2 items of STUDENT are further subdivided.
STUDENT
FIRST
M AMI? INITIAL
LAST
STREET
CITY
ADDRESS
STATE
ZIP
GPA
CLASS
13.3 More Complicated Records 265
STUDENT
STUDENT ADDRESS
STUDENT ADDRESS STREET .
STUDENT [Link]
STUDENT GPA
STUDENT CLASS
In a completely qualified name, names other than the final one are
called qualifiers. In [Link], for instance, STUDENT and
NAME are qualifiers.
We may abbreviate a completely qualified name by omitting qualifiers,
provided no confusion results. No confusion will result if the name is an
abbreviation of, at most, one completely qualified name. An abbreviated
name that can be an abbreviation of more than one completely qualified
name is ambiguous and hence illegal.
For instance, consider the record defined by:
DECLARE 1 A
2 B
3 X
3 Y
2 C
A Y
B C
X
DECLARE 1 E
2 B
3 X
3 Y
2 C
Record A Re cord
A E
A.B E.B
A.X E.X
A.Y E.Y
A.C E.C
long as each item in the record has a unique completely qualified name,
no confusion will result. Such duplications may seem like an invitation to
confusion, but they can reasonably occur in records such as:
DECLARE 1 ENROLLMENT
2 STUDENT
3 NAME
3 ADDRESS
2 PARENTS
3 FATHER
4 NAME
4 ADDRESS
3 MOTHER
4 NAME
4 ADDRESS
NAME and ADDRESS each occurs three times in this record. The com-
pletely qualified names for each occurrence of NAME are
13.4 Arrays of Records 267
STUDENT NAME .
The second and third occurrences have the following most abbreviated
forms:
FATHER NAME.
MOTHER. NAME
ENROLLMENT NAME .
PARENTS NAME .
NAME
are all invalid, since each abbreviates more than one completely qualified
name.
ADDRESS in this record is qualified in the same way as XAME.
Notice that the record definition
DECLARE 1 A
2 B
3 X
3 Y
2 B
3 U
3 V
is invalid, since the two level-2 items have the same completely qualified
name, A.B A record definition is valid if each component has a unique
we can have arrays whose elements are real numbers and strings,
Just as
we can have arrays whose elements are records. We can declare such an
array of records as follows:
DECLARE 1 B00K(5)
2 TITLE
2 AUTHOR
2 PUBLISHER
1
268 13 Records
The advantage of the second form is that we can drop unneeded qual-
ifierswithout interfering with the subscripting. Thus, [Link](l) can
be abbreviated to TITLE(l), [Link](2) can be abbreviated to AU-
THOR^), and [Link](3) can be abbreviated to PUBLISHERS).
The following table shows three equally valid ways of referring to the com-
ponents of BOOK(l).
FIGURE 13-8. BOOK is an array of five elements. Each element is a record with three com-
ponents.
BOOK
TITLE
ROOK ( 1 I
AUTHOR
_ PUBLISHER
["TITLE
PHCW
DUUI\ 1
(
*>
<=_ 1
i
AUTHOR
L PUBLISHER
"TITLE
rdok ( *; I AUTHOR
_ PUBLISHER
"TITLE
r>nnv
duuis. i
l
a
*i )
\
AUTHOR
_ PUBLISHER
"TITLE
DUUA 1 O AUTHOR
_ PUBLISHER
)
BOOK
BOOKd) .TITLE
BOOKd ) . AUTHOR
BOOKd . PUBLISHER
B00K(2) .TITLE
B00K(2) . AUTHOR
B00K(2) . PUBLISHER
BOOK (3) .TITLE
B00K(3) . AUTHOR
B00K(3) . PUBLISHER
BOOK(4) .TITLE
BOOK (4) . AUTHOR
BOOK (4) . PUBLISHER
B00K(5) .TITLE
B00K(5) . AUTHOR
B00K(5) . PUBLISHER
FIGURE 13-9. We can refer to the elementary items of BOOK by combining qualification with
subscripting.
INPUT AUTHORS_NAME
FOR I <- 1 TO 5 DO
IF AUTHOR(I) = AUTHORS_NAME THEN
OUTPUT TITLE(I)
END IF
END FOR
DECLARE 1 AUTHOR
2 NAME
2 B00KS(5)
3 TITLE
3 PUBLISHER
270
AUTHOR
vjuit
Vi AM 11.
F~ TITLE
0UUK.0 ( 1 )
L_ PUBLISHER
F~ TITLE
L»UUl\o I <c )
_ PUBLISHER
r~ TITLE
L_ PUBLISHER
r> r\r\ w* 4i F~ TITLE
DUU1S.O i
1 )
i
L_ PUBLISHER
F~ TITLE
BOOKS! 5 PUBLISHER
As before, we can move the subscript to the right of the entire com-
pletely qualified name:
TITLE(I)
PUBLISHER(I)
DECLARE 1 AUTH0R(3)
2 NAME
2 B00KS(5)
3 TITLE
3 PUBLISHER
AUTHOR(I) .NAME
AUTHOR I BOOKS J
( ) . ( ) . TITLE
AUTHOR I BOOKS J
( ) . ( ) . PUBLISHER
AUTHOR
M AMF
BOOKS!
TITLE
1) 1
1 PUBLISHER
TITLE
B00KS(2) 1
AIITHDP ( 1 I
L_ PUBLISHER
B00KS(3) TITLE
PUBLISHER
1
TITLE
BOOKS (4) 1
I
PUBLISHER
TITLE
BOOKS 5 ( )
1— PUBLISHER
\
TITLE
BOOKS(l) 1
L_ PUBLISHER
B00KS(2) 1
TITLE
rtllTHDP /
*">
i
1 PUBLISHER
B00KS(3) 1
TITLE
1 PUBLISHER
TITLE
BOOKS (4)
PUBLISHER
BOOKS (5 i
TITLE
PUBLISHER
M AMF
INHIVICj
TITLE
BOOKS! 1)
PUBLISHER
AIITHDP ( *; 1
B00KS,2)
—E PUBLISHER
B00KS(3
'HI PUBLISHER
BOOKS (4) T~ TITLE
L_ PUBLISHER
B00KS(5)
TITLE
— 1
1 PUBLISHER
FIGURE 13-11. An array, each of whose elements contains another array as a component.
AUTHOR. NAME! I)
AUTHOR. BOOKS. TITLE I, J) (
NAME( I)
TITLE! I, J)
PUBLISHER! I, J)
tant how many elements the array will have. On the other hand, we do
need to know which components of a record are arrays and which are not,
particularly if we are to use abbreviated names. For this reason, we some-
times write declarations with the array sizes omitted but with the sur-
rounding parentheses included to indicate which components are arrays:
DECLARE 1 AUTHOR ( )
2 NAME
2 BOOKS ( )
3 TITLE
3 PUBLISHER
This notation indicates that AUTHOR and BOOKS are arrays, but does not
tell how many elements are in each array.
DECLARE 1 AUTH0R(3)
2 NAME
2 NUMBER_WRITTEN
2 BOOKS (NUMBER_WRITTEN)
3 TITLE
3 PUBLISHER
In each element ofAUTHOR, the size of the array BOOKS depends on the
value of NUMBER_WRITTE\. In different elements, NUMBER_WRIT-
TEN will have different values and BOOKS will have different sizes. The
elements of AUTHOR are called variable-length records, since the size var-
ies from one record to another. Figure 13-12 illustrates variable-length rec-
ords.
INPUT STUDENT
would read in values for all the elementary items in STUDENT, while
OUTPUT AUTHOR
would print out the values of all the elementary items of AUTHOR.
Since the data read in or printed out is simply a list of values, we
must specify a correspondence between those values and the elementary
items of a record. The correspondence rule is simple: Elementary items are
read in or printed out in the same order in which they appear in the record
declaration. Thus, the first data value read or printed corresponds to the
13.5 Input, Output, and Assignment 273
AUTHOR
NAME —
AUTHOR (1 NUMBER. WRITTEN
TITLE
BOOKS
PUBLISHER
NAME
NUMBER ^WRITTEN
— TITLE
AUTH0R(2)-
BOOKS _
_~~
_ PUBLISHER
TITLE
BOOKS
_ PUBLISHER
NAME —
NUMBER- WRITTEN-
BOOKS TITLE
(
AUTHOR (3 PUBLISHER
TITLE
BOOKS
£ PUBLISHER
TITLE
BOOKS (3
L_ PUBLISHER
FIGURE 13-12. An array of variable-length records. In each element of AUTHOR, the value
of NUMBER_WRITTEN determines the size of the array BOOKS.
first elementary item in the record declaration, the second data value read
or printed corresponds to the second elementary item, and so on.
Consider the following:
DECLARE 1 INVENTORY_ITEM
2 STOCK_NUMBER
2 PRICE
2 QUANTITY_ON_HAND
The statement
INPUT INVENTORY_ITEM
is then equivalent to
OUTPUT INVENTORY_ITEM
is equivalent to
DECLARE 1 A
2 B
3 C
4 D
4 E
3 F
4 G
4 H
2 I
INPUT D, E, G, H, I
OUTPUT D, E, G, H, I
Note that values are inputted and outputted elementary items oniy.
for the
The same principle applies to assignment. Thus,
is equivalent to
D «- 5
E «- 10
G «- 15
H «- 20
I «- 25
Also, if P is defined by
DECLARE 1 P
2 Q
2 R
3 S
3 T
2 U
2 V
then
P «- A
is equivalent to
Re view Qu estions 275
Q«_ D
s «- E
T «- G
U <r- H
V 4^- I
[^@WD(gM (SJQfl®glSD®l
3. What is a record?
5. What are the numbers that appear before each item in a record descrip-
tion called? What function do they serve?
8. What is a declaration?
12. What is the rule for abbreviating a completely qualified name? Under
what conditions would an abbreviation be invalid?
13. Give two alternate ways in which BOOK(I). TITLE can be written.
AUTHOR (
I ) . BOOKS (
J ) . TITLE
can be written.
18. On input, what is the rule for assigning the values read to the elemen-
tary items of a record?
19. On output, what is the rule for printing out the elementary items of a
record?
20. When record names appear on both sides of the assignment operator,
give the rule by which the values of the elementary items of the record on
the right are assigned to the elementary items of the record on the left.
VZ^s^th^
The following record is referred to in Exercises 1-6:
DECLARE 1 H
2 I
3 X
3 Y
2 J
2 K
3 X
3 Y
INPUT H
and
OUTPUT H
Exercises 277
Note that qualified names such as K.X can be used in INPUT and OUTPUT
statements.
The following array of records is referred to in Exercises 7-10:
DECLARE 1 A( )
2 B
2 C( )
3 X
3 Y
10. Suppose that the array A contains 100 elements and, in each element
of A, C contains 25 elements. Modify the given declaration to reflect this
additional information.
©tonoife 3
m
Linked Lists
—
divided into parts that can be described separately then the record can
reflect this structure.
The only structure we have so far for representing relationships among
entities is the array. The relationships represented by arrays are those pres-
ent in lists, tables, books of tables, and so on. In a one-dimensional array,
for instance, every element except the last is related to the element that
follows it. And
every element except the first is related to the one that
precedes it. But while relations such as precedes and follows can be ex-
tremely useful, they fall far short of encompassing the rich and varied re-
lationships among objects in the real world.
One way to express more complex relationships is to link together rec-
ords that are related in some particular way. The linking is accomplished
278
14.1 SingJy Linked Lists 279
We will find that these lists are in many ways more flexible than arrays.
Also, their study will prepare us for the more complicated plexes taken up
in later chapters.
Fundamental Properties. Consider the array shown in Figure 14-2 and de-
fined by:
DECLARE 1 CELL( )
2 VALUE
2 LINK
FIGURE 14-1. Using a pointer to link together two records in an array. The Z component of
A(2) points to A(4).
A
DECLARE 1 A(5) ~ X
A M
2 X A( 1 \
) Y
2 Y Z
2 Z X
A(2) Y
L_ z 4
X
J/7|
A( o I Y
_ Z
X
A(4) Y
Z
X
R
R(D
A 1 \
) Y
_ Z
280 14 Linked Lists
DECLARE 1 CELL(5)
2 VALUE
2 LINK
CELL
VALUE
OfciLL 1
( )
_LINK
PFT 9 VALUE
T
_ LINK
1 1
PITT T / 7 \
VALUE
_~ LINK
VALUE
_ LINK
^~
'~
PITT T S --
VALUE
_ LINK
( 1
UEjl-iLi 1 <3 1
FIGURE 14-2. The array CELL. Although the text leaves unspecified how many elements
CELL contains, five elements are assumed here for the sake of illustration.
on the list. More specifically, the value of LINK is the subscript of the next
record.
The last record on the list has as the value of LINK some sentinel
whose value cannot be confused with a subscript. A zero or negative value
would serve; zero is often used. We will denote this sentinel value by NIL.
We must somehow designate the first element of the list. We use a
variable FIRST whose value points to the first element of the list.
Figure 14-3 illustrates a linked list. Note the order in the linked list is
not the same as the order of the cells in the array. In fact, the cells can be
scattered throughout the array in a random fashion. The only purpose of
organizing the cells into an array is to associate with each a unique sub-
script value. These subscript values are then used to link one cell to an-
other.
In fact, it is best to forget about the array structure of the cells entirely
and depict a linked list as shown in Figure 14-4. This diagram shows how
the cells are linked, which is the important thing. Exactly where each cell
happens to be located in the array is something we can usually forget
about.
The first cell on a linked list must always be treated as a special case.
The reason is that the first cell is pointed to by FIRST, which is not a
component of a cell and cannot be accessed in the same way as the other
LINK components. Because of this, the first cell is often singled out as the
header record. The VALUE part of the header is not used to hold one of
14.1 Singly Linked Lists 281
FIRST
3
CELL
VALUE -*
CELL(l)
_ LINK 4
~ VALUE
CELL(2)
L LINK
CELL 3 (
~"
VALUE V
)
L LINK l —
CELL (4 VALUE ^*
J
L LINK
~ VALUE
CELL(5)
L LINK
FIGURE 14-3. A linked list in the array CELL. The elements of the list are CELL(3j, CELL(2),
and CELL(4), in that order. FIRST contains a pointer to CELL(3], the first element of the list.
CELL(4), LINK contains 0, the end-of-list sentinel.
header is shaded to indicate its unique status. Also note that a diagonal
line in the LINK component of the last cell stands for NIL.
SEARCH (F, V, Q)
to search a list for the cell containing a given value.F is the pointer to the
header of the list to be searched, and V is the value sought after. When the
procedure returns, Q will point to the cell whose VALUE part is V, if such
FIGURE 14-4. A linked list drawn without regard for the locations of the elements in the
array CELL. The diagonal line in the LINK component of the last element represents the end-
of-list sentinel, which is called NIL.
VALUE
FIRST
*
'
FIRST
— '/////////////.
r ___
-"
FIGURE 14-5. A linked list with a header. The VALUE component of the header does not
contain useful data. The header serves only to provide a list cell whose LINK component
points to the first cell of the list that does contain useful data.
a cellwas found. If no such cell was found, the value of Q will be NIL (see
Figure 14-6).
We can outline the algorithm as follows:
PROCEDURE SEARCH(F, V, Q)
(Set Q to point to the header of the list to be searched,
(Initialize the flag N0T_F0UND to TRUE)
WHILE (Q ^ NIL) AND N0T_F0UND DO
(Set Q to point to the next cell on the list)
(If VALUE(Q) = V then set N0T_F0UND to FALSE)
END WHILE
END SEARCH
Theflag NOT FOUND is used to stop the search when the sought-
aftervalue is found. If the end of the list is reached before the sought-after
value is found, the search stops and the value NIL is returned for Q.
Since F points to the header of the list to be searched,
Q ^ F
14-6. Situation after a call to the procedure SEARCH. Note that, for convenience in
FIGURE
drawing, a pointer can be shown pointing to any part of a cell. What part of the cell it points
to is not significant.
VALUE component of
this cell contains item
being searched for
14.1 SingJy Linked Lists 283
Q «- LINK(Q)
Notice that this is executed once before VALUE is compared with V, thus
moving Q past the header, which is not to be searched. If there were no
next cell, the value of Q would be NIL. In that case, the repetition termi-
nates, and the procedure returns with the value of Q equal to NIL.
It is assumed that CELL —
and hence VALUE and LINK was declared —
GLOBAL in the main algorithm, so that these names are available to the
procedures. Each procedure also declares as GLOBAL whichever names it
needs access to:
PROCEDURE SEARCH(F, V, Q)
GLOBAL VALUE, LINK
Q «- F
N0T_F0UND *- TRUE
WHILE (Q ^ NIL) AND N0T_F0UND DO
Q «- LINK(Q)
IF VALUE(Q) = V THEN
N0T_F0UND <- FALSE
END IF
END WHILE
END SEARCH
We will see presently that some operations require access to the cell
preceding the one that is to be operated on. Deletion is an example of such
an operation. But in a singly linked list we can only work through the list
in a single direction, the direction in which the pointers point. There is no
provision for going backwards in the list.
Therefore, the SEARCH procedure will be more useful if it returns not
only a pointer to the cell found but to the preceding cell as well. We can
accomplish this with a pointer P that throughout the search will always be
one cell behind Q. When the procedure returns, Q will point to the cell
found, and P will point to the preceding cell, as shown in Figure 14-7.
The procedure SEARCH is easily modified to include P:
PROCEDURE SEARCH(F, V, P, Q)
GLOBAL VALUE, LINK
Q <- F
N0T_F0UND <- TRUE
WHILE (Q ? NIL) AND N0T_F0UND DO
P «- Q
Q «- LINK(Q)
IF VALUE(Q) = V THEN
N0T_F0UND <- FALSE
END IF
END WHILE
END SEARCH
284 14 Linked Lists
VALUE component of
this cell contains
item being searche d for
, 1
r
i
r
p Q
FIGURE 14-7. In addition to the pointer Q to the cell found, it's often convenient to have
SEARCH also return a pointer P to the cell preceding the one found.
FIGURE 14-8. The procedure ACCESS returns a pointer Q to the Ith cell on the list as well as
Ith cell
on 1 ist
i
I
p Q
1
14.1 Singly Linked Lists 285
PROCEDURE ACCESS! F, I, P, Q)
GLOBAL LINK
Q - F
FOR J <- 1 TO I DO
P «- Q
Q «- LINK(Q)
END FOR
END ACCESS
needed.
Note that several linked lists can exist in CELL at the same time, so
that a cell removed from one list can later be added to another.
To implement these ideas, we need some way of keeping track of the
currently unused elements of CELL. We do this by linking all of the unused
elements together in a free-space list. A global variable FREE points to the
first cell of the free space list. (The free space list has no header.) Figure
14-9 shows the free space list as it might actually exist in CELL.
At the beginning of a list-processing algorithm, all of the elements of
CELL are linked together in one free-space list (see Figure 14-10). As lists
are built and modified, all needed cells are obtained from the free-space
list. When a cell is no longer needed, it is returned to the free-space list.
The procedure XEW(P) obtains a new cell from the free-space list and
FIGURE 14-9. The free-space list. Shaded cells are currently in use. Unshaded ones are avail
able for use. The available cells are linked together to form the free-space list.
FREE
CELL
VALUE
CELLd LINK
CELL (2)-
VALUE
LINK
CELL (
CELL (4
CELL I
) )
FREE
1
CELL
CFT T M i
VALUE ^
L LINK _
2
CELL 2 1
VALUE 1
L LINK z
\J
CELL! 3)
VALUE
_
CELL (4 i
L
LINK
VALUE
LINK
A
BJ ,
— J
CELL 5 (
VALUE
)
_ LINK
FIGURE 14-10. At the start of a list processing algorithm, all the cells of CELL are linked
together to in a single free-space list.
sets P to point to it. [NEW prints an error message if there are no cells left
PROCEDURE NEW(P)
GLOBAL LINK, FREE
IF FREE = NIL THEN (Free-space list is empty)
CALL ERROR! 'FREE SPACE EXHAUSTED'
ELSE
P <- FREE
FREE «- LINK (FREE)
END IF
END NEW
PROCEDURE RECYCLE(P)
GLOBAL LINK, FREE
LINK(P) «- FREE
FREE <- P
END RECYCLE
FREE
FREE
FIGURE The procedure NEW(P) gets a new cell from the free-space list and sets P to
14-11.
point to it. illustration shows the effect of each of the two statements of NEW(P) that
The
manipulate the free-space list. P *— FREE sets P to point to the same cell that is pointed to by
FREE. FREE «- LIXK(FREE) is trickier to interpret. First find the cell pointed to by FREE.
Follow the link component of this cell to find the cell pointed to by LINK(FREE). Set FREE to
point to this cell.
) ) )
FREE
r _______
i—
i
P
*i
Figure 14-12. The procedure RECYCLE(P) returns the cell pointed to by P to the free-space
list. To interpret the statement LINK(P) *— FREE, locate the link component of the cell pointed
to by P. Set this link component to point to the same cell that is pointed to be FREE.
PROCEDURE INSERT_AFTER(V, P)
(Get a new cell and set Q to point to it)
(Set the link of the new cell to point to the cell
following the one pointed to by P)
) )
r-
i r r
p
f
Q
m
C r r
P
I
r
P
t
Q
iL
FIGURE 14-13. The procedure INSERT_AFTER(V, P) inserts a cell containing the value V
after the cell pointedto by P. To interpret LINK(QJ <- LINK(P), set LINK(QJ, the link com-
ponent of the cell pointed to be Q, to point to the cell that is now pointed to by LINK(P), the
LINK component of the cell pointed to by P.
) )
PROCEDURE INSERT_AFTER(V, P)
GLOBAL VALUE, LINK
CALL NEW(Q)
LINK(Q) «- LINK(P)
LINK(P) «- Q
VALUE(Q) «- V
END INSERT_AFTER
The procedure DELETE AFTER(P) deletes the cell following the one
pointed to by P.
Normally we will have found the cell we wish to delete using
SEARCH. To delete it with DELETE_AFTER, we need a pointer to the
preceding cell. This is why we modified SEARCH to return a pointer not
only to the cell located by the search, but to the preceding cell as well.
Figure 14-14 illustrates the operation of DELETE AFTER. We can out-
line the algorithm as follows:
PROCEDURE DELETE_AFTER P (
PROCEDURE DELETE_AFTER(P)
GLOBAL LINK
Q «- LINK(P)
IF Q / NIL THEN
LINK(P) *- LINK(Q)
CALL RECYCLE(Q)
END IF
END DELETE_AFTER
14.2 Rings 291
_J^ _r
p
t
cell to be deleted)
"
P
1
L
_r
P
1
c ALL R ECYCLE(Q)
(Return the d< sleted cell
to the f ree sp >ace list j
FIGURE 14-14. The procedure DELETE_AFTER deletes the cell following the one pointed to
by P.
14.2 Rings
An important limitation of a singly linked list is thatone can only go for-
ward in it. in the direction of the links. There is no provision for moving
in the other direction.
A simple solution is to provide a link from the last cell on the list back
292 14 Linked Lists
to the header, as shown in Figure 14-15. The resulting list is called a ring.
We can only move in one direction in a ring. But at least when we get
still
to the end, we can go back to the beginning and examine those cells pre-
ceding the one we started with. Specifically, we can start the search of a
ring atany cell, instead of just at the header.
With a singly linked list, there is no problem in distinguishing the
header from other cells. The header is always the first cell examined. In a
ring, where the search may begin anywhere, we must have some way of
identifying the header when we come to it. We will include in each cell a
component IS HEADER which will have the value TRUE for the header
and the value FALSE for every other cell. Figure 14-16 shows a ring in
which each cell has the component IS HEADER. In the illustration, TRUE
and FALSE are abbreviated to T and F.
We must redefine the array CELL for rings to include the component
IS HEADER in each record:
DECLARE 1 CELL( )
2 VALUE
2 IS_HEADER
2 LINK
To search a ring for a given value, we start with an arbitrary cell and
examine successive cells until we find the value we are looking for or until
we get back to our starting point. When the header cell is encountered, it
must be skipped over since it is not used to store an item on the list.
The procedure SEARCH(F, V, P, QJ searches a ring for the value V
starting at the cell pointed to by F, which may be any cell. When SEARCH
returns, Q points to the cell containing the desired value, and P points to
the preceding cell. If the sought-after value is not found, the value of Q
is NIL:
PROCEDURE SEARCH(F, V, P, Q)
GLOBAL VALUE, IS_HEADER, LINK
Q «- F
FOUND «- FALSE
REPEAT
P <- Q
Q <- LINK(Q)
IF NOT IS_HEADER(Q) THEN
IF VALUE(Q) = V THEN
FOUND «- TRUE
END IF
END IF
UNTIL (Q = F) OR FOUND
IF NOT FOUND THEN
Q «- NIL
END IF
END SEARCH
—
x±y///////w _p- j- r*
The search actually begins with the cell following the one pointed to
by F and continues on around the ring. Each cell except for the header —
is examined to see if its VALUE equals the value of V. If such a cell is
found, the repetition terminates, and the procedure returns with Q point-
ing to the cell found and P pointing to its predecessor. When we reach the
cell pointed to by F, we have searched the entire ring. If the value has not
been found, the repetition terminates, and the procedure returns with Q
equal to NIL.
A ring is most useful when we have pointers to cells other than the
header and so will not always begin a search with the header. For instance,
the values on the ring could be in alphabetical order. We could maintain
an index, which would contain a pointer to the first cell whose value starts
with 'A', a pointer to the first cell whose value starts with 'B', and so on.
Or, by giving a cell more than one LINK component, we can let it be on
more than one list at the same time (see Figure 14-17). We may reach a cell
by searching one list. Then we may wish to search some other list that cell
is on, beginning of course with the cell at hand.
the preceding cell; the other points to the following cell. The resulting list
is said to be doubly linked.
In a doubly linked list, we can move in either direction with ease. On
the other hand, a doubly linked list requires more memory than either a
singly linked list or a ring, since each cell must contain two link compo-
nents instead of one.
Figure 14-18 shows a doubly linked list. Note that the doubly linked
list is also a ring, since the last cell is linked to the header. A doubly
FIGURE 14-16. A ring in which each cell has the component IS_HEADER. TRUE is abbre-
viated to T and FALSE to F.
FIRST
-i:'//////Mi y p_p t
r-
1
>
294 14 Linked Lists
FIRST_A
V/////////A
FIRST_B
Y/////////A
FIGURE 14-17. A cell can belong to more than one ring. A cell reached by a search along one
ring can become the starting point for a search along the other ring.
linked ring provides the greatest possible flexibility in moving about on the
list.
For a doubly linked list, we need two links per cell. Also, since the
doubly linked list may be used as a ring, we need the flag IS HEADER to
identify the header cell:
DECLARE 1 CELL( )
2 VALUE
FIGURE 14-18. A doubly linked list. Notice that a doubly linked list is also a ring, since the
header and the last element are linked.
FIRST
F F r*" F
^_ '////////At
r\r 1\ 1
~"
)
2 IS_HEADER
2 LEFT_LINK
2 RIGHT_LINK
Searching. In searching a doubly linked list, one uses only one set of
since we never move around on the free-space list but just add or remove
cells from its beginning. Thus, we can use only the right links to build the
free-space list.
The procedures NEW and RECYCLE for doubly linked lists, then, will
differ from those for singly linked lists only in notation. It is left as an
exercise to write NEW and RECYCLE for doubly linked lists.
Insertion and Deletion. With insertion and deletion, we reach the point
where we will need some substantially new procedures. The insertion and
deletion procedures for doubly linked lists must cope with two links per
cell, instead of only one, and are thus somewhat more complex than the
corresponding procedures for singly linked lists.
Figure 14-19 shows the steps for inserting a cell after the one pointed
to by P. We can outline the procedure INSERT AFTER as follows:
PROCEDURE INSERT_AFTER(V, P)
(Get a new cell from the free-space list, and set Q
to point to it)
(Let R point to the cell following CELL(P))
(Link CELL(Q) in between CELL(P) and CELL(R)
(Set right links in CELL(P) and CELL(Q))
(Set left links in CELL(R) and CELL(Q))
(Set VALUE(Q) to V)
END INSERT_AFTER
i
*
n -—1
ri "1 ~"1 r*~
1
1
— "^""
1 L 1
Q ""
RIGH T_LINK(P) «- -
Q (Set right links
RIGH T_LINK(Q) «- - R
P R
1
."— * I
"1
^LT: -If 1
Q-
P R
1
-*~ m
'1
-
__r-
II
:
— 1
Q-
FIGURE 14-19. The procedure INSERT_AFTER(V, P) inserts a cell containing the value V
after the cell pointed to by P.
296
14.3 Doubly Linked Lists 297
PROCEDURE INSERT_AFTER(V, P)
GLOBAL VALUE, LEFT_LINK, RIGHT_LINK
CALL NEW(Q)
R <- RIGHT_LINK(P)
RIGHT_LINK(P) «- Q
RIGHT_LINK(Q) <- R
LEFT_LINK(R) «- Q
LEFT_LINK(Q) <- P
VALUE(Q) <- V
END INSERT_AFTER
For doubly linked lists, we also have INSERT BEFORE, which in-
serts a cell be/ore the one pointed to by P:
PROCEDURE INSERT_BEFORE(V, P)
GLOBAL VALUE, LEFT_LINK, RIGHT_LINK
CALL NEW(Q)
R «- LEFT_LINK(P)
RIGHT_LINK(R) <- Q
RIGHT_LINK(Q) «- P
LEFT_LINK(P) «- Q
LEFT_LINK(Q) <- R
VALUE(Q) <- V
END INSERT_BEFORE
LETER).
Figure 14-21 illustrates the deletion operation. We can outline the
needed procedure as follows:
PROCEDURE DELETE(P)
IF (P does not point to the header cell) THEN
(route the links from the cells before and after
CELL(P) to bypass CELL(P))
(Return CELL(P) to the free-space list)
END IF
END DELETE
PROCEDURE DELETE(P)
GLOBAL LEFT_LINK, RIGHT_LINK, IS_HEADER
IF NOT IS_HEADER(P) THEN
Q «- LEFT_LINK(P)
R <- RIGHT_LINK(P)
RIGHT_LINK(Q) +- R
1 . i )
~l 1
-\ ~l
T.
1 1
ir
—
n_~
,
i
S —
i
Q —
FIGURE 14-20. The procedure INSERT_BEFORE(V, P) inserts a cell containing the value V
before the cell pointed to by P.
298
3
) ) )
1 1 "I
'
"*11 ["" " ' '1 -*"i r""
1 1
p R
i ii ||
*i i — h r
4- i
LEFT_LINK(R) *-
CALL RECYCLE (P
END IF
END DELETE
[^®WD®M ©ao®gfe[M
1. Frequently a programmer wishes to model some portion of the real
world inside the computer. Give two things that must be represented in
such a model.
2. What are entities? How are they represented inside the computer':
300 14 Linked Lists
5. What is a plex?
7. What
is the value NIL used for? What are some numerical values that
10. Using diagrams and words, describe the processes of insertion and
deletion for a singly linked list.
11. What is a ring? In searching for a given value, what feature does a ring
have that a singly linked list does not have?
12. Will the INSERT AFTER procedure be the same for a ring as for a
singly linked list? If not, what modification is needed?
13. Will the DELETE AFTER procedure be the same for a ring as for a
singly linked list? If not, what modification is needed? (Hint: Thou Shalt
15. What is the advantage of a doubly linked list over a singly linked list?
The disadvantage?
16. Why do we have procedures INSERT_AFTER and INSERT_BEFORE
for a doubly linked list, whereas we have only INSERT AFTER for a sin-
gly linked list?
17. Using words and diagrams, describe the process of inserting a cell be-
fore a given cell in a doubly linked list.
18. Using words and diagrams, describe the process of inserting a cell af-
ter a given cell in a doubly linked list.
19. Using words and diagrams, describe the process of deleting a given
cell in a doubly linked list.
20. Lists can be stored either as arrays or linked lists. Give one advantage
of arrays over linked lists. Give two advantages of linked lists over arrays.
izmmm^
1. Write a version of the procedure ACCESS for a ring.
point to any cell on the list. I is the number of the cell pointed to by F. (I
is for the header, 1 for the cell following the header, and so on.) J is the
number of the desired cell. If J is less than I, ACCESS will move to the left
until it reaches the Jth cell. If J is greater than I, ACCESS will move to the
right until it reaches the Jth cell. ACCESS returns with Q pointing to the
4. Write two versions of the procedure NEW for doubly linked lists. For
the first version, assume that the free-space list is singly linked, using
right links only. For the second, assume that the free-space list is doubly
linked. (The left link of the first cell and the right link of the last one will
be NIL.)
DECLARE 1 CELL( )
2 LINE_NUMBER
2 LINE_TEXT
2 LINK
The linked list of lines is kept in line number order. Thus, if the list con-
tained lines 100, 110, and 120, and line 115 was inserted, it would be
inserted between 110 and 120.
Write the following procedures:
INSERT(NUMBER, TEXT). If a line with a number equal to NUMBER
is already present, then replace its text with the value of TEXT. Other-
wise, insert a new line in the proper position— with line number NUM- —
BER and text TEXT.
Modify INSERT so that if the value of TEXT is the null string, no new
line will be inserted,and if there is already a line with line number equal
to NUMBER, that line will be deleted.
DELETE(FIRST, LAST) Delete all lines whose line numbers are in the
range FIRST through LAST.
LIST(FIRST, LAST). Print out all lines whose line numbers lie in the
range FIRST through LAST.
©Cm)^@f Hi
Trees
302
15.1 Definitions and Terminology 303
FIGURE 15-1. A tree. If you turn the drawing upside down, you will see that it resembles a
natural tree.
terminology for trees comes from two sources: natural trees and family
trees.
From natural trees: The topmost node of the tree is called the root. The
bottommost nodes are called the leaves. The lines connecting the nodes are
called the branches. (See Figure 15-3.)
From family trees: As shown in Figure 15-4, a node is said to be the
parent of those immediately below it, which are said to be its children.
All of the children of a given parent are said to be twins or siblings.
(Father, son, and brother as well as mother, daughter, and sister are
sometimes used in place of parent, child, and twin. But rather than choose
a particular "sex" for the tree, most modern writers use parent, child, and
twin or sibling.)
The descendants of a node are the node's children, its children's chil-
dren, its children's children's children, and so on.
Any node of a tree, together with all its descendants, forms a tree in
its own right, as shown in Figure 15-5. This tree is said to be a subtree of
the original tree. Note two extreme cases. The entire tree is a subtree of
itself, and each leaf is a subtree consisting of only a single node.
s
304 15 Trees
Starting position
Opponent '
replies
counterreplies
Root
Leaves
FIGURE 15-3. An illustration of the terms root, branch, node, and leaf.
The level number of a child of a node is the level number of the node
plus 1.
306 15 Trees
^ Parent
1
•
c) . o J
/
Children. All the children of
a given parent are twins or siblings
FIGURE 15-4. An illustration of the terms parent, child, twin, and sibling.
The level numbers are not needed; the indentation displays the structure
of the tree perfectly, and the reader can count off the levels:
15.1 Definitions and Terminology 307
FIGURE 15-5. Subtrees. In additon to the subtrees shown, each leaf is a subtree, and so is
Note that the roots of the subtrees of a given node are indented once
with respect to that node.
Instead of indenting the subtrees of a node, we can enclose them in
parentheses instead. This gives a more compact notation:
A(B(C D E) F(G(H I) J)
FIGURE 15-6. The recursive definition of a tree. The circles represent nodes; the squares
represent subtrees.
308
15.2 Traversal and Linear Representations 309
Level 1
FIGURE 15-7. Level numbers. The level number of the root is 1. The level number of any
other node is one greater than the level number of its parent.
ABCDEFGHIJKLMNO
The order is the same as the order in which the nodes occur in the
15.2 Traversal and Linear Representations 311
Start finish
FIGURE 15-9. Preorder Traversal. A node is "visited" when the path goes through it, but not
when the path goes around it.
parenthesized notation for the tree. This is no accident, for the parenthe-
sized notation is based on a preorder traversal.
This raises the general question: What additional information must be
provided, besides just the list of nodes, so that a tree can be uniquely
reconstructed from a preorder list of its nodes? The answer is that we must
show how the nodes are grouped into subtrees. We already know one so-
lution. We can use parentheses, or some equivalent symbols, to enclose
each subtree. This just gives us back our parenthesis notation:
Figure 15-10 illustrates how the tree can be reconstructed from the pa-
renthesis notation. First, remove the one node that is not inside any paren-
theses:
This is the root of the tree. Xow remove the outside parentheses from the
remaining nodes:
i
312 15 Trees
Bi C D Ei Fi HlIiJKiLlMNOl
LlMNOi
This gives the subtrees of the root, each in parenthesis notation. The con-
struction just given is then applied recursively to the subtrees to translate
them from parenthesis notation into the corresponding tree.
Another technique we have already encountered is level number no-
tation. Suppose each node carries an indication of the level on which it
occurs. Thus, C3 means node C on level 3. Our preorder list becomes:
Al B2 C3 D3 E2 F3 G4 H2 13 J4 K4 L3 M4 N4 04
To show that the tree can be uniquely reconstructed from this list, we
convert the list to parenthesis notation. The rules for doing so are:
Whenever the level number increases by 1, insert a left parenthesis.
Thus,
B2 C3 translates into B (C
but
C3 D3 translates into C D
D3 E2 translates into D) E
and
At the end of the list, add enough right parentheses to bring the level
number back up to 1. Thus,
You should verify that these rules translate the preorder list with level
numbers into the parenthesized list, from which we already know the tree
can be reconstructed.
A third approach provide each node with an indication of how
is to
A3 B2 C D E. F. G H2 I2 J K L3 M N
314
15.2 Traversal and Linear Representations 315
branches below it. We continue in the same way, always hanging the next
node in the preorder list onto the leftmost dangling branch.
Postorder Traversal. Instead of visiting the root before traversing its sub-
trees, we can traverse the subtrees first and then visit the root. This scheme
is called postorder traversal; it is formally defined by:
CDBGFEJKIMNOLHA
As with preorder traversal, merely the list of nodes is not enough to
allow us to reconstruct the original tree. But we can use any of the same
—
techniques enclosing subtrees in parentheses, level numbers, or num-
FIGURE 15-12. Postorder traversal. The path is the same as for preorder traversal. But the
nodes (except for the leaves) are visited at different points on the path.
316 15 Trees
bers of children — to get lists from which the original tree can be recon-
structed. The following shows each of the three forms:
The arguments that the original tree can be reconstructed from each of
these postorder lists parallel the ones for preoder lists.
Binary Trees and Inorder Traversal. A binary tree is a tree in which each
node has at most two children, as shown in Figure 15-13. The children are
known as the left child and the right child, respectively. If a node has only
one child, it may be either a left child or a right child.
In the same way, each node has at most two subtrees, the left subtree
and the right subtree. If a node has only a single subtree, it may be either
a left subtree or a right subtree.
A binary tree has another kind of traversal, inorder traversal, in
which the root is visited in between the traversals of the two subtrees:
For the inorder traversal of the binary tree of Figure 15-13, the nodes
are visited in the following order:
D B E A C F
FIGURE 15-13. A binary tree. Notice that in a binary tree a node can have a right child even
though its left child is missing.
This node
has a right
child but no
left child
15.3 Linked Representations 317
We can reconstruct the tree from the inorder list, provided the subtrees are
enclosed in parentheses:
DECLARE 1 N0DE( )
2 VALUE
2 NUMBER_OF_CHILDREN
2 CHILD (NUMBER_OF_CHILDREN)
DECLARE 1 NODE( )
2 VALUE
2 CHILD(3)
The unused child pointers are set to NIL, as shown in Figure 15-15. Note
that memory
space is wasted in each node in which one or more child
pointers have the value NIL.
318 15 Trees
E
o
B
2
„ F
^^
G
O
A C
3 X
H
O
^^ I
O
^^
J
o
D
2
FIGURE 15-14. A representation of the tree of Figure 15-1 using multiple child pointers and
variable-length records.
DECLARE 1 N0DE( )
2 VALUE
2 LEFTMOST_CHILD
2 RIGHT TWIN
^^ M ^^ D
B C
E F G H
_. —
I
-"""^
J K
FIGURE 15-16. The child-and-twin pointers representation of the tree of Figure 15-1.
Parent pointers. Multiple child pointers and child and twin pointers are
oriented toward top-down processing: we start with the root and work
downward. If we also wish to do bottom-up processing to work from —
leaves to root— we can place in each node a pointer to its parent. Occasion-
ally, parent pointers are used by themselves, but more commonly they are
used together with either multiple child pointers or child and twin point-
ers.
FIGURE 15-17. The tree of Figure 15-1 redrawn as the equivalent binary tree implied by the
child-and-twin pointers representation.
as well as a right twin. This allows us to move either to the left or to the
right in a twin list.
Rings. We can get the effect of rings in two ways. First, with child and
twin pointers, we can join the leftmost twin and the rightmost twin, mak-
ing the twin list into a ring. Second, with either method, we can give each
leaf a pointer to the root. This gives us rings in the parent-child direction.
i, 1
B C D
i 1
E F
a) Parent pointers
PROCEDURE PREORDER_TRAVERSAL P (
PROCEDURE P0ST0RDER_TRAVERSAL(P)
GLOBAL NODE, NUMBER_OF_CHILDREN CHILD
N <- NUMBER_OF_CHILDREN(P)
) )
324 15 Trees
FOR I <- 1 TO N DO
Q *- NODE(P) .CHILD(I)
CALL POSTORDER_TRAVERSAL(Q)
END FOR
CALL VISIT(P)
END POSTORDER_TRAVERSAL
Child and Twin Pointers. The traversal procedures using child and twin
pointers are similar to those using multiple child pointers. The difference
is that the children of a node form a linked list, instead of being accessed
through an array of pointers.
For preorder traversal we have:
PROCEDURE PREORDER_TRAVERSAL P (
Q <- RIGHT_TWIN(Q)
END WHILE
END PREORDER_TRAVERSAL
PROCEDURE POSTORDER_TRAVERSAL(P)
GLOBAL LEFTMOST_CHILD, RIGHT_TWIN
Q «- LEFTMOST_CHILD(P)
WHILE Q ± NIL DO
CALL POSTORDER_TRAVERSAL(Q)
Q «- RIGHT_TWIN(Q)
END WHILE
CALL VISIT! P)
END POSTORDER TRAVERSAL
**. An operator node has one subtree for each operand of the operator. We
15.5 Expression Trees 325
will only use binary operators here, so each operator node will have ex-
actly two subtrees. But operator nodes with 1, 3, 4, and so on arguments
are also possible.
The value nodes correspond to values to be operated upon. For sim-
plicity, we will confine our values to real numbers, although expression
treescan also be constructed for string or logical expressions. A value node
has no subtrees. Thus, value nodes are the leaves of the expression tree.
Figure 15-19 illustrates operator and value nodes.
As mentioned, the subtrees of an operator node are its operands. An
operand can be either a value or a subexpression that will evaluate to a
value. For instance, in
3+5
the operator is +, and its operands are 3 and 5. The operator node for +
will have as its subtrees the value nodes for 3 and 5, as shown in Figure
5-20a.
On the other hand, consider the expression:
3+5 7-4
The operands of the operator * are the values of 3 + 5 and 7-4. Thus, the
subtrees of the operator node for * are the expression trees for 3 + 5 and
7-4 (see Figure 15-20b). Note that the parts of the expression in parenthe-
ses form subtrees.
In the expression
3+4*5
we know that the multiplication will be done before the addition because
326
15.5 Expression Trees 327
3+ (4*5)
Hence, the operator node for + has two subtrees. One is the value node
4*5 (see Figure 15-20c).
for 3; the other is the expression tree for
Since each operator node has exactly two subtrees, and each value
node has none, our expression trees are binary trees. There are three
ways, remember, of traversing a binary tree: preorder, postorder, and in-
order. Each of these gives a linear representation of the tree. That is, each
one gives a way of writing the expression as a list of symbols a notation —
for the expression.
Consider the expression tree of Figure 15-21. If we write the operators
and values as they occur in a preorder traversal, we get:
+ 5 3 4-75
This is the same as prefix notation or Polish notation: Each operator im-
mediately precedes its operands.
Furthermore, we can reconstruct the expression tree from the prefix
notation. The reason is that we can recognize the difference between oper-
ators and values. Each operator node has two children, each value node
has none. Therefore, this expression is equivalent to
2 ^2 °Q 2 °0 ^0 2 '0 °0
where the subscripts give the number of children of each node. But we
already know
given a preorder list of nodes and the number of chil-
that,
dren of each node, the original tree can be reconstructed.
Now let's do a postorder traversal of the expression tree of Figure 15-
21. The corresponding list of nodes is:
534* + 75 - *
^o °o ^o 2 ~2 'o -"o 2 2
5 + 3*4*7-5
which corresponds to infix notation. However, it is now impossible to re-
construct the original tree merely by inspecting the inorder list of nodes.
5 + 3*4
*
it is impossible to say whether + has subtrees 5 and 3 * 4, or whether
has subtrees 5 + 3 and 4.
(5 + (3 * 4) )
* (7 - 3)
(5 + 3 * 4) * (7 - 3)
we eliminate the spaces, we get the usual infix form of the expression:
(5+3*4)*(7-3)
3*5 + 3*7
could be modified to
3*(5+7)
which gives same value with one less multiplication. And the statement
A «- 5*(C+4*D) + (C+4*D)**2
X <- C + 4*D
A <- 5*X + X**2
330 15 Trees
^opponent tne number of kings. Checkers experience shows that the relative
value of kings and men is 3:2, that is, one should be willing to trade three
men for two kings, or vice versa. Thus, the static evaluation function
might be given by the expression:
3*(k computer
v
- k opponent.* + 2*fm
1 ili
v computer
- m 1
opponent-*
In a position inwhich the computer had five men and two kings and the
opponent has seven men and one king, the value assigned by the static
evaluation function would be:
The negative value means that this position is favorable to the opponent.
Positions with positive ratings are favorable to the computer, and those
with zero ratings favor neither side.
More complicated static evaluation functions are used in real checkers-
playing programs, of course. These have terms for additional features of
the position, such as the mobility of each side's pieces and the extent to
which each side has occupied certain strategic squares.
One use of the static evaluation function is to restrict the number of
moves to be explored further at each stage of the lookahead. Only a few
moves leading to positions with the highest static evaluations are ear-
marked for further exploration.
But the most important use of the static evaluation function is to assign
a rating to each leaf of the tree. These ratings are used to determine which
leaf position the computer should aim for and so what its next move
should be.
More specifically, we assign to each node in the tree the value of the
best leaf position that can be reached from the position in question. With
this done, then the correct move for the computer is the one that leads to
the second-level position with the highest value. That is the position that
will eventually lead to the best leaf position.
In determining the best leaf position that can be reached from a given
.
332 15 Trees
FIGURE 15-22. The rules for determining the value of a node from the values of its children.
A circle represents a node in which it is the computer's turn to play. A triangle represents a
node in which it is the opponent's turn to play.
3. Draw a tree and indicate the nodes, the branches, the root, and the
leaves.
5. Give two other sets of terms sometimes used in place of parent, child,
and twin.
bi The static values backed up one level ising the minimax technique
FIGURE 15-23. Assigning a value to every position in a game tree using the minimax tech-
nique. We start with the values assigned to the leaves by the static evaluation function and
work upwards.
334
Exercises 335
18. Define left child, right child, left subtree, and right subtree for a bi-
nary tree.
22. Describe in words the operation of each of the four traversal procedures
given in this chapter.
23. Describe the relations between traversal methods and notations for al-
gebraic expressions.
24. Give an argument that postfix notation (RPN) is best suited for expres-
sion evaluation by computer (provided that more complicated manipula-
tions, such as rearranging the expression to simplify the calculation, are
not to be attempted).
25. Describe how a game-playing program goes about determining its next
move.
izm\?©mm
1. Write a function EVALUATE(P) whose argument, P, points to the root
of an expression tree, and whose value is the value of the expression.
The nodes of the expression tree are defined as follows:
DECLARE 1 N0DE( )
2 0PERAT0R_0R_VALUE
2 IS_VALUE
2 LEFT_CHILD
2 RIGHT_CHILD
'-100', or '25.25'.
IS VALUE is TRUE for a value node and FALSE for an operator node.
For an operator node, LEFT CHILD and RIGHT
CHILD point to the
left right children of the node. For a value node, these components are
and
unused.
The basic logic of EVALUATE(P) is: If P points to a value node, then
return the corresponding value. If P points to an operator node, then eval-
uate its left and right subtrees, apply the operator to the resulting values,
and return the result. As mentioned in the text, this logic implies a
postorder traversal of the expression tree.
DECLARE 1 NODE( )
2 POSITION
2 IS_MY_MOVE
2 LEFTMOST_CHILD
2 RIGHT_TWIN
POSITION describes the current board position and will normally be.
either a string or an array. For this problem we will not have to worry about
the details of POSITION.
IS MY MOVE is TRUE if it is the computer's move and FALSE if it
©faa^SsD Hd 3
i
J
J
Graphs
and Plexes r—
The word graph is the mathematician's term for a set of points connected
by lines, as shown in Figure 16-1. More familiar terms for the same thing
are network, map, maze, and flowchart. A tree, for instance, is a special
case of a graph.
(This kind of graph has nothing to do with the kind used for plotting
data. Unfortunately, the term graph is used in mathematics for two com-
pletely different ideas.)
A plex, as has been mentioned, is a collection of records, each of
which contains one or more pointers to other records. The linked lists and
linked representations of trees we have already studied are special cases of
plexes. But the structure of the most general possible plex is that of a graph.
The most important use of a graph is to show relationships among
Each point on the graph corresponds to an entity. Each line corre-
entities.
sponds to some relationship between the two entities connected.
16.1 Terminology
The points of a graph are called nodes. The lines connecting the points are
called arcs.
If the arcs have directions associated with them, as indicated by an
arrowhead on each arc, then the graph is directed. If there are no direc-
tions associated with the arcs, and hence no arrowheads, then the graph
is undirected. Figure 16-2 shows directed and undirected graphs.
337
FIGURE 16-1. A graph. The points are called nodes; the lines connecting the points are called
arcs.
C D
lai Undirected graph
338
16.1 Terminology 339
The graphs used in computer science are usually directed, because the
methods used for representing arcs have directions associated with them.
If an undirected arc is needed, it is represented by two directed arcs join-
ing the same nodes in opposite directions. (Example: A singly linked list
represents the directed graph shown in Figure 16-3a. A doubly linked list
represents the undirected graph shown in Figure 16-3b.)
Consider the directed arc shown in Figure 16-4. The arc joins node A
to node B, with the arrowhead pointing to node B. We say that node B is
the immediate successor of node A and that node A is the immediate pred-
ecessor of node B. The arc goes from node A to node B.» Node A is the
initial node of the arc; node B is the final node.
A graph is said to be labeled if the arcs carry labels as shown in Figure
16-5. Otherwise, it is unlabeled.
Suppose that we start at one node in a graph and move to another
node, always following the arcs in the direction of the arrowheads. The
nodes we pass through, including the starting and ending node, constitute
a path. (See Figure 16-6.)
A path is a cycle if it begins and ends on the same node. A graph that
contains no cycles is acyclic. Figure 16-7 illustrates a graph with cycles
and an acyclic graph.
A directed graph is if there exists a path between
strongly connected
any two distinct vertices. The graph merely connected if such a path
is
exists when the directions of the arcs are ignored. If no path exists between
FIGURE 16-3. A singly linked list corresponds to the directed graph (a). A doubly linked list
corresponds to the undirected graph (b). The doubly linked list is represented in memory,
however, by a structure corresponding to the directed graph (c).
C D
A B C D E F
A B C D E F
J
Final node
V 11
FIGURE 16-4. Arcs and nodes. An arc may be represented by either a straight line or a curve.
FIGURE 16-5. A labeled graph. Different arcs can have the same label. We can think of a
label as specifying a particular kind of arc, rather than identifying an individual arc uniquely.
Thus the graph shown contains two arcs of type a, two of type b, two of type c, and one of
type d.
^\ " /
D
340
16.2 Tabular Representations 341
some pair of nodes, even when the directions of the arcs are ignored, the
graph unconnected. Figure 16-8
is illustrates strongly connected, con-
nected, and unconnected graphs.
Just as trees have both linear representations and linked (or plex) repre-
sentations, so there are two ways to represent graphs. In a tabular rep-
resentation, a table specifies the arcs connecting the nodes. In a linked
or plex representation, each node contains either a pointer to every node
to which it is joined by an arc or a single pointer to a linked list of such
pointers.
Ordered Pairs. One of the simplest ways to represent a graph is with a list
of ordered pairs of nodes. The first node of each pair is joined to the second
by an arc. The list contains one pair for each arc of the graph.
Such a list can be stored as a table of two columns. One column holds
the initial node of each arc; the other column holds the final node. There
is one row for each arc.
A B
C D
I b ) Acyclic graph
a ) Not connected
b) Connected
This table can be stored as a 9 x 2 array. The row entries can be in any
order, but putting them in alphabetical order according to the names of
one of the nodes may allow the entries to be accessed more efficiently.
Ordered Triples. If the graph is labeled, then the label of each arc must be
specified. Thus, we must use ordered triples instead of ordered pairs. In
the table, we need a new column for the arc labels.
Figure 16-10 shows a labeled version of Figure 16-9, where the arc
labels are denoted by small letters. The table representation for this
graph is:
FIGURE 16-9. An unlabeled graph whose representations are discussed in the text.
B b C
C b A
C a C
D c B
D a D
D b E
E c C
Successor Lists. We can gather together all the final nodes having the same
initial node and give a list of immediate successors for each node. Using
Figure 16-9 as an example, we have:
A C
B AC
C AC
16.2 Tabular Representations 345
FIGURE 16-10. A labeled graph whose representations are discussed in the text.
D B DE
E
This table can be stored as a 5 x 3 array. Note that some array ele-
ments are wasted, since not every element of every row has an entry. (The
unused elements contain some special value indicating that they are un-
used.)
Transition Tables. Again, for labeled graphs, we must modify the table
representation to show the arc labels. We can do this by labeling the im-
mediate successor columns with the arc labels. Thus, Figure 16-10 can be
represented by:
Arcs
Nodes a b c
A C
B A C
C C A
D D E B
E C
346 16 Graphs and PJexes
Inputs
ates a b c
A C
B A C
C C A
D D E B
E C
pointers to error messages. When the user makes an error, the system uses
the table to determine the appropriate error message. After the error mes-
sage is printed, the virtual machine is placed in some standard starting
state Where it awaits further input from the user.
follows:
16.3 PJex Representations 347
Final Node
Initial Node A B C D E
A '
1
B 1 1
C 1 1
D 1 1 1
E 1
Each entry can be stored as a single bit, so the table can be stored very
compactly.
The connection table for an unlabeled graph is also called an incidence
matrix, a bit table, or a bit map.
For labeled graphs, the 1 entries are replaced with the appropriate
labels:
Final Node
Initial Node A B c D E
A a
B a b
C b a
D c a b
E c
Now the table cannot be stored so compactly, since more than one bit is
required to store each arc label.
DECLARE 1 N0DE( )
2 VALUE
2 NUMBER_OF_SUCCESSORS
2 SUCCESSOR NUMBER_OF_SUCCESSORS
(
FIGURE 16-11. Plex representation of an unlabeled graph using pointers to immediate suc-
cessors.
DECLARE 1 N0DE( )
2 VALUE
2 NUMBER_OF_SUCCESSORS
2 SUCCESSOR NUMBER_OF_SUCCESSORS
f
3 LABEL
3 POINTER
SUCCESSOR has one element for each arc leaving the node in ques-
tion. Each element has two components: LABEL, which is the label of the
arc; and POINTER, which is the pointer to the final node of the arc in
question.
Figure 16-12 shows the graph of Figure 16-10 represented using nodes
of this type.
If no more than one arc with each label leaves any particular node,
then we can reserve a pointer position for each label. Suppose, for in-
stance, a graph has arcs labeled a. b. and c. We could use nodes defined
as follows:
DECLARE 1 N0DE( )
2 VALUE
2 SUCCESS0R_A
2 SUCCESSORS
2 SUCCESSOR.
16.3 PJex Representations 349
A B
1 2
a a
C E D
2 1 3
b c c
"*
a b
FIGURE 16-12. Plex representation of a labeled graph using pointers to immediate successors.
Each pointer is preceded by a component giving the label of the corresponding arc.
Figure 16-13 shows the graph of Figure 16-10 represented in this way.
Note that space is wasted in some records when pointers have NIL values.
On the other hand, the records are of fixed length, and computer systems
usually find fixed-length records easier to work with than variable-length
records.
Our next approach may be regarded as a generalization of the child-
and-twin-pointers method of representing trees. We use two kinds of rec-
ords: node records and arc records. Each node contains a pointer to a
linked list of arc records; each arc record contains a pointer to the final
node of the arc, and possibly a label.
The node records are defined as follows:
DECLARE 1 N0DE( )
2 VALUE
2 SUCCESSOR_LIST
|
—
1
" A
"
. a
B
b
b
c ^^ c
a
b
C
n^ a
E
^>v. a
D
—
b
b
c c
FIGURE 16-13. A plex representation of a labeled graph in which one pointer position is
reserved for each label. Although the labels are shown in the drawing, they don't have to be
stored in memory. The position of a pointer in the record uniquely determines the label.
SUCCESSOR LIST points to a linked list of arc records. Each arc rec-
ord contains a pointer to a successor:
DECLARE 1 ARC( )
2 SUCCESSOR
2 LINK
Figure 16-14 shows the graph of Figure 16-9 represented using node
and arc records. Note that all the records are of fixed length. And the suc-
cessor lists are easy to manipulate because they are linked lists. These are
the principal advantages of this representation.
If the graph is labeled, the labels must be associated with the arcs. The
most obvious way to do this is to include the labels in the arc records:
DECLARE 1 ARC( )
2 LABEL
2 SUCCESSOR
2 LINK
Figure 16-15 shows the graph of Figure 16-10 represented using la-
beled arc records.
Occasionally, all the information in a graph is carried by the arcs; the
nodes can be anonymous, with no values or labels. In this case the node
records can be omitted entirely; the representation need only contain arc
records.
Figure 16-16 shows a graph with anonymous nodes and its represen-
tation using arc records alone. In this kind of representation, the LABEL
16.3 PJex Representations 351
FIGURE 16-14. Plex representation of an unlabeled graph using node and arc records. Node
records are shown as rectangles, arc records as squares.
DECLARE 1 N0DE( )
2 VALUE
2 SUCCESSOR LIST_A
352 16 Graphs and PJexes
FIGURE 16-15. Plex representation of a labeled graph using node and arc records. Arc labels
appear in arc records.
16.3 Plex Representations 353
^^
r
a
^" a —
b
a m
"""
FIGURE 16-16. Plex representation of a graph with anonymous nodes. Node records are omit-
ted. Successor pointers point to the first record of an arc list, instead of to a node record.
2 SUCCESSOR_LIST_B
2 SUCCESSOR_LIST C
node record contains a pointer to a unique successor for each arc label.
Suppose there are again three arc labels: a, b, and c. Suppose further that
354 16 Graphs and PJexes
FIGURE 16-17. Plex representation of a labeled graph in which there is a separate arc list for
each arc label. Notice that the arc records don't need to contain labels. Which list an arc
record is on determines the label for the arc.
16.4 Applications 355
only one arc labeled a or b can leave a node, but that any number of arcs
labeled c can do so. Then we can use the following node records:
DECLARE 1 N0DE( )
2 VALUE
2 SUCCESSOR_A
2 SUCCESSOR_B
2 SUCCESSOR_LIST_C
DECLARE 1 PERSON ( )
2 NAME
2 FATHER
2 MOTHER
2 SPOUSE
2 SIBLING..LIST
2 CHILD_LIST
A person can have only one natural father or mother and, in our society,
only one spouse at a time. Hence, FATHER, MOTHER, and SPOUSE each
point to a unique record. On the other hand, a person can have more than
one sibling or child, and so SIBLING__LIST and CHILD_LIST point to
lists of arc records.
16.4 Applications
Department
t 1
1
|
f
'
I f
l |
1
scribing the operation of some abstract machine. Transition tables and the
corresponding transition graphs are of considerable importance in design-
ing the various abstract machines that occur in a computer system. The
implementations of these machines may be physical (implemented in hard-
ware) or virtual (implemented in software). A hardware example is the
computer's control unit. Software examples are compilers and interpreters.
Language Specification. We
can think of the items of a language key- —
—
words, signs, constants, and so on as inputs that cause a compiler or
interpreter to go from one state to another, carrying out the translation or
interpretation in the process. One way to describe the grammar of the lan-
guage is to give the transition graph for its interpreter or compiler.
We are not really interested in the internal states of the compiler, how-
ever. Instead, it is the inputs to the language processor — the arc labels
that we are trying to relate. Therefore, the graph that describes the lan-
guage will have "anonymous" nodes. The mere fact that a given state exists
is sufficient. It is the arc labels —
the items from the language that we are —
interested in relating to one another.
Figure 16-19 shows the graphs for assignment statements and arith-
metic expressions in the algorithmic language. Note that all of the named
items in boxes or circles are arc labels. The nodes are the barely visible
dots where the arcs come together.
—
There are two kinds of arc labels those that are enclosed in circles
and those that are enclosed in boxes. The items enclosed in circles are
single characters whose presence or absence the machine can detect in a
single operation. The labels enclosed in squares are composite items de-
fined by their own graphs. When a label for a composite item is encoun-
tered, the machine refers to the graph for that item to process it. The
graphs for composite items function much like procedures in a program-
ming language. Wherever a label for a composite item occurs, we can think
of the corresponding graph being substituted.
The graphs are read by starting at the beginning and following the ar-
rows. Thus, an assignment statement consists of a variable followed by the
assignment operator followed by an expression.
A loop indicates that the items in the loop can occur any number of
times. Thus, an expression consists of a term followed by any number of
items of the form " + term" or " - term".
This kind of graph can be used for processing natural languages as well
as programming languages. One feature of natural languages is that they are
not so regular or consistent as programming languages. For each arc of the
graph, however, we can specify arbitrarily complex tests for an}' special
cases or features that need to be considered at that point in the processing.
Term
Expression Term -®
Factor
Constant
Factor Variable
Expression
FIGURE 16-19. Graphical description of simple assignment statements. Each graph is invoked
by some other graph, just as a procedure isinvoked by a main algorithm or another proce-
dure. When the circled state is reached, a return is made to the invoking graph.
358
Review Questions 359
C^(gWD®\^7 ©0Q©g1]D®[JQ©
2. What are the names for the points and the lines of a graph?
12. Describe the connection between a transition table and an abstract ma-
chine.
14. Give the representations for labeled and unlabeled graphs that are
(roughly) equivalent to the multiple-child-pointer representation for trees.
15. Give the representations for labeled and unlabeled graphs that are
(roughly) equivalent to the child-and-twin-pointer representation for trees.
16. Describe the use of graphs in information retrieval and data processing.
17. Describe two kinds of programs that may manipulate the flowchart of
another program.
18. Give some examples of real world objects that have a graphlike struc-
ture and would usually be represented inside a computer as graphs.
360 16 Graphs and PJexes
19. Describe the use of graphs in the design of physical and virtual ma-
chines.
21. What is one way that graphs are used in artificial intelligence research?
vzyy^z^v-
1. Represent the graph of Figure 16-20 using:
(a) ordered pairs
(b) immediate successor lists
(c) a connection table
(d) records containing successor pointers
V
FILE -1
L
ORGANIZATION
AND PROCESSING '—1
mm^m W 1
In
Sequential
Files
V r
'
365
366 17 Sequential FiJes
Magnetic Tape. Computer tape is similar to the tape used in home record-
ers, and works on the same principle. It is relatively inexpensive and will
hold large amounts of information. The reels are easily stored when not
being used on the computer.
The main disadvantage of magnetic tape is well known to every home
recordist who ever searched for, say, a particular musical selection located
somewhere on a large reel of tape. The process is time consuming. Tape is
fine when you play the reel from beginning to end but very frustrating
when you are looking for a particular selection.
The same thing holds for computer tape. Tape is efficient when the
entire reel is be processed from beginning to end, but inefficient other-
to
wise. In short, tape is a sequentiaJ-access medium: To use it efficiently,
output files, and we need some way to distinguish between them. We will
do this by giving each file a name and putting that name in parentheses
after INPUT or OUTPUT. Thus,
INPUT (0LD_FILE)
OUTPUT (NEW_FILE)
inputs a record from OLD FILE and assigns this record to OLD REC. In
the same way,
We update the master each month using the data in the transaction
file
Computer
run
/ /
T ransaction fi le
l on cards i
Report
1 printout
The records in the master file (both OLD_FILE and NEW_FILE) have
the following structure:
1 0LD_REC
2 KEY
2 BALANCE
For simplicity, each record has just two fields, KEY and BALANCE.
The value of KEY identifies a particular record; we will assume that
the keys are four-digit numbers, such as 3751, 4862, and 5234. The last
record in OLD FILE or NEW FILE is a special sentinel record with a key
of 9999.
The BALANCE field is a value that can be updated. It might be the
amount a customer owes to a company, which will change as purchases
and payments are made. It could be the amount in a person's bank ac-
count, which will change with deposits and withdrawals. Or it could refer
to something having nothing to do with money, such as the number of
items of a particular kind that are in stock.
The records in the transaction file, which will be used to update the
records in the master file, have the following structure:
1 TRANS_REC
2 KEY
2 KIND
2 AMOUNT
KEY
has the same significance for a transaction record as it does for a
master record. The last record in the transaction file is a special sentinel
record with a key of 9999.
The value of KIND determines what kind of transaction each particular
record represents. The following table shows the three possible values of
KIND and the kind of transaction corresponding to each:
ALGORITHM FILE_UPDATE
GLOBAL 0LD_REC, NEW_REC TRANS_REC CURRENT_KEY, IN_USE
,
DECLARE 1 0LD_REC
2 KEY
2 BALANCE
DECLARE NEW_REC LIKE 0LD_REC
DECLARE 1 TRANS_REC
2 KEY
2 KIND
2 AMOUNT
SENTINEL *- 9999
INPUT (TRANS_FILE) TRANS_REC
INPUT (0LD_FILE) 0LD_REC
WHILE (0LD_REC.KEY ± SENTINEL)
OR TRANS_REC KEY ^ SENTINEL DO
I .
CALL GET_NEXT_KEY
CALL PR0CESS_TRANSACTI0NS
IF IN_USE THEN
OUTPUT NEW_FILE NEW_REC
( )
END IF
END WHILE
NEW_REC.KEY <- SENTINEL
OUTPUT NEW_FILE NEW_REC
( )
END FILE_UPDATE
17.3 The File Update Problem 371
made for a moment. The value of CURRENT KEY is set to the key value
selected by GET_NEXT_KEY.
The procedure PROCESS TRANSACTIONS processes all transaction
records whose key values are equal to CURRENT KEY, the key selected
by GET NEXT KEY. All of these transactions refer to the same master
record. For instance, they may represent various purchases and payments
made by a particular customer during the month.
A
newly added record may be updated by later transaction records
having the same key. Although not likely, it is possible that one trans-
action could add a new record, several more transactions could update it,
and a final one could delete it, so that the entire sequence of transactions
would have no effect on the master file.
After all the transactions having a particular key have been processed,
NEW REC may or may not contain a valid record to be written to NEW
FILE. NEW REC does contain a valid record, the value of IN USE will
If
REC does not hold valid data, the value of IN USE is FALSE, and no
output to NEW FILE takes place.
After all of the old master and transaction records have been pro-
cessed, the last two statements of the algorithm write a sentinel record to
NEW_FILE.
Figure 17-3 shows the procedure GET NEXT KEY, which selects
the next key value to be processed.
GET_NEXT__KEY OLD_REC.KEY,
has two key values to select from:
the key of the last record read from OLD_FILE, and TRANS_REC.KEY,
the key of the last record read from TRANS_FILE. GET_NEXT_KEY al-
ways selects the smaller of the two. By always processing the smaller key
first, we new master file will be in
assure that the records written to the
ascending numerical order. This key-selection principle, which is the basis
of merging, will be discussed in more detail in Section 17.4.
Also note that the values of all valid keys are less than the sentinel
PROCEDURE GET_NEXT_KEY
GLOBAL 0LD_REC, NEW_REC. TRANS_REC CURRENT_KEY , , IN_USE
IF OLD_REC.KEY « TRANS_REC KEY THEN .
NEW_REC «- 0LD_REC
IN_USE «- TRUE
INPUT (0LD_FILE) 0LD_REC
ELSE
CURRENT_KEY <- TRANS_REC KEY .
IN_USE «- FALSE
END IF
END GET NEXT_KEY
372 17 Sequential Files
value 9999. If the sentinel record has been read for one file but not the
other, GET NEXT KEY will always select the non-sentinel key for pro-
cessing. Therefore, when the end of one file has been reached, all of the
remaining records in the other file will be processed.
If OLD_REC.KEY is less than or equal to TRANS_REC.KEY, then,
CURRENT_KEY is set to OLD_REC.KEY. If OLD_REC.KEY is greater
than TRANS_REC.KEY, CURRENT_KEY is set to TRANS_REC.KEY.
CURRENT_KEY is set to OLD_REC.KEY, then the old master file
If
already contains a record — the value of OLD REC — whose key is equal to
CURRENT_KEY. The value of OLD_REC is moved to NEW_REC for fur-
ther processing. IN_USE is set to TRUE to indicate that NEW_REC con-
tains valid data. Another record from OLD FILE is read into OLD REC.
If CURRENT_KEY is not set to OLD_REC.KEY, then there is no rec-
ord in the old master file having a key equal to CURRENT KEY (Why?).
In this case, no master record is placed in NEW REC. IN USE is set to
FALSE to indicate that NEW REC does not contain valid data.
The situation set up by GET NEXT KEY persists throughout the
transaction processing. If whose key is equal to CUR-
a master record exists
RENT_KEY, that record is stored in NEW_REC
and the value of IN_USE
is TRUE. If no such record exists, the value of IN USE is FALSE.
Figure 17-4 shows the procedure PROCESS_TRANS ACTIONS, which
controls the processing of all transactions having a particular key. The
WHILE construction processes transaction records as long as their keys are
equal toCURRENT KEY. For each transaction, the CASE construction
ADD_RECORD, UPDATE_RECORD, or DELETE_RECORD,
calls either
depending on the kind of transaction. An error message is printed if a
transaction record has an invalid transaction code. After processing each
transaction record, anew transaction record is read from TRANS FILE.
Figure 17-5 shows ADD RECORD, the procedure for adding a new
record to the master file. If IN USE is TRUE, then there is alreadv a mas-
PROCEDURE PROCESS_TRANSACTIONS
GLOBAL TRANS_REC, CURRENT_KEY
WHILE TRANS_REC KEY = CURRENT_KEY DO
.
CASE TRANS_REC.KIND OF
1:
CALL ADD_RECORD
2:
CALL UPDATE_RECORD
3:
CALL DELETE_RECORD
ELSE
OUTPUT 'INVALID TRANSACTION CODE FOR', CURRENT_KEY
END CASE
INPUT (TRANS_FILE) TRANS-REC
END WHILE
END PROCESS_TRANSACTIONS
17.3 The File Update Problem 373
PROCEDURE ADD_RECORD
GLOBAL NEW_REC, TRANS_REC CURRENT_KEY, IN_USE .
IF IN_USE THEN
OUTPUT 'CANNOT ADD RECORD', CURRENT_KEY
OUTPUT 'RECORD ALREADY IN MASTER FILE'
ELSE
NEW_REC.KEY «- TRANS_REC KEY .
IN_USE «- TRUE
END IF
END ADD_RECORD
ter record having the same key as that of the record to be added. We con-
sider it an error to add a record if a record with the same key is already
we
are free to add a record with that key. The
as the transaction record, so
KEY and BALANCE components of NEW_REC are set to the KEY and
AMOUNT components, respectively, of TRANS_REC. IN_USE is set to
TRUE to indicate that NEW REC now contains valid data.
Figure 17-6 shows UPDATE RECORD, the procedure for updating a
record in the master file. If IN USE
REC contains a mas-
is TRUE, NEW
ter record to be updated. UPDATE_RECORD uses the compo- AMOUNT
nent of TRANS_REC to update the BALANCE component of NEW_REC.
If IN USE is FALSE, the procedure complains that it cannot update a
record that does not exist.
Figure 17-7 shows the procedure DELETE RECORD, which deletes a
record from the master IN USE is TRUE, NEW_REC contains the
file. If
PROCEDURE UPDATE_RECORD
GLOBAL NEW_REC, TRANS_REC CURRENT_KEY IN_USE
, ,
IF IN_USE THEN
NEW_REC. BALANCE «- NEW_REC BALANCE + TRANS_REC AMOUNT
.
.
ELSE
OUTPUT 'CANNOT UPDATE RECORD', CURRENT_KEY
OUTPUT 'RECORD NOT IN MASTER FILE'
END IF
END UPDATE_RECORD
374 17 Sequential Files
PROCEDURE DELETE_RECORD
GLOBAL CURRENT_KEY, IN_USE
IF IN_USE THEN
IN_USE *- FALSE
ELSE
OUTPUT 'CANNOT DELETE RECORD' CURRENT_KEY ,
the key. Many other file-processing algorithms impose the same require-
ment.
If a file is not already in order with respect to the key to be used, it
5 17 24
3 19 30 35 42
5 17 24
3
19 30 35 42
17 24
3 5
19 30 35 42
24
3 5 17
19 30 35 42
24
3 5 17 19
30 35 42
3 5 17 19 24 30 35 42
3 5 17 19 24 30 35 42
3 5 17 19 24 30 35 42
3 5 17 19 24 30 35 42
FIGURE 17-8. Merge. Two ordered files are merged to give a single merged file, which is also
ordered.
the sentinel record for one input file has been read, then all of the remain-
ing records of the other input file are copied onto the output
This is file.
because the key of each of these records is smaller than the sentinel key.
Note that the principle for selecting the key of the next record to be
processed is the same for the merge algorithm and the file-up date algo-
rithm. This is no accident. The file-update algorithm is a form of merge,
but with the records of one file being used to update the records of the
other, instead of just being placed with them in the output file.
Runs. Now let's consider a sequential file to be sorted. We will confine our
attention to the keys of the records, and we will use two-digit keys for
simplicity. The file might look like this:
25 38 17 65 94 59 73 87 35 76
We can break the file down into sequences of records that are already
in order. These sequences are called runs:
25 38 17 65 94 59 73 87 35 76
376 17 Sequential Files
ALGORITHM MERGE
DECLARE 1 RECORD_l
2 KEY
2 DATA
DECLARE REC0RD_2 LIKE RECORD_l
SENTINEL «- 9999
INPUT (FILE_1) RECORD_l
INPUT(FILE_2) REC0RD_2
WHILE (RECORD_l.KEY SENTINEL)
OR (RECORD_2.KEY SENTINEL) DO
IF RECORD_l.KEY REC0RD_2.KEY THEN
;
FIGURE 17-9. The algorithm MERGE. Compare the method used here to select the next record
to go to FILE 3 with the method used in GET NEXT KEY to select the next key to be
processed.
downs.
25 38 59 73 87
17 65 94 35 76
and place the result on the output file. Then we merge the second run from
the first file with the second run from the second file and put that result on
the output file, and so on. The result is:
17 25 38 65 94 35 59 73 76 87
The runs are, of course, merged record by record as the two files are
processed sequentially. But it is necessary for the merging algorithm to de-
tect the ends of the runs. When the end of the run has been detected on
one file, all the records remaining in the current run on the other file are
moved to the output file.
We can now distribute the runs onto two files again:
17 25 38 65 94
35 59 73 76 87
17 25 35 38 59 65 73 76 87 94
single run.
The Balanced Merge Sort. One problem with the merge sort just described
is that each merge is preceded by a distribution. The distributions contrib-
ute nothing to the actual sorting, since they do not change the order of any
records. Yet they consume as much time as the merges. If we could elimi-
nate all distributions except the first,we could nearly halve the sorting
time.
One way to do this is to use four files instead of three, as shown in
Figure 17-11. As before, we start out by with a distribution: FILE 1 is
The Polyphase Sort. The balanced merge sort eliminates the separate dis-
tribution passes but requires an extra For magnetic tape, this means
file.
FILE_1: 25 38 17 65 94 59 73 87 35 76
FILE_2:
FILE_3:
Distribute
FILE_1:
FILE_2: 25 38 59 73 87
FILE_3: 17 65 94 35 76
Merge
FILE_1: 17 25 38 65 94 35 59 73 76 87
FILE_2:
FILE_3:
Distribute
FILE_1:
FILE_2: 17 25 38 65 94
FILE_3: 35 59 73 76 87
Merge
FILE_1: 17 25 35 38 59 65 73 76 87 94
FILE_2:
FILE_3:
FILE_1: 25 38 17 65 94 59 73 87 35 76
FILE_2:
FILE_3:
FILE_4:
Distribute
FILE_1:
FILE-2:
FILE_3: 25 38 59 73 87
FILE_4: 17 65 94 35 76
FILE_1: 17 25 38 65 94
FILE_2: 35 59 73 76 87
FILE_3:
FILE_4:
FILE_1:
FILE_2:
FILE^3: 17 25 38 59 65 73 76 87 94
FILE_4:
FIGURE 17-11. The balanced merge sort. By using an extra file, we can combine all but one
of the distributions with merges. This saves us from having to do separate passes over the
files for distributions.
on one fileand three runs on the other. The distribution algorithm may
have to augment the real runs with imaginary dummy runs in order to
obtain an acceptable combination.
1. What is a file?
FILE_1: 25 38 17 65 94 59 73 87 35 76 45 60 80
FILE_2:
FILE_3:
Distribute
FILE_1:
FILE_2: 25 38 59 73 87 45 60 80
FILE_3: 17 65 94 35 76
FILE_1: 17 25 38 65 94 35 59 73 76 87
FILE_2: 45 60 80
FILE_3:
FILE-1: 35 59 73 76 87
FILE_2:
FILE_3: 17 25 38 45 60 65 80 94
FILE-1:
FILE^2: 17 25 35 38 45 59 60 65 73 76 80 87 94
FILE_3:
FIGURE 17-12. The polyphase sort also avoids separate distribution passes after the initial
distribution and it uses only three files. But its operation is more complicated than that of
the other two sorts. (The example has been chosen to avoid most of the complications.)
5. Describe the input and output statements used in the algorithmic lan-
guage when more than one input and one output file are involved.
7. Draw and give the meaning of each symbol used on the system flow-
chart in Figure 17-1.
Exercises 381
9. Why, for the file-update and merge algorithms, is the key of the sen-
tinel chosen to follow every other key in numerical order?
10. update, after the sentinel has been read for the master file, any
If file
remaining records in the transaction file will be processed. But only one of
the three operations is now permitted; the other two will produce error
messages. What is the permitted operation?
11. Why are internal-sorting algorithms unsuitable for files stored on disk
or tape?
16. Give an example showing how stepdowns are used to partition a file
into runs.
17. Describe with words and illustrations the operation of the merge sort.
18. What defect of the merge sort is remedied by the balanced merge sort?
19. What defect of the balanced merge sort is remedied by the polyphase
sort?
£X®[rXgD§@£
transaction file; who drops the box of cards on the floor will
the person
probably stick the cards back in the box (in random order) quickly before
someone finds out! Modify FILE UPDATE to check that the records in
both TRANS FILE and IN FILE are in the correct order. If an out-of-order
record is found, issue an error message, pass over the out-of-order record,
and continue. (Hint: You will have to save the key of the previous record
from each file in order to check the current one for proper order.)
3. Write an algorithm to merge the runs of FILE 2 and FILE 3 and place
the results onto FILE 1. (Hint: This is more complicated than the merge
382 17 Sequential FiJes
algorithm given in the text, since merging is done run by run. That is,
when the end of the run occurs on one file, the remainder of the current
run on the other file must be moved to FILE 1 before going on to the next
pair of runs. A
run can end either because a stepdown was detected or
because the sentinel was read on that file. It may be helpful to have flags
EOR 2 and EOR 3 that will set to TRUE if either condition occurs.)
4. Drawing on the results of Exercises 2 and 3, write a merge sort algo-
rithm. The distributions and merges will be repeated until only one run
remains on FILE 1 (so you must count the number of runs that go onto
FILE 1 each time). Don't forget to write a sentinel record at the end of
each file when it has been filled; the sentinel will be needed when the file
is read.
©c^e*? ^
Random
Files
is TRUE.
—
Accessing records by giving values or ranges of values of one or —
more secondary keys is called secondary-key retrieval. Since the values of
383
384 18 Random FiJes
FIGURE 18-1. A mass storage device divided into three buckets. Each bucket can hold four
records.
Bucket 1
Record 1 of bucket 1
Record 2 of bucket 1
Record 3 of bucket 1
Record 4 of bucket 1
Bucket 2
Record 1 of bucket 2
Record 2 of bucket 2
Record 3 of bucket 2
Record 4 of bucket 2
Bucket 3
Record 1 of bucket 3
Record 2 of bucket 3
Record 3 of bucket 3
Record 4 of bucket 3
18.1 The Logical Structure of Random-access Devices 385
An
everyday example of this is a filing cabinet. The filing cabinet has
four drawers and each drawer is a bucket. Obviously, it is easier to find a
record in one drawer than it would be to examine one record in one
drawer, then another record in another drawer, and so on. We would
spend more time opening and closing drawers than we would spend look-
ing at records!
For this reason, a file cabinet has a card on the front of each drawer
bearing a legend such as A-F or G-L or M-R or S-Z. Each card gives the
range of keys of the records stored in a particular drawer. Using the cards,
we immediately narrow our search down to one drawer one bucket and — —
do our further searching inside that drawer.
all
FIGURE 18-2. A filing cabinet illustrates a hierarchically structured mass storage device.
Level 1 is the entire filing cabinet. On level 2, the filing cabinet is divided into drawers. On
level 3, each drawer is subdivided by divider partitions.
A-Z
Platters
Recording
surfaces I
Read-write
heads
disks or platters. Each platter has two recording surfaces on which infor-
mation can be stored. The outermost recording surfaces the top one on —
the top platter and the bottom one on the bottom platter are not used. —
Information is stored on and retrieved from the disks with read-write
heads. These are mounted on a comblike access mechanism whose access
arms move in and out between the platters.
Suppose the access mechanism is in a fixed position. As the disks ro-
tate, a circular portion of each recording surface passes under the adjacent
read-write head. That circular portion is called a track.
For any position of the access mechanism, there will be one track on
each recording surface that is currently passing under a read-write head.
18.1 The Logical Structure of Random-access Devices 387
The set of all such tracks is called a cylinder. For any position of the access
mechanism, we can access the tracks of one cylinder. To access a track on
another cylinder, we have to move the access mechanism.
Figure 18-4 shows the hierarchical structure of a disk pack. Since mov-
ing the access mechanism is time consuming, it is best first to narrow the
search down to a particular cylinder, instead of jumping from cylinder to
cylinder. Thus, on level 2 of the hierarchy the disk pack is divided into
cylinders.
The obvious subdivision of the cylinder is the track. For the kind of
disk pack considered here, the tracks are not further subdivided. Instead,
a track issearched for a given record by examining the records as they pass
under the read-write head. Since we must wait for the proper record to
pass under the read-write head anyway before we can retrieve it, this
search consumes no additional time. On some computer systems, this
search is done automatically by the hardware. We give the hardware the
key of the record we wish to access and the track on which it is located.
The hardware then scans the specified track for the desired record.
On some disks, a track is further subdivided into sectors. These disks
are usually used on small computers, where the automatic track-search
mechanism is not available.
FIGURE 18-4. Hierarchical structure of a disk pack. The number of cylinders and the number
of tracks per cylinder vary from one type of disk pack to another.
Disk pack
200 Cylinders
. .
applied on each level except the bottom one, on which the buckets would
simply be searched.
Our problem, then, boils down to the following: Given the primary
key of a record, find out which bucket contains the record (or should con-
tain it if the record is being stored).
The two commonly used methods of solving this problem are index
sequential access and hashing.
1 AB CG EC EG
Index
Key Bucket
EG 1
2 FA GQ LZ NP
NP 2
VP 3
3 SA TC UN VP
XL 4
4 XA XL
inserted in that bucket. Only inside that one bucket may some records have
to be moved to allow the new record to be inserted in the proper position.
It may happen, however, that the bucket into which a particular rec-
ord is to go is already full, its free space having been used up by previous
insertions. When this happens, we must use one of the free buckets. The
full bucket is split into two parts. Some of its records (usually half) are
retained in the old bucket, and the rest are placed in the free bucket. The
index entry for the original bucket must be modified, and a new index
entry must be made for the formerly free bucket. The new record can now
be inserted, since both parts of the original bucket now contain free space.
Figure 18-7 illustrates the overflow-area technique. The file is divided
into two parts: a prime area and an overflow area. Originally, all of the
Before Insertions:
AB CG
Index
Key Bucket
CG 1
FL HA LR
LR 2
XP 3
SA XP
AB BB CG
Index
Key Bucket
CG 1
FL GZ HA
HA 2
LR 4
SA XP
XP 3
JQ LR
record is also inserted into bucket 2. This causes bucket 2 to split, part of its contents staying
in bucket 2 and the remainder going into bucket 4.
390
18.2 Primary-key Retrieval 391
Before insertions:
Bucket Number
File
AB CG EC EG
Index
EG 1
EG FL HA LR NN Prime
Area
NN 2
NN
YQ
^ 3
SA XP YL YQ
YQ
Overflow
Area
Bucket Number
File
AB BB CG EC
Index
EC 1
EG 2 FL GZ HA JQ Prime
Area
JQ 2
NN
YQ 3
YQ 3 SA XP YL YQ
EG NN LR Overflow
Area
li
FIGURE 18-7. Using overflow areas to handle insertions in an indexed sequential file. The
first new record is inserted in bucket 1 and the next two into bucket 2. This pushes one record
from bucket 1 and two records from bucket 2 into the overflow area.
392 18 Random Files
records of the file are placed in the prime area. No free space is left in the
prime area. Instead, all of the free space is gathered together in the over-
flow area.
When a new
record is inserted, the index is consulted to determine
which bucket should go in. The record is placed in that bucket. But since
it
the bucket has no free space, inserting a new record will cause a record to
be pushed off the end of the bucket. The record that is pushed off the end
goes into the overflow area.
For each bucket in the prime area, there is a pair of index entries. The
first is the usual one; it contains the key of the last record in that bucket
no records have been pushed off a particular bucket, then the key
If
parts of the main and overflow index entries for that bucket are the same.
The pointer part of the overflow entry is NIL. If some records have been
pushed off, then the key part of the overflow entry is greater than the key
part of the main entry, and the pointer part points to the list of overflow
records.
The value of a pointer locates a particular record by bucket number
and position in the bucket. Thus, (5, 2) refers to the second record in
bucket 5, (6, 1) to the first record in bucket 6, and so on.
An overflow list may extend through several buckets. Thus, searching
for a record on an overflow list is less efficient than searching for it in a
single bucket. For this reason, as more and more buckets overflow and the
overflow lists become longer, access will become less efficient. Eventually,
the file will have to be reorganized. All the records will be copied into the
prime area of a new file, and we will start all over again.
The name ISAM (Index Sequential Access Method) is applied to in-
dexed sequential files using overflow areas. ISAM is incorporated in oper-
ating systems available from a number of computer manufacturers.
There are many possible ways to do the hashing calculation, but one
of the simplest is also —
one of the most effective a rare situation in com-
puter science. This calculation involves dividing the key by the number of
buckets in the prime area of the file and taking the remainder of the divi-
sion. When 1 is added to the remainder, the result is the number of the
bucket in which the record should be stored.
As we saw in Chapter 1, the operator MOD is often used to represent
the operation of taking the remainder (rather than the quotient) in a divi-
sion.
Expression Value
5 MOD 3 2
11 MOD 5 1
101 MOD 25 1
1003 MOD 100 3
Using the MOD operator, we can express the hashing calculation as:
Suppose, for instance, a file has five buckets in the prime area. Then
a record with key 137648 would be placed in bucket 4, since:
Figure 18-8 further illustrates the use of this hashing calculation to place
records in buckets.
The hashing calculation is often included in a function, called the
hashing /unction, whose argument is the key and whose value is the
bucket to which the record having that key is assigned. We can write the
hashing function as follows:
Bucket
Number
1 432165 742960
5 498234
evenly as possible, instead of filling up a few buckets and leaving the oth-
ers empty. For HASH to have this property, we must place a restriction on
NUMBER OF BUCKETS; its value must be a prime number. A prime
number is one that cannot be evenly divided by any other number, expect
for 1 and itself. Some prime numbers are
2 3 5 7 11 13 17 19 23 29 31 37
prime area and an overflow area, as was done for index sequential files
[see Figure 18-9).
Records are inserted in the prime area using the hashing function.
(Note the NUMBER_OF_BUCKETS in the hashing function is the number
of buckets in the prime area.) If the bucket whose number the hashing func-
tion yields is already full, then the record is inserted on the overflow list
for that bucket. (If this is the first overflow record for that bucket, a new
overflow list is started.)
1 432165 742960
5 498234 1
searched. If the desired record is not found in that bucket, the overflow
list for that bucket is searched. Searching the overflow list will mean ac-
cessing one or more additional buckets. Thus, accessing a record in the
overflow area is more time consuming than accessing one in the prime area.
The number of records in the prime area should not exceed about 75
percent of its capacity. If this load factor is exceeded, many buckets will
overflow, and overflow lists will become
Average access time will
long.
increase since many searches through long overflow lists will be required.
If the load factor is not exceeded, however, overflow lists will be
DECLARE 1 ITEM
2 STOCK. .NUMBER
2 TYPE
2 TYPE_LINK
2 COLOR
2 COLOR. _LINK
TYPE LINK is used to link together all records having the same value of
TYPE; COLOR LINK is used to link together all records having the same
value of COLOR.
for each value of each secondary key.
The indexes contain one entry
TYPE has five possible values —
1, 2, 3, 4, and 5 —
and so the TYPE index
has five entries. COLOR has four possible values— 'BLUE', 'GREEN', 'RED'
and 'YELLOW'— so the COLOR index has four entries.
Each index entry contains one more part in addition to the secondary
18.3 Secondary-key Retrieval 397
Main File
1 123985 1 5 'BLUE' 3
2 278943 2 7 'RED' 8
4 398732 5 10 'YELLOW 7
7 543998 2 9 'YELLOW 9
1 1 3 'BLUE' 1 4
2 2 3 ' GREEN 5 1
3 3 1 'RED' 2 2
4 6 1 'YELLOW 4 3
5 4 2
FIGURE 18-10. The multilist approach to organizing a file for secondary key retrieval.
key value and the pointer to the list of records having that value. That part
gives the number of records on the list.
The reason for giving the number of records is this. Suppose we are
requested to find the records satisfying:
We can conduct this search in two ways. We can search the list for TYPE
= 3 and select all records for which COLOR = 'RED'. Or, we can search
the list for COLOR = 'RED', and select all records for which TYPE = 3.
398 18 Random Files
Which list should we search? The shortest one, of course. And the num-
ber-of-records parts of the index entries tells us which list is shortest.
Inverted Files. An inverted file is not a file turned upside down, but an
index for the values of a secondary key. It is said to be inverted since the
secondary key plays the same role for the inverted file as the primary key
plays for the main file. The entries in the inverted file are in alphabetical
order according to the secondary key rather than the primary key.
A library, for instance, contains three inverted files in the card cat-
alog. These are the author catalog, the title catalog, and the subject
catalog. In some libraries, these are separate catalogs kept in separate
drawers. In others, the author, subject, and title cards are combined in
one catalog.
Thus, if we want to find the books on a given subject, we look up that
subject in the subject catalog, finding a card for each book on the subject
we looked up. We proceed similarly to find the books by a given author or
the books with a given title.
Figure 18-11 shows the file from Figure 18-10 with two inverted files.
There one inverted file for each secondary key. Each inverted file has an
is
entry for each possible value of the secondary key in question. That entry
consists of the secondary-key value and an occurrence list containing the
locations of all records in the main file for which the secondary key has
the corresponding value.
(In Figures 18-10 and 18-11, each record is, for simplicity, designated
by a single record number. In practice, this designation would probably
consist of two parts —
a bucket number, specifying the bucket containing
the record, and a record number, designating a particular record in that
bucket.)
Given a simple condition such as
COLOR = 'RED'
we consult the appropriate index and access all records on the occurrence
list found.
For compound conditions such as
or
we must merge two occurrence lists and use the merged lists to select the
records to be accessed.
We define two kinds of merge: the OR-merge and the AND-merge. The
OR-merge of two lists yields a list occur on one or the
of those items that
other or both of the original lists. The AND-merge of two lists yields a list
of only those items that are on both the original lists.
18.3 Secondary-key Retrieval 399
Main File
1 123985 1 *
BLUE
2 278943 2 'RED'
5 431778 1 •
GREEN
6 534219 4 BLUE
8 678920 1 •RED'
10 794235 5 'BLUE'
1 15 8 ' BLUE 1 3 6 10
2 2 7 9 ' GREEN 5
3 3 •RED' 2 8
4 6 •YELLOW 4 7 9
5 4 10
OR-merge. Consider the next entry to be processed on each of the two lists
being merged. Compare these two entries. If they are equal, place one on
the merged list and discard the other. Otherwise, place the smaller of the
two on the merged list.
400 18 Random Files
Repeat this procedure until one of the lists is exhausted. Then copy
the remainder of the other list onto the merged list.
on the merged list and discard the other. Otherwise, discard the smaller of
the two entries.
Repeat this procedure until one of the lists is exhausted. Then discard
the remainer of the other list.
17 25 35 49
15
20 25 30 35 50
25 35 49
15 17
20 25 30 35 50
25 49
15 17 20
25 3C tO
35 49
15 17 20 25
30 35 50
49
15 17 2 ; 25 -Zf)
49
15 17 2C 25 30 35
50
15 1 ( 2C 25 30 35 49
50
15 17 20 25 30 ^5 49 50
Review Questions 401
17 25 35 49
15 20 25 30 35 50
17 25 35 49
20 25 30 35 50
25 35 49
20 25 30 35 50
25 35 49
25 30 35 50
35 49
25 CA
30 35
35 49
25
35 50
49
25 35
50
25 35
50
25 35
10. Describe the procedure for locating the record with a given key in a
simple indexed sequential file.
11. Describe the method of distributed free space for organizing an in-
dexed sequential file so that insertions may be made.
16. What are two advantages of hashing? What is its main drawback?
17. In what important way does a secondary-key index usually differ from
a primary-key index? What is the reason for the difference?
21. Describe the OR-merge and the AXD-merge. What are these merges
used for?
1. If the index for an indexed sequential file is small enough, the entire
index may be read into main memory to speed up searching. Assume that
the index is stored in main memory as an array:
DECLARE 1 ENTRY ( )
2 KEY_0F_LAST_REC0RD
2 BUCKET_NUMBER
Write a procedure that, given the key of a record, will determine the
bucket in which that record is stored. Assume a simple indexed sequential
file with no provisions for overflow.
an overflow area. The procedure will return either the number of the bucket
or a pointer to the overflow list containing the desired record. The index
has the following structure:
DECLARE 1 ENTRY ( )
2 MAIN_ENTRY
3 KEY_OF_LAST_RECORD
3 BUCKET_NUMBER
2 OVERFLOW ENTRY
3 KEY_OF_LAST_RECORD
3 POINTER
4 BUCKET_NUMBER
4 RECORD_NUMBER
3. Consider a hash file with seven buckets, with each bucket able to hold
four records. Choose 21 six-digit keys at random and, using the hashing
function, insert the records with those keys into the file. Construct over-
flow lists when necessary. (Hint: To find the remainder of a division by 7
using a pocket calculator, do the following:
124735 (Key)
7)124735 (Divide by 7)
17819.28571
-17819 (Subtract off integer part)
.28571
x 7 (Multiply by 7)
1.99997
2 (Round to nearest integer
Thus, the value of 124735 MOD 7 is 2. With a little practice, this compu-
tation can be carried out very quickly on the calculator.)
INTRODUCTION JrL
TO —u
NUMERICAL
METHODS
©CM^fe U 1
Solving
Equations
ax + b =
there exists an explicit solution — a formula that gives the root of the equa-
tion in terms of the constants that appear in it:
407
408 19 SoJving Equations
x = — b/a
4x + 1 =
we have only to plug the constants into the explicit solution to get the root:
x = -- = -0.25
4
ax 2 + bx + c =
x = (-b ±Vb 2
-4ac)/(2a)
Explicit solutions exist for equations of the third and fourth degrees,
but they are quite complex. For the general equation of the fifth degree
5 4 2
+ bx + ex + dx ex + / =
3
ax -t-
no explicit solution exists. The same holds for the equations of the sixth,
seventh, and higher degrees.
Another kind of equation for which an explicit solution rarely exists is
the transcendental equation constructed using the trigonometric, logarith-
mic, or exponential functions. A few of these can be solved using special
identities, such as trigonometric identities. Bur for most, such as
sin ax — b
x
+ c =
Element being
searched for is
in first half
FIGURE 19-1. In binary search, the part of the array still to be searched is divided in half,
and only the half containing the sought-after element is retained.
array in half. We
then determined if the sought-after element was in the
first second half. We narrowed the search down to the half con-
half or the
taining the desired element and discarded the other half. We repeated the
process on the selected half, and so on. Proceeding in this way, we
quickly narrowed our search down to the element being sought.
Figure 19-2 shows how the same principle can be applied to finding
the root of an equation. We start with an interval containing one such root.
The endpoints of the interval are x_ and x_. (We will see the reason for
that notation in a moment.) We divide the interval at its midpoint
giving us two intervals: one from x_ to x mid and one from x mid to x_.
Now we determine in which interval the root lies. If it lies in the left
interval, we x + equal to x mid to narrow down the search to the left
set
interval. If the root is in the right interval, we set x_ equal to x mid to narrow
down the search to the right interval. Repeating this process, we get a se-
ries of smaller and smaller intervals, all containing the root. The succes-
410 19 Solving Equations
Root
X X.
III
1
T
1
1
1
1
X
1
X- x
|
1
x
1
•
r
1
X
w
x_
x
^ T
x_ X,
FIGURE 19-2. The principle of binary search can be applied to finding the root of an equation.
An interval containing the root is divided in half and only the half containing the root is
retained.
f[x) =
where the function f[x) is defined as equal to the left side of the equation.
Thus, if the equation is
sin ax - b" + c =
then
flxj <
flxj >
Note that although the figure shows x_ < x + , we could just as well
have x, < x_ if f[x) goes from a positive value to a negative value as x is
increased.
The interval from x_ to x+ may contain more than one root of f[x) = 0.
If we apply the half-interval method to an interval initially containing more
than one root, the successive intervals will narrow down on one of the
roots, but which one is not easily predictable in advance.
The remaining question is how long we should let the algorithm run.
That is, how do we know when x mid is a close enough approximation to
FIGURE 19-3. If f[x _) < and f(x J > 0, then there is a root of f(x) = lying between x_
and x..
: r
y = fix)
f(xj > o-
ROOt y^
(_ ^/
01 yS x X
f(x_) < - m ^m
412 19 Solving Equations
the actual root of the equation? Since we are searching for an x that will
give f{x) =
reasonable approximation would be an x mid such that the
0, a
absolute value of f(x mid ) is less than some maximum error. The user must
specify the maximum error, since it depends on the equation and the use
to which the solution is to be put.
We can now outline the algorithm:
FMID <
If 0, then XMINUS should be set to XMID; if FMID > 0, then
XPLUS should be set to XMID. That way, F(XMINUS) will still be nega-
tive, and F(XPLUS), positive, so that the interval from XMINUS to XPLUS
will still contain a root of F(X) = 0. See Figure 19-4.
(If FMID = 0, then the manipulations of XMINUS and XPLUS are imma-
terial, since the algorithm will terminate after the current pass with XMID
equal to the root of the equation.)
The initial values supplied for XMINUS and XPLUS when the algo-
rithm is called must be such that F(XMINUS) is negative and F(XPLUS) is
positive. When the algorithm terminates, XMID contains the desired ap-
proximation to the root.
Figure 19-5 shows the complete procedure HALF INTERVAL.
19.2 Systems of Linear Equations 413
fix ) <
x.
fi x„ . I >
FIGURE 19-4. If / (x mid ] < 0, then we halve the interval by setting x_ equal to x mid . if / (x mid )
> 0, then we set x_ equal to x mid In each case, the
. new interval from x_ to x_ contains a
root of the equation.
3x, + 2x + 4x = 19
2 3
6x, + 5x + 9x = 43
2 3
present another problem. Several explicit methods for solving such systems
are taught in elementary mathematics courses. Unfortunately, systems of
hundreds or even thousands of equations in as many unknowns are not
uncommon in some applications. With so many equations, it is too labo-
414 19 Solving Equations
3x. + 2x 2
+ 4x 3
= 19
6x, + 5x 2 + 9x 3
= 43
9x + 8x 2
+ 13x 3
= 64
x2 + x 3 = 5
The 6Xj terms cancel and x is eliminated from the second equation.
t
In the same way, we can multiply the first equation by 9/3 = 3 and
subtract it from the third equation. The 9x terms cancel, eliminating x^ :
3x, + 2x 2
+ 4x 3
= 19
*2 + *3 = 5
2x, + X 3
= 7
FIGURE 19-7. The equations of Figure 19-6 after using the first equation to eliminate x, from
the second and third equations.
In exactly the same way, we can now use the second equation to elim-
inate x 2 from the and third equations. Figure 19-8 shows the result of
first
these eliminations.
Finally, we can use the third equation to eliminate x 3 from the first
and second equations. Figure 19-9 shows the results of these eliminations.
FIGURE 19-8. The equations of Figure 19-7 after using the second equation to eliminate x2
from the first and third equations.
3x. + 2x 3
= 9
x2 + x 3
= 5
-x, = -3
416 19 Solving Equations
FIGURE 19-9. The equations of Figure 19-8 after using the third equation to eliminate x, from
the first and second equations. Since each equation now contains only one unknown, the
equations are easy to solve.
Now x. appears only in the first equation, x 2 only in the second, and
,
x :
= 3 3 = 1, x2 = 2, x 3
= -3 -1 = 3
Now let us write an algorithm that will carry out this elimination for
N equations in N unknowns. We assume that the coefficients on the left
side of the equations to be solved, as well as the constants on the right,
are stored in an array A of N rows and N + l columns. Figure 19-10 illus-
trates this for three equations in three unknowns. Columns 1 through N of
the array hold the left-hand-side coefficients. Column X- 1 holds the right-
hand-side constants. Each row of A represents one equation, and any ma-
nipulation of equations can be carried out on the rows of A.
We will use each equation in turn to eliminate the corresponding un-
known from the other equations. Equation 1 will be used to eliminate x.
from equations 2, 3, 4, ... equation 2 will be used to eliminate x 2 from ;
FOR I ^
1 TO N DO
(Use the Ith equation to eliminate Ith unknown
from the remaining equations)
END FOR
3 2 4 19
A - 6 5 9 43
9 3 -: 54
19.2 Systems of Linear Equations 417
FOR I <- 1 TO N DO
FOR J <- 1 TO N DO
IF J / I THEN
(Use the Ith equation to eliminate the
Ith unknown from the Jth equation)
END IF
END FOR
END FOR
F^A(J, I) /A (I, I)
FOR K <- 1 TO N+l DO
A(J, K) «- A(J, K) - F*A(I, K)
END FOR
The coefficient A(J, I) is set to 0, thus eliminating the Ith unknown from
the Jth equation.
can make the elimination somewhat more efficient as follows: We
We
know I) is going to be set to 0. Therefore, we can avoid calculat-
that A(J,
ing A(J, I] on the grounds that it is a waste of time to do a calculation if
we already know the answer.
Moreover, when the Ith equation is used for purposes of elimination,
all the coefficients A(I, 1), A(I, 2), A(I, I— 1] will have already been
. . . ,
for K = 1, 2, 3, ... ,
1-1. Hence, A(J, 1), A(J, 2) A(J, 1-1) will
not be changed by the elimination process, and we need not bother to
calculate new values for them either.
Thus, new values need only be calculated for AQ, 1 + 1), A(J, 1 + 2),
. .A(J, N + l). We can modify the elimination to read:
. ,
F^A(J, /A (I, I) I)
FOR K <- TO N + l DO 1 + 1
A(J, K) *- A(J, K) - F*A(I, K)
END FOR
F^A(J, I) /A (I, I)
The element we divide by — A(I, — I) is called the pivot eiement. Now what
if the pivot element is 0? Dividing by results in — disaster.
The system
x, + x + x = 6
2 3
Xj + x + 2x = 9
2 3
x, + 2x + 3x = 14
2 3
X !
+ *2 + X =3
6
0x + x
2
=3
3
x + 2x
2
=3
8
The next step would be to use the second equation to eliminate x 2 from
the other two equations. The pivot element would be the coefficient of x 2
in the second equation. Unfortunately, that coefficient is 0.
The simplest way out is to interchange the second and third equations:
x, + x + x =
2 3
6
x + 2x =
2 3
8
0x + x =
2 3
3
pose that A(I, I) is merely very small. Then F will be very large. In the
calculation
we are subtracting a very large number from a much smaller one (assuming
that A(J, K) and A(I, K) are of the same order of magnitude, which will
usually be the case).
If our numbers could be represented with infinite precision, this situ-
0.421357
- 983245.000000
-983244.578643
- 983245 (Round off to six places)
The .421357 has had no whatever on the answer, and the informa- effect
tion contained in it has been
Thus, small pivot elements tend to in- lost!
—
crease round-o^f error the loss of information due to rounding.
To defend against zero pivot elements, and to help defend against
roundoff error caused by small pivot elements, we proceed as follows: Be-
fore using A(I, I) as a pivot element, we search the column A(I, I),
A(I+1, I), +
A(N, I) to locate the A(L, I) having the largest
A(I 2, I), . . . ,
absolute value. We then exchange the Ith and Lth equations (the Ith and
Lth rows in A) so that A(L, I) becomes the pivot element. We then proceed
to use the Ith equation to eliminate x, from the other equations, as before.
This technique is called partial pivoting.
To find the row containing the largest of the elements A(I, I),
A(I + 1, I), A(N, I), we proceed as follows:
. . . ,
MAX_A < 1
FOR K ^
TO N DO I
IF ABS(A(K, I)) > MAX_A THEN
MAX_A ^- ABS A K I ( ( ,
) )
L ^ K
END IF
END FOR
)
FOR K <- I to N + l DO
T «- A(I, K)
A(I, K) <- A(L, K)
A(L, K) <- T
END FOR
NPLUS1 N+l
and then used NPLUSl everywhere that we need N+l. The algorithm
would be more efficient but not so easy to read. In the algorithmic language
x, + x = 2
3
x, + 2Xj = 5
You can easily verify that the exact solution to this system is x, = 1 and x 2
= 2. Hereafter, we will write exact and approximate solutions in the form
x 2 ). Thus, the exact solution to the system is (1, 2).
(x 1(
Now let us solve this system using the Gauss-Seidel method. We start
by choosing an initial approximation arbitrarily. Let us choose (0, 0).
Now we solve the first equation for xt using the current value of x 2 , .
We have:
x, = 3 - x =2
3 - = 3
Our next approximation is (3, 0). This satisfies the first equation but not
the second.
Now we solve the second equation for x 2 , using the current value
of x,:
x2 = (5 - xJ/2 = (5 - 3)/2 = 1
Thus, the next approximation is (3, 1). This satisfies the second equation
but not the first.
(0. 0), (3, 0), (3, 1), (2, 1), (2, 1.5), (1.5, 1.5), [1.5, 1.75),
(1.25, 1.75), (1.25, 1.88), (1.13, 1.88), (1.13, 1.94), (1.06, 1.94),
(1.06, 1.97), . . .
FIGURE 19-13. The Gauss-Seidel method. In this case, the successive trial solutions get
closer and closer to the exact solution. We sav that the Gauss-Seidel method converges.
= 3
Exact solution
x = 1
x = 2
Approximate solutions
Path followed
in going from
Initial
one trial solution
trial
to the next
solution
19.2 Systems of Linear Equations 423
of equations. Indeed, let us take the same system as before, but inter-
change the two equations:
x a
+ 2x = 5 2
x. + x = 3 2
Again we will solve the first equation for x and the second for x 2 but, a
,
because of the exchange, the first and second equations will not be the
same ones as before.
Again we start at the point (0, 0). We obtain the following sequence of
values for [x lt x 2 ):
(0, 0), (5, 0), (5, -2), (9, -2), (9, -6), (17, -6), (17, -14),
(33, -14), (33, -30), (65, -30), (65, -62), . . .
Obviously, we are getting further and further away from the solution (1,
2) instead of closer and closer to it. The Gauss-Seidel method does not
converge when the equations are written in this order.
Figure 19-14 shows this graphically. Solving the first equation for x^
means moving along a horizontal line to the point where it intersects the
line for the equation x + 2x 2 = 5. Solving the second equation for x 2
1
means moving along a vertical line until it intersects the line for the equa-
tion Xj + x 2 = 3. Proceeding in this way, we see that our successive "ap-
proximations" are indeed moving away from the exact solution, and will
never get nearer to it. You can easily show that this behavior will occur for
any starting point other than the exact solution (1, 2).
Clearly, then, convergence is a somewhat tricky question for the
Gauss-Seidel method. Simply changing the order of the equations which —
means changing which equation is solved for which unknown can affect —
whether or not convergence takes place. And even when convergence is
known to take place, it is difficult to say how many points must be gener-
ated to obtain a solution of the desired accuracy.
Since our main interest is in the algorithm for generating the succes-
sive approximations, we will leave further considerations of convergence
to numerical analysis courses.
How can we tell when we have approximated the solution of the equa-
tion to the desired accuracy? We could write our system of equations as:
3 - x, - x =
2
5 - x, - 2x = 2
r, = 3 - x — x
a 2
r2 = 5 - x, - 2x 2
The smaller the residuals, the more accurate is the solution. We will find
MAX R, the absolute value of the largest residual. We will consider the
424 19 Solving Equations
Exact solution
x = 1
x, = 2
x, + 2x 2
= 5
Initial
Path followed
trial
in going from
solution
one trial solut
to another
FIGURE 19-14. The Gauss-Seidel method. In this case, the successive trial solutions get fur-
therand further away from the exact solution. We say that the Gauss-Seidel method diverges.
Note that the equations are the same as those in Figure 9-13. The only thing different is which
equation is solved for x, and which for x2
.
Figure 19-15 shows the outline for the procedure GAUSS SEIDEL.
We begin an iteration by setting
MAX R
so that MAX R may be used to calculate the absolute value of the largest
residual.
We now process each equation in turn:
FOR I ^
1 TO N DO
(Process one equation)
END FOR
R <- A(I, N+ 1)
FOR J <- TO N DO
1
R *- R - A(I, J)*X(J)
END FOR
Finally, we solve the Ith equation for X(I). This is easily done using
the residual we have already calculated. This residual is the amount by
which the left side of the equation falls short of the right side. If we in-
crease A(I, I)*X(I) by R, then the two sides will be equal, and the new
residual will be zero. Increasing X(I) by R/A(I, I) does the trick:
4. Contrast the binary search for an element of an array with the half-
interval method for finding a root of an equation. In what ways are they
similar? In what ways do they differ? What would you say is the idea of
both algorithms?
10. Explain how partial pivoting remedies the problem mentioned in Ques-
tion 8 and helps alleviate the one mentioned in Question 9.
OK <- FALSE
COUNT «- 1
REPEAT
MAX_R *-
FOR I <- 1 TO N DO
R *- Ad, N + l)
FOR J <- 1 TO N DO
R «- R - A(I J)*X(J) ,
END FOR
IF ABS(R) > MAX _R THEN
MAX R ^- ABS(R)
END IF
X(I) ^- X(I) + R/A(I, I)
END FOR
IF MAX_R < MAX_ERR0R THEN
OK *- TRUE
END IF
COUNT *- COUNT + 1
UNTIL OK OR (COUNT > MAX_ITERATI0h
END GAUSS_SEIDEL
Exercises 427
11. Describe the operation of the statements used to accomplish partial pi-
voting.
[Link] a graph similar to Figure 19-13, and use it to show one way in
which the Gauss-Seidel can converge.
16. Sketch a graph similar to Figure 19-14, and use it to show one way in
which the Gauss-Seidel method can fail to converge.
19. How are the residuals used to determine when a solution of the desired
accuracy has been obtained?
$m\?©mm
1. In the half-interval method, instead of choosing x mid as the midpoint of
the interval, we could use interpolation (as in trig and log tables) to get a
value of x mid closer to the actual root. The value of x mjd is then given by
- fix.)
Xm,d X" lX XJ
/(xj - f[x J -
or
m,d j(x_)
~ /(xj - f[x.
the root.
3. In Gauss-Jordan with partial pivoting, suppose that the equations are ill
X(SUB(I) )
«- A(I. N + 1)/A(I, I)
is searched for the largest element. Then both two rows and two columns
are interchanged to bring the largest element to the pivot position. Since
columns are interchanged, the array SUB must be used as in Exercise 4.
Modify the Gauss-Jordan procedure to use full pivoting.
6. Investigate graphically the convergence of the Gauss-Seidel method for
the following systems of equations:
(a] x - y = -1
x + y = 3
(b) 2x - y =
x + y = 3
©fei^iteD3 M)
I I i
~~"
Numerical |r 11
Integration
429
430 20 Numerical Integration
teachers can let noncalculus and precalculus students solve problems with
the computer that would require calculus if solved explicitly.
There are many applications of differential equations other than the
study of moving objects. We will stick to the moving-object problem, how-
ever, since we can visualize it, and thus we can sometimes substitute
common sense for calculus.
x = f(t)
FIGURE 20-1. The object shown can move along a straight line. Its position, x, is its distance
from the origin. This distance is positive when the object is to the right of the origin and
negative when the object is to the left of the origin.
Or ugin Object
/ 1
-3 -2 2 3
>
--
X 2
/ /
X 3XIi '
• | !
i
-3 -2 2
X ~r~ - -
20.1 Formulation of the Problem 431
x = h - Vzgt
2
and so fit) = h - V 2 gt 2 .
The
velocity fvj of the object is the rate of change of x with respect to
time. Velocity in general also varies with time. For the falling body prob-
lem, for instance,
v = -gt
The acceleration (a) of the object is the rate of change of v with respect
to time. In the falling body problem, the acceleration is given by
a = -o
FIGURE 20-2. We can show the motion of an object by graphing its position as a function of
time.
)
2 =
FIGURE 20-3. We can also describe the motion of an object by means of a table. The table
gives the position and velocity of the object at different times.
t X V
(sec 1 ft) (ft/sec)
1 16 32
2 64 64
3 144 96
4 256 128
5 400 160
6 576 192
7 784 224
8 1024 256
9 1296 288
10 1600 320
20.2 Problems Involving Only Position and Velocity 433
Equations involving only position and velocity are not too common in
mechanics, but they occur frequently in other disciplines. For instance,
let the "position" x be the population of a certain environment with people
v = kx
v = cxfb — xj
v = fix, t)
Thus, if we drive for three hours, keeping the speedometer on 55 mph all
distance = 55 mph x 3 hr
distance = 165 mi
x i
- xo = w {
,
- u
434 20 Numerical Integration
or
x, = x + v(t, - t )
If we let t be any time, and x our postion at that time, then we can
express our position x as a function of the time t
x = x + v(t - tj
x = x + v(t - tj
FIGURE 20-4. If v is the velocity of the object at time t , then x = x + v(t - t ) is the
equation of the straight line that is tangent to x = /(tj at the point (t 0> v J.
x-axis
)Difference
Sbetween
|
curve and
tangent line
t-axis
20.2 Problems Involving Only Position and Velocity 435
graphs as a straight line that passes through the curve at the point (t x ).,
—
Furthermore, the straight line is tangent to the curve that is, the line and
the curve are going in the same direction at time t Figure 20-5 illustrates
.
coincide. Therefore we can, with reasonable accuracy, use the straight line
x = x + v{t - y
to predict the positionx of the object at time t, provided only that t - t
is not too large. The larger t — t becomes, the greater the distance be-
tween the line and the curve becomes, and the greater becomes the error
of using the equation of the line to describe the motion of the body.
Thus, we found
a way of calculating the postion of the moving object
as a function of time, but it works only for times near t Can we use this .
intervals: t to t x , t, to t
2
, and so on.
Let
h = t1+] - t
v = f{x, t)
FIGURE 20-6. We can divide the t-axis into intervals sufficiently small so that the curve can
be approximated by a tangent inside each interval.
Tangent line
x-axis
V tn-,*n
t-axis
h
20.2 Problems Involving Only Position and Velocity 437
v = f[x ,
y
Then in the interval t to t lt the position of the body is given, with ac-
ceptable accuracy, by:
x = x + v [t - t )
If we set t - t equal to t
a
- t , which is equal to h, we can calculate the
position x 1 of the object at time ta :
= x + v h
Now we can proceed in exactly the same way to calculate the position
x 2 of the object at time t 2 .
We start by defining:
v a
= fix,, y
In the interval tt to t
2
, then, we can represent the motion of the body with
acceptable accuracy by:
x = X] + v,(t - tj
Setting t - t, equal to t
2
- tv which equals h, we get the position x2 :
x = 2
x, + v,h
Time Position
t. X.
x = xo
i
+ vo h where v = /(x , t )
x2 = x 1
+ v,h where v, = /(x,, tj
so that their values will be xi+1 and ti+1 respectively, we do the fol-
lowing:
V <- F(X, T)
X «- X + V*H
T <- T + H
where H is the size of the time intervals. These statements are executed
repeatedly for each new X and T value desired.
Let us write a procedure to integrate v = j[x, t) using the Euler
method. We will supply the procedure with the starting time and position
TO and X0, the number, N, of new points to be calculated, the time in-
terval size H, and the function F. The procedure will return its results in
two arrays, T VALUES and X VALUES. After the procedure executes,
the value of T_VALUES(I) will be tp and the value of X_VALUES(I) will
be x,. Figure 20-7 shows the procedure EULER.
accumulate in the Euler method. Even though the error in going from time
t,to time ti+1 may be small, the accumulated error in x n may be substantial.
We can improve the accuracy, in theory, by making h smaller. In
practice, this has its own pitfalls. If we make h very small, then in
x .
,
= x + . v.h
we will be adding a very small number, v,h, to a much larger one, x,. We
saw in the last chapter that adding a smaller number to a much larger one
aggravates round-off error. When we make h very small, we just trade
round-off errors for errors that come from h being too large. We need some
other plan for increasing our accuracy.
Let us go back to the equation:
xi+1 = x, + vh
Now v, is the velocity of the object at time t,. This velocity will change
during the time from t, to t
1 + 1
, in fact, it will be:
It seems reasonable that our results would be more accurate if, instead of
v,, we used the average of v and vi+v Then xi+1 will be given by:i
x ,
= x + Vzfv. + v. Ah
value we
will eventually calculate for xi+1 But v', +1 is a good approxima- .
We can easily write an algorithm for the improved Euler method. Us-
ingVI for v, and V2 for v' i+1 , we get the procedure IMPROVED_EULER
shown in Figure 20-8.
The Runge-Kutta Method. The idea behind the improved Euler method
can be carried even further. We can achieve still greater accuracy by mak-
ing more estimates of the velocity during the time interval to ti+1 and t,
v, = v = fix, t,)
v2 = f[ Xi + Vzvji, t, + 7zh)
440 20 Numerical Integration
PROCEDURE IMPROVED_EULER(TO. XO N, H, F, ,
T_VALUES, X_VALUES)
X «- XO
T «- TO
FOR I «- 1 TO N DO
VI «- F(X, T)
V2 «- FIX - V1*H, T - H)
X *- X + 0.5*(V1 - V2)*H
T «- T + H
X_VALUES(I) *- X
T_VALUES(I) <- T
END FOR
END IMPROVED_EULER
and
v3 = /(x, + %v2h, t + V 2 h)
v4 = f[x, + v 3
h, t, + h)
[Link] that each estimate is used in computing the next one: v, is used
in computing v 2 v 2 is used in computing v 3 and v 3 in computing v 4
, , .
The average
v, + 2v, + 2v, + v.
—
v, + 2v, + 2v, + v, ,
x + * h
time t,, two are at time t + ^Izh, and one is at time t,_ r 1
Furthermore,
v, + 2v„ + 2v, + v A
velocities estimated at the midpoint of the interval are each given twice as
much weight as those estimated at the endpoints.
20.3 Problems Involving Position, Velocity, and Acceleration 441
x-axis
^h
^v
t-axis
t t + -h t + h = t 1+ ,
An analysis of why these particular estimates are made, and why they
are weighted the way too complicated for this
they are in the average, is
book. Even numerical analysis texts often omit this analysis, which in-
volves lengthy and complex algebra.
Figure 20-10 shows the procedure for the Runge-Kutta method which
is a straightforward extension of the one for the improved Euler method.
PROCEDURE RUNGE_KUTTA(TO. XO N H F. . ,
T_VALUES X_ VALUES
X «- XO
T «- TO
FOR I *- 1 TO N DO
VI «- FIX. T)
V2 «- FIX + 0.5*V1*H, T - 5*»H .
or
ma = F
where m is the mass of the object, a is acceleration, and F is the net force
acting on it.
a = F/m
In general, F/m depends on the position and velocity of the object, as well
as on time. Thus, we have:
a = f(x, v, t)
This is the equation that must be integrated to find the motion of the object.
F = -bv kx
The term kx represents the force exerted by the spring. The constant k is a
measure of the stiffness of the spring. The term bv represents the frictional
force exerted (mainly) by the air as the weight moves through it. The con-
20.3 Problems Involving Position, Velocity, and Acceleration 443
Origin
x >
ma bv - kx
where m is the mass of the object. The acceleration is then given by:
a = -{b/m)v — (k/m)x
lated to velocity in the same way that velocity is related to position (see
Figure 20-12.) If a problem involved only acceleration and velocity, we
could use the methods of the last section but with velocity in place of
position and acceleration in place of velocity.
444 20 Numerical Integration
v-axis
v = v + a(t - t ;
t-axis
FIGURE 20-12. Velocity and acceleration are related in the same way as position and velocity.
Compare this figure with Figure 20-4.
The Euler Method. Let's generalize the Euler method to handle position,
velocity, and acceleration. Suppose that the acceleration is given by:
a = f[x, v, t)
a = /( x o> vo> U
Knowing a we can calculate v r Remembering that velocity is calculated
,
X, = Xo + V° h
X = X + V h
!
V = V + Q h
l
Q = /( X 0- V 0- U-
x 2 = x, + v,h v 2 = v, + a.h a, = f[x x v, tj
x n = x n-1 + v n — ,h
, vn = vn — +.
1
a n — ,h a n—
n ,
1
= f(x n — 1*
J*- ., v n — 1*
„ t ,1
n — A*
The Improved Euler Method. The improved Euler method is also easily
extended to handle acceleration as well as velocity and position.
Now we make two estimates of acceleration and velocity:
Al <r- F(X, V, T)
VI «- V
A2 <- F(X + V1*H, V + A1*H, T + H)
V2 <- V + A1*H
FIGURE 20-13. This version of the procedure EULER solves equations involving position,
velocity, and acceleration.
The average of Al and A2 is then used to estimate the next value of V; the
average of VI and V2 is used to estimate the next value of X. Figure 20-14
shows the procedure for the improved Euler method.
(2tegG[]®[rDg
1. What is a differential equation?
6. If an object travels with constant velocity, what is the rule for finding
how far it will travel in a specified amount of time?
X = x„ + v„t
FIGURE 20-14. This version of IMPROVED EULER solves equations involving position, ve-
locity, and acceleration.
PROCEDURE IMPR0VED_EULER(T0, X0 V0 N, H, F, , ,
8. Describe the Euler method for a problem involving position and veloc-
ity only.
11. Give the procedure for the improved Euler method and explain its op-
eration.
12. The Runge-Kutta method follows the same general idea as the im-
proved Euler method but differs in details. How many velocity estimates
(per interval) are used in the improved Euler method? In the Runge-Kutta
method?
13. At what points is the velocity estimated in the improved Euler method?
In the Runge-Kutta method?
14. How are the velocity estimates averaged in the improved Euler
method? In the Runge-Kutta method?
15. In view of Newton's Second Law, why do the equations describing
moving objects usually involve acceleration as well as position and ve-
locity?
18. When dealing only with position and velocity, we need only specify
the value of x time
at t . What must we specify for problems involving
acceleration as well?
20. What additional estimates, corresponding to VI, V2, V3, and V4,
must be introduced to generalize the Runge-Kutta method to problems in-
volving acceleration?
:&?>:-
procedures using the methods we have studied to integrate each of the fol-
lowing:
-x
449
450 For Further Reading
Extensive discussion of input and output devices can be found in data pro-
cessing books such as:
Chapters 17 and 18. The file-update algorithm given in Chapter 17, which
was invented by W. H. J. Feijen, is a substantial improvement over many
such algorithms found in textbooks. It is described in:
In recent years there has been much interest in organizing files into data
bases, which have a structure of their own apart from the programs that
manipulate them. Some references in this area are:
Pascal. Many books on Pascal are being published now; check your library
and book store for recent selections. Of the following, the books by Bowles
cover UCSD Pascal and the UCSD Pascal [Link] user manual and
report by Jensen and Wirth is the standard reference on Pascal. The remain-
ing four references are to Pascal textbooks.
to be as simple and informal as possible, so you can express your ideas for
algorithms without getting bogged down in technicalities.
The time eventually arrives, however, when you want a computer to
execute some of your algorithms. Then you must translate your algorithms
from the informal algorithmic language into one of the formal programming
languages available for the computer system you wish to use.
Once formulated in the algorithmic language, algorithms can be trans-
lated into almost any programming language with little difficulty. Still, we
can expect the job to be easier if the programming language is similar in
structure to the algorithmic language and, like the latter, emphasizes the
basic operations of sequencing, selection, and repetition.
A language that satisfies these requirements is Pascal. This language
was specifically designed for teaching computer science. Recently, how-
ever, Pascal has moved out of the classroom and into the real world of
everyday programming. Pascal is now established as one of the major pro-
gramming languages.
This supplement should be used in conjunction with the main text.
The topics taken up in the supplement correspond to those in the main
text and are taken up in the same order. Figure P-l shows the correspon-
dence between sections in the main text and sections in this supplement.
Each section in the supplement assumes that you have read the corre-
454
P.l Data Types and Vaiues 455
FIGURE P-l. The correspondence between sections in the supplement and those in the main
text. Sections P.15 and P. 27 don't correspond to any sections in the main text. Section P.15,
however, should be read before going on to the following sections.
sponding section in the main text (if any) and concentrates on showing
them more rapidly. Another distinction between the two is that operations
on integers always yield exact answers, but some operations on real num-
bers only give approximate results.
An integer is a whole number that does not contain a decimal point.
The following are examples of integers:
When the sign is omitted, the integer is assumed to be positive. Thus +25
and 25 represent the same value.
Commas are not allowed in writing integers or any other numbers.
Thus, 1,375 is invalid. In Pascal, we must write 1375 instead.
A real number can be written with a decimal point:
1.25 95.0 -3.1416 +6.25
At least one digit must precede and follow the decimal point. The follow-
ing are invalid:
721. .372
721.0 0.372
the left of the E. In the following, the three real numbers on each line are
equivalent:
changeably. The two values are represented differently inside the com-
puter, and some of the operations that can be carried out on them are
different.
'GOpD MORNING*
'3.1416'
'
$%#&(a ? !
'
1
'
(One blank space)
The quotes enclose the string but are not part of it. Thus, the string
' HELLO
must be written
must be written
P.2 Output
In the algorithmic language we don't worry about the details of how com-
puter output be arranged on display screens or printed pages. When it
is to
WRITELN (250)
WRITELN (3. 14159)
WRITELN 'HELLO! (
*
250
3.14159
HELLO
Note that the three statements in the example are separated by semi-
colons. We can see this more clearly if we write all of the statements on
the same line:
WRITELN;
WRITELN 'HOW ARE YOU TODAY?'
(
GOOD MORNING.
(This line skipped)
HOW ARE YOU TODAY?
1020-30-4050
1.10000 2.20000-3.30000-4.40000 5.50000
0NETW0THREEF0URFIVE
Unfortunately, the spacing of the items (or lack of it) leaves something
to be desired. What's more, the details of the spacing vary from one ver-
sion of Pascal to another, so if you try the preceding three statements on
your computer, you may well find that the printed items come out spaced
differently.
WRITELN(250:10)
bbbbbbb250
To make up the five-character fields, 10, 20, and 50 are each preceded by
three blank spaces, while -30 and -40 are each preceded by two blank
spaces. Replacing the b's by the blank spaces they represent, we see that
the actual printout looks like this:
10 20 -30 -40 50
WRITELN (
' ONE ' : 6 , TWO • : 6 , ' THREE ' :
6 , ' FOUR • : 6 , ' FIVE ' :
6
produces
bbbONEbbbTWObTHREEbbFOURbbFIVE
prints the value 2.67 in a field seven characters wide and with three digits
to the right of the decimal point:
bb2 670
.
The statement
10 20 30 40 50 60 70 80
10 20 30
40 50
60 70 80
and the next WRITE or WRITELN statement begins printing on a new line.
We will use WRITELN much more frequently than WRITE, since or-
dinarily we want each output statement to produce a single line of output.
Sometimes, however, it comes in handy to have several output statements
print on the same line, and then we can put the WRITE statement to good
use.
The arithmetic operators in Pascal are the same as those in the algorithmic
language with two exceptions: (1) Pascal does not have an exponentiation
operator, so the operator ** does not occur, and (2) Pascal has two addi-
tional division operators, DIV and MOD, that are used only with integers.
The following table summarizes the arithmetic operators in Pascal:
f addition
- subtraction
* multiplication
/, DIV, and MOD division
462 Pascal Supplement
7 + 4 = 11
7.0 + 4 = 11.0
7 + 4.0 = 11.0
7.0 + 4.0 = 11.0
3/2 = 1.5
3.0/2 = 1.5
3/2.0 = 1.5
3.0/2.0 = 1.5
DIV andMOD take only integers as operands and yield integers as re-
[Link] operators allow us to do quotient-remainder division, with
DIV yielding the quotient and MOD the remainder. For example, 30 di-
vided by 8 yields a quotient of 3 and a remainder of 6. Therefore,
30 DIV 8-3
30 MOD 8=6
The arithmetic operators have the same priorities in Pascal as in the
algorithmic language. The priority of DIV and MOD is the same as for /.
Since there is no exponentiation operator, the arithmetic operators in Pas-
cal have only two levels, of priority:
12/2 DIV 3
is invalid. Since / and DIV have the same priority, / will be applied first,
giving
6.0 DIV 3
P. 5 Writing Pascal Programs 463
But 6.0 is not a valid operand for DIV, whose operands must be integers.
P. 4 Functions
Pascal has five built-in functions that apply to integers or real numbers:
The arguments of ABS and SQR can be either integers or real numbers.
The value of the function has the same type as its argument. For SQRT.
the argument can be either an integer or a real number, but the result is
always a real number. For TRUNC and ROUND, of course, the argument
is always an integer, and the result, a real number, since the purpose of
cussing to write a complete PASCAL program. Figure P-2 shows the Pascal
:3:c:;s;
A SIMPLE PASCAL PF : SRAM *
IN
rELN 3 +5 = '
. 3+E
-5 = '
.
3-
*5 - 3ȣ
'
,
3 +5 = 8
3-5 = -2
3*5 = 15
3/5 = 0.6
SORT (1.69) = 1.3
The Program Heading. Referring to Figure P-2, the first line of the program
is the program heading:
PROGRAM EXPRESSIONS;
3. An identifier must not be the same as a reserved word, a word that has
a specific use in the Pascal language. Examples of reserved words in our
example program are PROGRAM, BEGIN, and END. Thus PROGRAM
would not be a valid identifier. A list of all the reserved words is given in
an appendix to this supplement.
4. To save memory, the Pascal language processor keeps track of only the
first eight characters of each identifier. Identifiers that are intended to be
different from one another must differ in their first eight characters. Thus
the computer would confuse EXPRESSIONS, EXPRESSION, and EXPRES-
SIONS considering all three to be the same identifier.
In some versions of Pascal, the program heading must include a list of
all files used by the program. A file is any source from which data can be
that required the files to be listed in the program heading, its program
heading would be
is a comment. Comments are intended for human readers and are ignored
The Statement Part. The statement part of the program contains the state-
ments that the computer is to execute.
Notice that the statements are bracketed by the reserved words BEGIN
and END. A group of statements bracketed by BEGIN and END is said to
form a compound statement. The statement part of the program is always
a compound statement.
The statements making up a compound statement are separated by
semicolons. Note that there is no semicolon between BEGIN and the first
statement nor between the last statement and END.
The statements making up a compound statement are usually indented
with respect to BEGIN and END. This makes it easy to see at a glance which
statements make up a particular compound statement without having to
hunt through a complicated program to find the END that goes with a par-
ticularBEGIN.
The period following END indicates the end of the program.
P.6 Variables
Variable Names. Variable names in Pascal are identifiers and so must sat-
isfy the four restrictions listed in the last section. A variable name must
begin with a letter of the alphabet; its remaining characters can be letters
or digits. Reserved words must not be used as variable names, and variable
names intended to be different must differ in their first eight characters.
The following are some examples of valid variable names in Pascal:
COST AMOUNT
X 15
SUM SALESTAX
466 Pascal Supplement
SALESTAX1 SALESTAX2
are both valid, but the computer will consider them to be identical, which
is almost certainly not what the programmer wanted.
VAR
AMOUNT: REAL;
COUNT: INTEGER;
VAR
X, Y, Z: REAL;
I, J, K: INTEGER;
As with strings, the single quotes enclose the character values but are not
part of them. The single quote or apostrophe character is represented as
follows:
In o/ther versions of Pascal, the programmer must define the data types of
string variables using techniques that we will take up later.
The variable declaration part
VAR
BOOLEAN;
CHAR;
STRING;
P.7 Assignment
Pascal uses the symbol =
for its assignment operator instead of the left-
:
VAR
I INTEGER;
X REAL ;
P BOOLEAN;
C CHAR;
S STRING:
;
I = 25;
X = 3.14;
p = TRUE;
c = 'Z' ;
s = 'PASCAL'
I 25 X 3.14 P TRUE
C 'Z' S 'PASCAL'
X :
= 25;
A :
= -73
are valid. Pascal will convert the integers to the corresponding real num-
bers so that X and A receive the following values:
X 25.0 A -73.0
I :
= 25.0
I :
- TRUNC 32 75 ( .
)
N :
= ROUND (32. 75)
I 32 N 33
) ;
P.8 Input
Pascal has two statements for input, READ and READLN, corresponding
to WRITE and WRITELN for output.
READLN
reads successive values from a line of input and assigns the
READLN statement. For example,
values read to the variables listed in the
consider the statement
READLN(X, Y, Z)
where X, Y, and Z are real variables. If, when this statement is executed,
the user enters
then X is assigned the value 3.14, Y the value 7.5, and Z the value 1.0.
The effect is precisely the same as if the assignments
X : = 3.14;
Y : = 7.5;
Z : = 1.0
READLN (
I
3.14
the program will terminate with an error message, since a real value can-
not be assigned to an integer variable.
Pascal will, however, convert an integer value to the corresponding
real value, just as for assignment statements.
Character and string values are entered without enclosing them in
quotes. For instance, suppose C is a character variable and S is a string
variable. The statements
READLN C ( )
READLN(S)
read a character from one line and a string from the next line. If, when
these statements are executed, the user types
THIS IS A STRING
; ;
A string value extends all the way to the end of the line on which it is
typed. Therefore, no other value can follow a string on the same line,
since everything else on the line is considered to be part of the string.
The READLN statement always accepts a full line of input and ignores
any unneeded data. For example, consider the statements
READLN(X)
READLN(Y, Z)
1.8 7.3
2.5 3.9
X assigned the value 1.8; the value 7.3 is ignored. Y is assigned the value
is
2.5 and Z
is assigned the value 3.9
Occasionally, we may need to let more than one input statement read
from the same line of input data. In that case we can use the READ state-
ment, which remains on the same line of input after reading the requested
data. For instance, suppose the statements
READ(X)
READ(Y, Z)
1.8 7.3
2.5 3.9
then X is assigned the value 1.8, Y the value 7.3, and Z the value 2.5. The
value 3.9 is still available for use by the next READ or READLN statement.
In interactive versions of Pascal, where the user types in data as the
program needs it, the program should print a message requesting each line
of data. Such messages are call prompts. For instance, suppose a program
wants the user to enter the length, width, and height of a box. It could use
the following statements:
PROGRAM CONVERT
(
* CONVERT FEET AND INCHES TO CENTIMETERS *)
VAR
FEET, INCHES TOTALINCHES: INTEGER;
CENTIMETERS: REAL;
BEGIN
WRITE! 'ENTER FEET AND INCHES:
'
J
READLNIFEET, INCHES)
TOTALINCHES = 12*FEET + INCHES;
CENTIMETERS = 2.54*T0TALINCHES;
WRITEfFEET, FEET '. INCHES, INCHES =');
'
CENTIMETERS'
END.
The prompt was typed by the computer, the remainder of the line by the
user. The variables L, W, and H receive the values 25.3, 8.7, and 3.9,
respectively.
your version of Pascal does not allow you to interact with a program
If
PROGRAM PURCHASE:
(* COMPUTE COST OF PURCHASE *)
VAR
PRICE, DISCNTRATE, TAXRATE, DISCOUNT. TAX: REAL;
BEGIN
WRITE!' ENTER PRICE, DISCOUNT RATE, AND TAX RATE:
READLNf PRICE, DISCNTRATE, TAXRATE);
DISCOUNT = PRICE*DISCNTRATE
:
PRICE = PRICE-DISCOUNT;
:
TAX := PRICE*TAXRATE;
PRICE = PRICE + TAX;
:
END.
472 Pascal Supplement
P. 9 Conditions
Boolean values in Pascal correspond to logical values in the algorithmic
language. In each language the values in question are represented by TRUE
and FALSE. TRUE and FALSE represent Boolean values in the same way
that 3.14 represents a real number, 25 represents an integer, and 'PASCAL'
represents a string.
Three of the relational operators in Pascal are identical to their coun-
terparts in the algorithmic language. Two others are similar:
¥ <>
< <
> >
sS <=
=2 >=
we incorporate the relational operators into our table of priorities for Pas-
cal, we get
3 < 5
6*4 = 7*3
•JOE' <= 'JIM'
The IF Statement. For one-way selection, we use the following form of the
Pascal IF statement:
false, no action is taken, and the computer goes on to the next statement
in the program.
Note that the IF statement contains another statement as a part. This is
characteristic of Pascal; a number of Pascal statements can contain other
statements as parts.
Although we can write the controlled statement on the same line as IF
condition THEN, readability is usually improved if we write the statement
on the line below, indented with respect to IF condition THEN to show
that it' is a continuation of the IF statement:
IF condition THEN
statement
IF I = J THEN
J = K:
causes the computer to compare the values of I and J. If the two are equal,
the value of K is assigned to J. Otherwise, no action is taken, and the
computer goes on to the next statement in the program.
When an IF statement is followed by another statement, the semicolon
separating the two comes after the complete IF statement, NOT after the
IF-THEN part:
I :
= 5;
IF I = J THEN
J = K;
: (* NOTE SEMICOLON *)
K : = K-l
BEGIN
I 1-1
J J+l
K
END
IF I < J THEN
BEGIN
I : = I-l;
J :
= J + l;
K :
=
END
IF I > 5 THEN
BEGIN
I : = 1;
WRITELN(J)
END; (* NOTE SEMICOLON *)
J : = J+l
The ELSE Part. The IF statement in Pascal has two forms. We have already
seen one form, which has only one controlled statement. The other form
has two controlled statements:
PROGRAM WAGES;
(* COMPUTE EMPLOYEE'S GROSS WAGES *)
VAR
NAME: STRING;
HOURS, RATE, GROSS, EXTRA: REAL;
BEGIN
WRITE! 'NAME? '
)
READLN(NAME)
WRITE 'HOURS AND RATE?
(
'
)
END;
WRITELNf 'GROSS WAGES FOR ', NAME, '
ARE , GROSS 7
: :
2
END.
cuted. One statement or the other is always executed, but never both. After
the selected statement has been executed, the computer goes on to the next
statement in the program.
For ease of reading, statement-1 and statement-2 are usually written
on separate lines, indented with respect to IF and ELSE:
IF condition THEN
statement-1
ELSE
statement-2
IF I = THEN
I :
= J
ELSE
I = K; : (* NOTE SEMICOLON *)
WRITELN(I)
IF I = THEN
I :
= J
; ; ;
ELSE
BEGIN
I = K;
K =
END; NOTE SEMICOLON
WRITELNC
you may modify the program to put integers in numerical order instead of
strings in alphabetical order. You may wish to try a more challenging ver-
sion of the program that puts three values into alphabetical or numerical
order.
P. 11 Nested if Statements
We know that some Pascal statements can contain
other statements as
parts. When statement contains another statement of the same kind, we
a
say that the statements are nested.
IF statements can be nested. For example, consider the general form
of the IF statement with ELSE part:
IF condition-1 THEN
statement-1
ELSE
statement-2
PROGRAM ALPHABETIZE;
(* PRINT TWO STRINGS IN ALPHABETICAL ORDER *)
VAR
FIRST, SECOND: STRING;
BEGIN
WRITE! 'FIRST STRING? ');
READLN( FIRST)
WRITE! 'SECOND STRING? '
)
READLN( SECOND)
IF FIRST <= SECOND THEN
WRITELNf FIRST, ','
SECOND)
ELSE
WRITELNf SECOND, '. FIRST)
'
END.
P. 11 Nested if Statements 477
IF condition-1 THEN
IF condition-2 THEN
statement-3
ELSE
[Link].t~4
ELSE
statement-2
dition-1 is true, then the nested IF statement will be executed. This means
that if condition-1 is true and condition-2 is true, then statement-3 will be
executed. But if condition-1 is true and condition-2 is false, then state-
ments will be executed.
We can summarize the results of our reasoning in the following table
IF condition-1 THEN
statement-1
ELSE
IF condition-2 THEN
statement-3
ELSE
statement-4
following IF statement (the words condition and statement have been ab-
breviated to get the IF statement all on one line):
478 Pascal Supplement
The question is, to which of the two IF-THEN parts does the ELSE
part go? Put another way, if we write the statement in indented form, in
which of the following two ways should we indent it?
We
cannot answer this question based on what we already know. We
just have to be told the rule that Pascal compilers follow when processing
IF statements. The rule is this: each ELSE part goes with the nearest pre-
ceding IF-THEN part that doesn't already have a matching ELSE part. Ac-
cording to this rule, the ELSE part in the example goes with the second IF-
THEN part, not the first. The indentation on the left is correct; the one on
the right is highly misleading since it doesn't reflect the way in which the
Pascal compiler will actually process the statement.
The Pascal compiler pays no attention to indentation, but analyzes
statements according to rules such as the one just given. If we should mis-
takenly indent the statement as shown on the right, we would manage
only to confuse ourselves as to how the statement will actually be exe-
cuted. Incorrect indentation is worse than none at all, for it almost forces
upon us a misunderstanding of how the computer will execute the improp-
erly indented statement.
Figure P-7 illustrates nested IF statements in a Pascal program. This
program corresponds to Example 3 in Chapter 6.
IF condition-1 THEN
statement-1
; ; ) ; )
PROGRAM QUESTION;
(* ASK A QUESTION AND CHECK THE ANSWER »)
VAR
ANSWER: STRING;
BEGIN
WRITE('WHAT IS THE CAPITOL OF WEST VIRGINIA? ');
READLN( ANSWER)
IF ANSWER - 'CHARLESTON' THEN
WRITELNf 'YOU ARE RIGHT'
ELSE
BEGIN
WRITE) 'NO. TRY AGAIN: '
)
READLNf ANSWER)
IF ANSWER = 'CHARLESTON' THEN
WRITELNf 'YOU GOT IT RIGHT THIS TIME")
ELSE
BEGIN
WRITE('NO, CHARLESTON IS THE CAPITOL OF
WRITELNf 'WEST VIRGINIA'
END
. END
END.
ELSE
IF condition-2 THEN
statement-2
ELSE
IF condition-3 THEN
statement-3
ELSE
statement-4
condition-1 statement-1
condition-2 statement-2
condition-3 statement-3
statement-4
)
) ;
With the aid of this table, we can state a very simple rule for inter-
preting the IF statement: Start from the top of the list of conditions and go
down the list. When you find the first true condition, execute the corre-
sponding statement. If all of the conditions are false, execute the last state-
ment, the one that doesn't correspond to any condition.
We wrote our IF statement in such a way as to emphasize the nesting
of the various IF statements making it up. Usually, it's clearer to write the
statement in such a way as to emphasize the correspondence between the
conditions and the controlled statements:
IF condition-1 THEN
statement-1
ELSE IF condition-2 THEN
statement-2
ELSE IF condition-3 THEN
statement-3
ELSE
statement-4
PROGRAM LETTERGRADE;
(* CONVERT NUMBER GRADE TO LETT1
VAR
NUMBERGRADE: INTEGER;
BEGIN
WRITE 'NUMBER GRADE? ')
(
READLN NUMBERGRADE
( )
The CASE Statement. The Pascal CASE statement is very similar to the
CASE construction in the algorithmic language. We can best illustrate the
Pascal case statement with an example:
CASE I OF
1 statement-1
2 statement-2;
3 statement-3
4 statement-4
CASE 1-3 OF
1, 2, 3: statement-1;
4, 5: statement-2;
6, 7, 8: statement-3
END
CASE LETTERGRADE OF
'A' SCORE = 4
'B' SCORE = 3
'C SCORE = 2
'D' SCORE = 1
•F' SCORE =
END
; ; ;
Figure P-9 gives a Pascal program using the CASE statement. This pro-
gram corresponds to the second version of the algorithm LETTER GRADE
in Chapter 6.
A < B AND C = 25
is erroneous. Since AND has a higher priority than < and = , the computer
will start out by trying to evaluate:
B AND C
PROGRAM LETTERGRADE;
(* CONVERT NUMBER GRADE TO LETTER GRADE *)
VAR
NUMBERGRADE. RANGE: [NTEGER;
BEGIN
WRITE 'NUMBER GRADE?
(
); '
READLN( NUMBERGRADE)
RANGE = NUMBERGRADE DIV 10;
: :
CASE RANGE OF
0, 1, 2, 3, 4, 5: WRITELN( 'F' )
6: WRITELN( 'D' )
7: WRITELN( C ' )
8: WRITELN( 'B' )
Aside from not being what we intended, this is erroneous because B and
C are integer variables, and the Boolean operators can only operate on
Boolean values.
Instead, we must write:
Now the computer will apply the relational operators before attempting to
apply the Boolean operator. Since the relational operators yield Boolean
values, all will be well.
Thus, Example 6 of Chapter 6 must be written:
P.14 Repetition
The Repetition Statements. The repetition statements in Pascal are very
similar to the corresponding constructions in the algorithmic language.
Corresponding to the WHILE construction, we have the WHILE statement:
Usually, the statement begins on the line following WHILE and DO:
WHILE condition DO
statement
all.
I = 0;:
WHILE I <= 20 DO
BEGIN
WRITE(I:4) ;
I = 1+5 :
END
484 Pascal Supplement
5 10 15 20
(Note the use of WRITE, as opposed to WRITELN, to cause all five values
tobe printed on the same line.)
Pascal has a REPEAT statement that is precisely the same as the RE-
PEAT-UNTIL construction in the algorithmic language:
REPEAT
statements
UNTIL condition
The following two examples contrast the WHILE and REPEAT state-
ments:
1 = 21;
: I := 21;
WHILE I <= 20 DO REPEAT
BEGIN WRITE(I:4);
WRITE(I:4) ; I = 1+5
:
FOR I :
= L TO M DO statement
FOR I :
- L D0WNT0 M DO statement
; ; ;
FOR I - 5 TO 10 DO
:
WRITE(I:4)
5 6 7 8 9 10
The statement
FOR I ~= 10 D0WNT0 5 DO
WRITE(I:4)
10 9 8 7 6 5
PROGRAM PAYROLL;
(* COMPUTE EMPLOYEES' GROSS WAGES
VAR
NAME: STRING
HOURS RATE. GROSS, TOTAL: REAL;
BEGIN
TOTAL = 0; :
READLN(NAME)
WHILE NAME <> 'END OF DATA' DO
BEGIN
WRITE ('HOURS AND RATE? ); '
PROGRAM GRADES;
(* CONVERT NUMBER GRADES TO LETTER GRADES AND DISPLAY
GRADE DISTRIBUTION *)
VAR
NAME: STRING;
LETTERGRADE: CHAR;
NUMBERGRADE, ACOUNT, BCOUNT.
CCOUNT, DCOUNT, FCOUNT INTEGER; :
BEGIN
ACOUNT = :
BCOUNT = :
CCOUNT = :
DCOUNT = :
FCOUNT - :
WRITE 'NAME ?
(
1
'
)
READLN(NAME)
WHILE NAME <> END OF DATA' DO '
BEGIN
WRITE 'NUMBER GRADE?
(
'
) ;
READLN( NUMBERGRADE)
IF NUMBERGRADE > = 90 THEN
BEGIN
LETTERGRADE = A :
' '
;
ACOUNT = ACOUNT + 1 :
END
ELSE IF NUMBERGRADE ^=80 THEN
BEGIN
LETTERGRADE = B :
'
BCOUNT = BCOUNT +1 :
END
ELSE IF NUMBERGRADE > = 70 THEN
BEGIN
LETTERGRADE - C :
' '
;
CCOUNT = CCOUNT +1 :
END
ELSE IF NUMBERGRADE > = 60 THEN
BEGIN
LETTERGRADE = D' :
'
;
DCOUNT = DCOUNT + 1 :
END
ELSE
BEGIN
LETTERGRADE - F' :
'
;
FCOUNT = FCOUNT + 1 :
END;
WRITELNf 'GRADE FOR '
. NAME, '
IS LETTERGRADE)
WRITE 'NAME?
(
'
)
READLN(NAME)
END;
WRITELNf 'GRADE DISTRIBUTION' ) ;
END.
the keyboard, since we can see the results just by glancing through the
data. But if we imagine large amounts of data stored, say, on a disk file,
where we can't just glance through it, then the program becomes more
reasonable.
;; ; ; ; ; ; ; ) ; ; ; ;
PROGRAM HIGHANDLOW;
(* FIND HIGH AND LOW TEMPERATURES *)
VAR
HIGH, LOW, TEMPERATURE: INTEGER;
BEGIN
WRITE 'TEMPERATURE?(
'
)
READLN( TEMPERATURE)
LOW = TEMPERATURE;
:
HIGH = TEMPERATURE;
:
WRITE 'TEMPERATURE? (
'
)
READLN TEMPERATURE (
END;
WRITELN( 'LOW: '
. LOW)
WRITELN( 'HIGH: ', HIGH);
END.
PROGRAM INTEREST;
(» COMPUTE INTEREST ON SAVINGS ACCOUNT *)
VAR
AMOUNT, DEPOSIT, YEARLYRATE, MONTHLYRATE: REAL
N, MONTHS: INTEGER;
BEGIN
WRITE 'AMOUNT IN YOUR ACCOUNT NOW?
(
'
)
READLN (AMOUNT)
WRITE( 'MONTHLY DEPOSIT? ');
READLN (DEPOSIT)
WRITE 'YEARLY INTEREST RATE?
(
'
)
READLN (YEARLYRATE)
WRITE( 'NUMBER OF MONTHS? '
)
READLN (MONTHS)
YEARLYRATE := YEARLYRATE/100 . ;
MONTHLYRATE = YEARLYRATE/12 : . ;
FOR N = 1 TO MONTHS DO
:
BEGIN
AMOUNT := AMOUNT + DEPOSIT
AMOUNT = AMOUNT + MONTHLYRATE*AMOUNT
:
END;
WRITELNf 'AMOUNT IN ACCOUNT AFTER ', MONTHS,
MONTHS IS ', AM0UNT:8:2)
'
END.
selves to the built-in data types. In this section we will begin to look at
some of the data types that the We will be using
programmer can define.
programmer-defined data types extensively in later sections.
To begin with. Pascal classifies data types as simple, structured, and
pointer types. The simple types are those whose values are not made up
from simpler components. The structured data types are those whose val-
ues are made up of simpler components. The pointer types are those whose
values are used to locate data items in the computer's memory.
In this section we will confine ourselves to the simple data types. We
will begin to study the structured data types in the next section. The simple
data types are divided into scalar types and subrange types.
Scalar Data Types. Among the scalar data types we can distinguish be-
tween those that are built into the language and those that are defined by
the user.
The built-in, or standard, scalar data types are INTEGER, REAL,
BOOLEAX, and CHAR, all of which need no further introduction. Note
that the STRING data type, which is built into UCSD Pascal, is not a sim-
ple data type since its values (strings) are made up of simpler components
(characters).
Real numbers aren't suited for certain applications, such as counting.
For this reason the type REAL is something of a second-class citizen among
the scalar data types. You will often be told that a particular variable or
value can be of "any scalar type except REAL." Values of type REAL are
used only for doing real-number arithmetic. Values of other scalar types
have a wide variety of applications.
The user-defined scalar types are also called enumeration types, since
the programmer defines the type by listing, or enumerating, each of its
values.
We define an enumeration type by a type definition such as the follow-
ing:
TYPE
DAY = (SUN, MON, TUE, WED, THURS, FRI , SAT);
This defines new data type. The possible values of DAY are SUN.
DAY as a
MON, TUE, WED, THURS, FRI, and SAT. Note that the identifiers SUN.
MON. and so on now denote values in the same way as do TRUE, FALSE,
25, 3.14, and 'A'.
TYPE
DAY = (SUN, MON, TUE, WED, THURS, FRI, SAT);
VAR
D, E: DAY;
D :
= MON;
E :
= WED
are valid and give D the value MON and E the value WED. The assignment
D : = E;
TYPE
COLOR = ORANGE, YELLOW, GREEN, BLUE,
(RED,
INDIGO, VIOLET);
CHESSMAN = (PAWN, KNIGHT, BISHOP, ROOK,
,
QUEEN, KING);
MONTH = (JAN, FEB, MAR, APR, MAY, JUN, JULY,
AUG, SEPT, OCT, NOV, DEC);
GRADE = F D, C, B, A);
( ,
The identifiers that represent the values must be unique. The same
identifier cannot appear in more than one type definition.
Operators and Functions on Scalar Data Types. Each of the scalar data
types is ordered. That is, the values of each type are arranged in a partic-
ular order, so we can always say that one value precedes, is equal to, or
follows another value. To the values of any scalar type we can apply the
six relational operators
For the standard data types, the order for integers and real numbers is
the usual numerical order. For Boolean values, FALSE precedes TRUE, so
that specifies the order of the characters. Although the collating sequence
varies from one character code to another, invariably the letters are in al-
phabetical order and the digits are in numerical order. Thus
are true.
For enumeration types, the order of the values is the same as the order
)
in which they were listed in the type definition. For instance, if we define
the type OFFICER by
statement
causes the statement to be executed five times. The first time the value of
D is MON, the second time the value of D is TUE, and so on.
CASE M OF
PAWN: statement-1;
BISHOP: statement-2;
KNIGHT: statement-3 ;
ROOK: statement-4;
QUEEN: statement-5 ;
KING: statement-6
END
Subrange Types. For any scalar type except REAL, we can define a new
type whose values are a subrange of those of the original type. For in-
stance,
defines a subrange of type DAY. The values of type WORKDAY are MON,
TUE, WED, THURS, and FRI.
The following are examples of subranges of type INTEGER:
NUMBERGRADE = . . 100
DEGREE = 0. .359;
MINUTE - 0. .59;
The type used to define a subrange type is called the associated scalar
type. For WORKDAY, is DAY; for NUMBER-
the associated scalar type
GRADE, DEGREE, and MINUTE, the associated scalar type is INTEGER.
Any operations that can be performed on values of the associated sca-
lar type can also be performed on values of the subrange type. The only
difference is that when a value is assigned to a variable of the subrange
type, the computer checks to see if the value is in the proper range. If it
isn't, the program terminates with an error message.
;
VAR
I: INTEGER;
N: NUMBERGRADE;
The assignment
I : = N
N :
= I
is valid only if the value of I lies in the range through 100. Only integers
in this range are also values of type XUMBERGRADE.
Xow consider the two statements
N : = 80
N : = N + 25
VAR
D: DAY;
N: NUMBERGRADE;
VAR
D: (SUN, M0N, TUE, WED, THURS, FRI , SAT, SUN);
N: 0. .100;
P. 16 Arrays
One-dimensional Arrays. In Pascal, arrays are values of special data types
called array types. Array types are structured data types, since each array
value is made up of simpler components, the elements of the array.
We can define an array type as follows:
P. 16 Arrays 493
TYPE
LIST = ARRAY [1.. 5] OF INTEGER;
This definition refers to two other data types. The type whose descrip-
tion is enclosed in brackets is the index type. (Index is a synonym for sub-
script.) The subscripts used to designate particular elements of an array
value must be of the index type. Index types may be any simple type except
REAL or INTEGER. Subranges of type INTEGER are allowed, however,
and are in fact the most commonly used index types.
The data type following the word OF is the component type. It is the
type of the components, or elements, of the array values.
Thus the definition of LIST says that each value of type LIST is an
array of five integers and that the five integers are labeled 1 through 5. Note
that if we define LISTl by
then each value of type LISTl is also an array of five integers, but the
integers are labeled 6 through 10 instead of 1 through 5. Figure P-14 shows
typical values of LIST and LISTl.
Now let's declare two variables of type LIST:
VAR
A, B: LIST;
Suppose the value of A is the value of type LIST given in Figure P-14. We
can refer to the individual components of the value using a subscript en-
closed in brackets. The value of the subscript must belong to the index
type. Thus, the value of A[l] is 25; the value of A[2] is -5; the value of
A[3] is 11; and so on.
We
can use any expression as a subscript as long as the value of the
expression belongs to the index type. If I, J, and K are integer variables,
then
LIST LISTl
25 30
1 6
-5 18
2 7
11 -1
3 8
9
99
4
-8 65
5 10
494 Pascal Supplement
are valid, provided that in each case the value of the subscript expression
is an integer in the range 1 through 5.
We can assign the value of one array variable to another array variable
of the same type. Since A and B are both of type LIST, the assignment
B : = A
A[l] : = 13;
A[5] :
= 29
A 13
-5
11
29
Arrays must be read in and printed out element by element. For ex-
ample, to print the elements of the array A, we can use:
FOR I- 1 TO 5 DO
:
13 -5 11 29
FOR I : = 1 TO 5 DO
READ A ( [
I ] )
7 9 -5 3 2
then A[l] would be assigned the value 7; A[2]. the value 9; A[3], the value
- 5: and so on.
Figure P-15 shows a Pascal program corresponding to the binary-search
algorithm DIRECTORY in Chapter 8. Note how a single FOR statement is
used to read in the values of the two parallel arrays NAME and NUMBER.
P.16 Arrays 495
PROGRAM DIRECTORY;
(* DEMONSTRATE TABLE LOOKUP USING BINARY SEARCH *)
CONST
LIMIT - 50: (* MAXIMUM SIZE OF DIRECTORY *)
TYPE
COLUMN = ARRAY[1. .LIMIT] OF STRING;
VAR
LOW, HIGH, MIDDLE, I, N: INTEGER;
DESIREDNAME: STRING;
NAME, NUMBER: COLUMN;
BEGIN
WRITE! 'NUMBER OF ENTRIES IN DIRECTORY '
)
READLN I
BEGIN
WRITELN 'ENTRY NUMBER ', I, ':');
(
WRITE! 'NAME?
READLN! NAME[ I] )
WRITE! 'NUMBER 9
READLN! NUMBER[ I]
END;
WRITELN! 'DIRECTORY ENTRY COMPLETE
WRITE! 'NAME TO LOOK UP? '
READLN (DESIREDNAME .
HIGH - N; :
REPEAT
MIDDLE := (LOW^HIGH) DIV 2;
IF DESIREDNAME < NAME [MIDDLE] THEN
HIGH = MIDDLE- 1 :
ELSE
WRITELN 'THE NAME YOU REQUESTED IS NOT LISTED' );
(
READLN DESIREDNAME(
en:
END
CONST
LIMIT = 50;
CONST
LIMIT = 75;
instead of having to go through the whole program looking for 50s and
changing them to 75s. Second, the word LIMIT suggests to a human reader
the purpose for which the constant is used, something that 50 and 75 do
not do.
Note that LIMIT is used to define the index type in the array-type def-
inition:
We could not have used a variable in place of LIMIT; only constants can
be used to define subrange types.
In a program, constant definitions come before type definitions. The
required order is
constant definitions
type definitions
variable declarations
TYPE
TABLE = ARRAY [1.. 3, 1..4] OF INTEGER;
defines the type TABLE whose values are tables of integers, each contain-
ing three rows and four columns. Values of type 1 3 are used to label the
. .
VAR
T: TABLE;
Columns
1 2 3 4
1 7 80 9 -3
Rows 2 4 6 12 30
3 25 7 14 3
READ T ( [ I , J ] )
FOR J = : 1 TO 4 DO
READ T ( [ I , J ]
This statement reads values for the row determined by the value of I, for
the Ith row, so to speak.
Now let's vary I from 1 through 3:
FOR I = 1 TO 3 DO
:
FOR J = 1 TO 4 DO
:
READ(T[I, J])
For I equal to 1, the values for the first row are read; for I equal to 2, the
values for the second row are read; for I equal to 3, the values for the third
row are read. Thus the value of T is read in row by row. If the input data
is
7 80 9 -3 4 6 12 30 25 7 14 3
498 Pascal Supplement
then the value read for T will be that shown in Figure P-16.
We could read in the array by columns instead of rows just by revers-
ing the order of the two FOR statements:
FOR J = 1 TO 4 DO
:
FOR I = 1 TO 3 DO
:
READ(T[I, J])
We can use the same technique for printing the values of an array. For
instance,
FOR I = 1 TO 3 DO
:
FOR J = 1 TO 4 DO
:
WRITE(T[I, J]:4)
prints out the array by rows. All the values are printed out on one line,
however. We
can print the array in table form by using a WRITELN state-
ment to make the printer go to a new line after each row is printed out:
FOR I = :
1 TO 3 DO
BEGIN
FOR J = 1 TO 4 DO
:
WRITE(T[I, J]:4);
WRITELN
END
P. 17 Functions
A function declaration in Pascal has the same form as a program except the
program heading is replaced by a function heading. For example, consider
PROGRAM AVERAGES;
(* COMPUTE AND DISPLAY AVERAGE GRADES BY CLASS AND MAJOR *)
VAR
CLASS, MAJOR, GRADE: INTEGER;
TOTAL, COUNT: ARRAY [1.. 4, 1..3] OF INTEGER;
AVERAGE: ARRAY 1 4 1..3] OF REAL; [ . . ,
FOR MAJOR = 1 TO 3 DO :
BEGIN
TOTAL [CLASS, MAJOR - 0;
COUNT [CLASS, MAJOR = 0;
END;
(* READ DATA, ACCUMULATE COUNTS AND TOTALS
WRITE! 'CLASS, MAJOR, AND GRADE' '); 7
FOR MAJOR = 1 TO 3 DO :
CLASSNAME[2] = 'SOPHOMORE'
CLASSNAME[3] = 'JUNIOR
CLASSNAME[4] = 'SENIOR
WRITELN( :9 'ENGLISH' 13.
'
'
HISTORY 13 MATHEMATICS ' : . ' ' : 13 )
FOR CLASS 1 TO 4 DO
:
BEGIN
WRITE (CLASSNAME [CLASS] :9) ;
FOR MAJOR = 1 TO 3 DO :
WRITELN
END
END
LENGTH and WIDTH are declared to be parameters of type REAL; that is,
only values of type REAL can be substituted for them.
Note that the first declaration ends with a semicolon but the second
one does not. In general, each declaration except the final one ends with a
semicolon. The final declaration is terminated by the closing parenthesis.
As with variable declarations, we can combine the declarations of formal
parameters that are declared to be of the same type:
The colon followed by the word REAL at the end of the function head-
ing specifies the type of the values that the function returns. Thus, the
function DIAGONAL returns values of type REAL.
As we indicate what value the function is
in the algorithmic language,
by assigning that value to the name of the function.
to return
The semicolon following the word END terminates the entire function
declaration.
Local variables for a function are declared in a variable declaration
program. For instance, the following is the Pascal version
part, just as for a
of the function FACTORIAL from Chapter 9:
= F*I;
F :
FACTORIAL = F :
END;
the calling program. No copy of the data has to be made. When large
amounts of data are involved, then, it is usually more efficient to use var-
iable parameters instead of value parameters.
For instance, consider the function SUM defined in Chapter 9. Sup-
pose the array A is of type
FOR I = : 1 TO N DO
S :
= S + A [ I ] ;
SUM :
= S
END;
Procedures. Procedures have the same form as programs and functions ex-
cept a procedure heading replaces the program or function heading:
ment to the procedure name, since procedures use the formal parameters
to return values. The parameters LENGTH and WIDTH, used to supply
data, are declared as value parameters; AREA and DIAGONAL, used to
502 Pascal Supplement
W = 12.0;
:
X = 5.0;
:
RECTANGLE(W, X, Y, Z)
assign to —
Y and Z the values 60.0 and 13.0, respectively the area and
diagonal of a 12 x 5 rectangle.
The procedure call just given will work regardless of whether LENGTH
and WIDTH are value or variable parameters. If LENGTH and WIDTH are
value parameters, however, we could just write
constant definitions
type definitions
variabie declarations
function and procedure declarations
Another thing to notice about Figure P-18 is the type VECTOR, which
is used to declare the array A in the program SORTER and the formal pa-
P. 18 Variable Parameters and Procedures 503
PROGRAM SORTER;
(* "EXERCISE" THE PROCEDURE SORT *)
TYPE
VECTOR = ARRAY [1.. 50] OF INTEGER;
VAR
A; VECTOR;
I, SIZE: INTEGER;
FOR J = 1 TO N-l DO
:
LIST[J] = LIST[J + 1] :
;
LIST[J + 1] = TEMP; :
NOEXCHANGES = FALSE :
END
UNTIL NOEXCHANGES
END; (* SORT *)
FOR I = 1 TO SIZE DO
:
READ A I ( [ ] ) ;
SORT(A, SIZE)
WRITE( 'SORTED DATA: '
)
FOR I = 1 TO SIZE DO
:
WRITE! A[ I] :4)
END.
can be used to declare formal parameters. We must define the type VEC-
TOR in order to declare the formal parameter LIST.
504 Pascal Supplement
Blocks can be nested one inside another. In Figure P-18, for instance,
we have two blocks. One block extends from immediately after the program
heading to the end of the program. The other extends from immediately
after the procedure heading for SORT to the end of the procedure, that is,
to the end of the statement part of SORT.
Each block is immediately preceded by a program, function, or pro-
cedure heading. We can use the name of the program, function, or proce-
dure to name the following block.
In Figure P-18, for example, we have two blocks, SORTER and SORT.
SORTER extends from just after the program heading to the end of the pro-
gram. SORT extends from just after the procedure heading for SORT to the
end of the procedure.
It's blocks in complete programs. We will find it
difficult to visualize
easier instead to use diagrams that illustrate blocks and the variables de-
clared in each but leave out the rest of the details of the actual program.
Figure P-20 shows the diagram for the program SORTER. VECTOR, A,
I, and SIZE can be accessed from anywhere in the outer block, SORTER.
P. 19 Local and Global Variables 505
VAR
TEMP: INTEGER;
J,
NOEXCHANGES: BOOLEAN;
BEGIN
REPEAT
NOEXCHANGES = TRUE;
:
FOR J = 1 TO N-l DO
:
LIST[J] = LIST[J + 1]
: ;
LIST[J + 1] = TEMP; :
NOEXCHANGES - FALSE :
6>
END
UNTIL NOEXCHANGES
END;
FIGURE P-19. The procedure heading and block for the procedure SORT.
J, TEMP, and NOEXCHANGES can be accessed only from inside the inner
block, SORT. It's helpful to think of the boxes representing the blocks as
made of one-way glass. From inside the SORT box we can look out and see
VECTOR, A, I, and SIZE. But we cannot look into a box from the outside,
so J, TEMP, and NOEXCHANGES are hidden from the rest of the program.
Figure P-21 shows a more complicated example. We have a main pro-
gram named P. Inside P two functions or procedures (it doesn't matter
which) are declared. Finally, the function or procedure Ql contains a dec-
laration of another function or procedure, R.
The variables A and B are declared in the outermost block, the main
program P. They can be accessed from everywhere in the block P. Specifi-
cally, they can be accessed from P, Ql, Q2, and R.
variables C and D can be accessed from Ql and R. They cannot be
The
accessed from P or Q2. The variables E and F can only be accessed from R.
The variables H and I can only be accessed from Q2.
We use the terms iocaJ and giobai in Pascal as follows. Identifiers are
local to the block in which they are declared. Thus, C and D are local to
Ql; E and F are local to R; H and I are local to Q2. Identifiers declared in
the outermost block, which are accessible throughout the program, are
said to be global. Thus A and B are global variables in the program P.
Figure P-22 illustrates the situation in which the same identifier is de-
clared in more than one block. Thus we have an A in P and an A in Ql; a
B in P and a B in Q2; an F in Ql and an F in Q2.
Identifiers declared in different blocks have nothing to do with one
another, even though they are spelled in the same way. Thus the variable
A declared in P names a different memory location than the variable A
506 Pascal Supplement
SORTER
TYPE
VECTOR = ARRAY [1.. 50] OF INTEGER
VAR
A: VECTOR;
I. SIZE: INTEGER;
SORT
VAR
J, TEMP: INTEGER;
NOEXCHANGES: BOOLEAN;
FIGURE P-20. This diagram illustrates the blocks and declarations in the program SORTER.
VAR A. B: INTEGER;
Ql
VAR C, D: INTEGER;
R
VAR E T INTEGER;
Q2
VAR H, I: INTEGER;
FIGURE P-21. This diagram shows a main program P that contains declarations for proce-
dures Ql and Q2. Ql, in turn, contains a declaration for procedure R.
Ql nor to the global variable B from inside Q2. In each case the declaration
508 Pascal Supplement
VAR A. B C: INTEGER;
Ql
VAR A. F. G: INTEGER:
Q2
VAR B, F. H: INTEGER;
FIGURE P-22. This diagram shows a main program P that contains declarations for proce-
dures Ql and Q2. Variables named A are declared in P and Ql: variables named B are de-
clared in P and Q2; and variables named F are declared in Ql and Q2.
P. 20 Program Design
Figure P-24 shows a Pascal program corresponding to CRAPS, the algo-
rithm we used as an example of top-down design in Chapter 10. The Pascal
program uses a separate procedure for each module. Note that a function
declaration for the pseudorandom-number generator RANDOM is also pres-
ent. In the algorithmic language, we assume RANDOM to be a built-in
it is not built into Pascal.
function, but
Notice something peculiar about the Pascal program. Although top-
down design was praised in Chapter 10, the modules of the Pascal program
; ; : ; ) ) ; ; ;
PROGRAM GAME;
* PLAY GUESSING GAME WITH USER
( *
VAR
SEED: REAL;
ANSWER. CHAR;
NUMBER, GUESS: INTEGER;
END; (* RANDOM *)
-WRITELN
WRITELNI "I AM THINKING OF A NUMBER FROM 1 THROUGH 100.
WRITELN 'YOU ARE TO TRY TO GUESS THE NUMBER.
(
' )
REPEAT
NUMBER = RANDOM (100)
:
;
:TELN;
WRITE('I HAVE MY NUMBER. WHAT IS YOUR GUESS? ');
REPEAT
READLN (GUESS)
IF GUESS > NUMBER THEN
WRITE('TOO LARGE. TRY AGAIN: ')
ELSE IF GUESS < NUMBER THEN
WRITE ('TOO SMALL. TRY AGAIN: ')
UNTIL GUESS = NUMBER;
i'YOU ARE RIGHT. CONGRATULATIONS
.'.OULD YOU LIKE TO PLAY AGAIN?' ) :
READLN (ANSWER)
UNTIL ANSWER <> 'Y' ;
FIGURE P-23. The program GAME including the function RANDOM. Note that the global
variable SEED is accessible from both GAME and RANDOM.
This order results from a requirement of Pascal that functions and pro-
cedures be declared before they are used. Although the requirement sim-
plifies the design of Pascal compilers, it requires each function or proce-
dure to be declared before the functions or procedures that call it, and all
function and procedure declarations must precede the statement part of the
main program. For this reason, we sometimes hear people say that Pascal
top-down design.
isn't suitable for
The answer to this is that nothing forces us to write the modules in the
same order in which they will appear in the final program. If we work out
510 Pascal Supplement
PROGRAM CRAPS;
(* PLAY CRAPS WITH THE USER *)
VAR
AMOUNT, BET, SEED: REAL;
WON, FINISHED: BOOLEAN;
DIE2 = RANDOMf 6)
:
;
VALUE = DIE1+DIE2;
:
READLN(SEED)
WRITE! 'HOW MUCH MONEY DO YOU HAVE TO PLAY WITH? ); '
READLN! AMOUNT)
WHILE AMOUNT <= 0.0 DO
BEGIN
WRITELNf'YOU CANNOT PLAY WITH A ZERO OR NEGATIVE ); 1
FIGURE P-24. The program CRAPS including the function RANDOM and the procedures
ROLLDICE, INITIALIZE, ACCEPTBET. PLAY, and UPDATE.
our program on paper first, we can write the modules in whatever order
we please, then enter them into the computer in the order required by
Pascal.
If we create our programs at the computer terminal, we can take ad-
vantage of modern text editors that allow insertions to be made at any point
in the text being worked on. Thus we can start out writing the program
heading, the definitions and declarations for the main program, and the
statement part of the main program. Then we go back and write the func-
tion and procedure declarations, inserting each one in the position re-
quired by Pascal, but writing them in whatever order is most convenient
for us.
; ; ; ;
READLN(BET)
WHILE (BET < O.O) OR (BET > AMOUNT) DO
BEGIN
IF BET < 0.0 THEN
WRITELN('YOU CANNOT BET A NEGATIVE AMOUNT')
ELSE IF BET > AMOUNT THEN
WRITELNf 'YOU CANNOT BET MORE THAN YOU HAVE' );
WRITE 'PLEASE ENTER ANOTHER BET:
(
'
)
READLN(BET)
END
END; (* ACCEPT BET *)
WON - FALSE
:
ELSE
BEGIN
POINT = VALUE; :
REPEAT
ROLLDICEt VALUE)
UNTIL (VALUE = POINT) OR (VALUE =7);
WON := VALUE = POINT (* BOOLEAN EXPRESSION *)
END
END; (* PLAY *)
one value to a memory location, some of the bits in each location will be
wasted. Clearly, it would be more economical to store more than one value
in each location. This is called packing.
The drawback of packing is that access to the stored values is slower.
To retrieve a packed value, for instance, the computer must get the con-
tents of the memory location holding the value, then separate the desired
value from the other values sharing the same location. As a rule, the sec-
ond step takes much longer than the first.
Pascal allows us to declared packed arrays, which are stored with as
many component values packed into each memory location as possible. We
; ) ; ) ; ; ; ) ; ;
END:
WRITELNI 'YOU NOW HAVE ', AM0UNT:8:2, DOLLARS'); '
ELSE
BEGIN
WRITE( 'DO YOU WANT TO PLAY ANOTHER GAME ');
WRITE (YES OR NO)?
(
'
'
)
READLN ANSWER ( )
REPEAT
WRITELN;
ACCEPTBET BET AMOUNT ( , )
PLAY(WON)
UPDATE (BET. AMOUNT. WON, FINISHED)
UNTIL FINISHED;
WRITELNf'I ENJOYED PLAYING WITH YOU
WRITELN 'LET' 'S PLAY AGAIN SOON*
(
END.
N[5] := 'A';
C := N[l]
are valid.
There is one limitation on access to packed arrays. Subscripted vari-
ables such as N[7] that refer to elements of packed arrays cannot be substi-
tuted for variable parameters in procedure calls. Worse yet, the READ and
READLN statements in Pascal are considered calls to procedures with var-
iable parameters. Thus
READ (N [7])
READ(C)
N[7f = C :
N : = M
VAR
M, N: NAME;
M :
= 'JOHN JONES
N : = 'MARY ROBERTS
are valid. Note that the trailing blank spaces are required. Each value as-
signed to M or N must consist of exactly 20 characters. If a value is shorter
; ;
M < N
WRITE(N)
FOR I = 1 TO 20 DO
:
BEGIN
READ C ( )
N[I] := C
END
JOHNbJONESbbbbbbbbbb
where the blank spaces. The trailing blank spaces are re-
b's represent
quired; after typing JOHN JONES
the user must hit the space bar 10 times,
a procedure likely to leave the user muttering about the peculiarities of
computers.
P. 22 Variable-Length Strings
UCSD some other versions as well) provides a built-in
Pascal (and perhaps
data type STRING. Values of type STRING are variable-length strings,
which are often more convenient to work with than fixed-length strings.
The following example illustrates how string variables are declared:
VAR
S STRING [10]
T STRING [20];
U STRING;
) ) —
CONCAT (
' AL '
, ' TO '
, ' GET '
, ' HER '
is
'ALTOGETHER'
FIGURE P-25. The correspondence (such as it is) between string operators and functions in
the algorithmic language and string functions and procedures in UCSD Pascal.
S+T+U+ . . . C0NCAT(S, T, U, . .
.
where the string to be searched comes first, then the substring to be found.
In Pascal, however, we must write
inserts the value of SUBSTRING into the value of STRING at the position
given by the value of POSITION. The procedure
deletes characters from the value of STRING. The value of POSITION spec-
ifies where the characters will be deleted and the value of LENGTH speci-
fies how many.
In each procedure,STRING is a variable parameter; only a variable
may be substituted for it. The other parameters are value parameters.
For instance, suppose S is a string variable. Then after executing the
statements
S - 'ABCDEF'
:
INSERT 'XY' (
S, 4) ,
•ABCXYDEF'
If we now execute
DELETE(S, 5, 3)
•ABCXF'
PROGRAM FORMLETTER;
(* FILL IN NAME AND CITY IN FORM LETTER *)
VAR
L, I, J: INTEGER;
LINE, NAME, CITY, SOURCE DESTINATION: STRING;
INFILE, OUTFILE: TEXT;
BEGIN
WRITEf 'SOURCE FILE? '
)
READLNf SOURCE)
WRITE( 'DESTINATION FILE? ');
READLNf DESTINATION)
WRITE 'NAME?
(
'
)
READLN NAME ( )
READLNf CITY)
RESETflNFILE, SOURCE);
REWRITE OUTFILE DESTINATION
( , )
IF I <> THEN
BEGIN
L = LENGTH (LINE) :
;
FIGURE P-26. The program FORMLETTER. For the moment, ignore the calls to the file-ma-
nipulating procedures RESET, REWRITE, and CLOSE.
P.23 Records
Record types, each record value is
like array types, are structured types:
made up of simpler components. The differences between arrays and rec-
ords are as follows: (1) All of the components of an array have to be of the
same type; the components of a record can be of different types. (2) We
refer to the components of arrays using subscripts whose values can be
computed as the program executes; we refer to the components of records
using identifiers that must be specified when the program is written.
;;
TYPE
STUDENT = RECORD
NAME: STRING [20];
GPA: REAL;
CLASS: (FRESHMAN, SOPHOMORE,
JUNIOR, SENIOR)
END;
NAME, GPA, and CLASS are field identifiers; they allow us to refer
to the various components, or fields, of a record. For instance, suppose
we declare
VAR
S, T: STUDENT;
Then we can use [Link] to refer to the NAME field of the value of S,
[Link] to refer to the GPA field; and [Link] to refer to the CLASS field.
The statements
S NAME
. = MARY JONES: '
'
S GPA
.
= 3.5; :
[Link] = JUNIOR :
READLN( [Link])
and
WRITELN( [Link])
are valid, as is
G :
= 10.0*[Link] + 60.0
[Link] = 2.8; :
T CLASS
. = FRESHMAN :
S :
= T
Then if the value of I is the range 1 . . 2000, the value of U[I] is of type
STUDENT. The field designators
U [ I ] NAME .
U[I] .GPA
U [ I \ CLASS
]
WITH S DO statement
prefixes
S.
WITH S DO
BEGIN
NAME = 'JIM BURNS' :
GPA = 3.9; :
CLASS = SENIOR :
END
assigns new values to [Link], [Link], and [Link]. In the same way,
WITH U[I] DO
BEGIN
GPA = 3.7; :
CLASS = JUNIOR :
END
assigns new values to U[I].GPA and U[I]. CLASS. U[I].NAME remains un-
changed.
;
More Complicated Records. Record values can be nested. That is, the
components can themselves be record values, those rec-
of a record value
ord values can have still other record values as components, and so on.
For instance, suppose we define
NAMETYPE = RECORD
FIRST: STRING [10];
INITIAL: CHAR;
LAST: STRING [10]
END;
and
ADDRESSTYPE = RECORD
STREET: STRING [20];
CITY: STRING [10];
STATE: PACKED ARRAY [1.. 2] OF CHAR;
ZIP: PACKED ARRAY [1.. 5] OF CHAR
END;
STUDENT = RECORD
NAME: NAMETYPE;
ADDRESS: ADDRESSTYPE;
GPA: REAL;
CLASS: (FRESHMAN, SOPHOMORE,
JUNIOR, SENIOR)
END;
[Link] - 'JOHN':
[Link] = 'DOE'
:
WITH S DO statement
WITH S, NAME DO
BEGIN
WRITE 'FIRST NAME?
(
*
)
READLN( FIRST)
WRITE 'MIDDLE INITIAL?
(
'
)
READLN( INITIAL)
WRITE 'LAST NAME?
(
'
)
READLN(LAST)
END
GPA = : 2.7
END
changes [Link], [Link], and [Link].
EMPLOYEE = RECORD
NAME: STRING [20];
CASE SALARIED: BOOLEAN OF
TRUE: (SALARY: REAL);
FALSE: (HOURS,
RATE: REAL)
END;
522 Pascal Supplement
The fields NAME and SALARIED constitute the fixed part of the rec-
ord; all values of type EMPLOYEE have these fields. The remainder of the
record is the variant part. If the value of SALARIED is TRUE, the variant
part of the record has just one field, SALARY. If the value of SALARIED is
FALSE, the variant part has two fields, HOURS and RATE. The variant
part always comes at the end of the record.
Put another way, if the value of SALARIED is TRUE, then the record
has the structure
RECORD
NAME: STRING [20];
SALARIED: BOOLEAN;
SALARY: REAL
END
On the other hand, if the value of SALARIED is FALSE, then the record
has the structure
RECORD
NAME: STRING [20];
SALARIED: BOOLEAN;
HOURS,
RATE: REAL
END
P: t INTEGER;
;
NEW(P)
creates a new integer variable and sets P to point to it. P f , which now
designates the newly created variable, can be used like any other variable.
Thus
Pt :
= 25
WRITE(P| :4)
DISPOSE(P)
P :
= NIL
PTR = t CELL
CELL = RECORD
VALUE: INTEGER;
LINK: PTR
END;
;
and declare
FIRST: PTR;
The value of FIRST points to a memory area that holds a value of type
CELL. That memory area contains an integer value and a pointer to another
memory area holding an integer value and a pointer, and so on. The situ-
ation is pictured in Figure 14-4. The link component of the last cell on the
list contains the value NIL, which acts as an end-of-list sentinel.
Pt -LINK = Q; :
Q t VALUE = V
• :
END;
P. 25 Sequential Files
A file is a sequence of values stored in auxiliary memory. All of the values
belong to the same data type. The number of values stored is not fixed but
may vary as the file is manipulated.
Values stored in a file must be transferred to main memory one by one
for processing. At any time, we only have access to the value that is cur-
rently in main memory. It's as if we had a window into the file through
which we could see only one value. We can move the window around in
the file, so at different times we can see different values through it. But at
P. 25 Sequential Files 525
one time the only value we have access to is the one we can see through
the window.
In Pascal, we can define a file type and declare a variable to be of that
type as follows:
TYPE
DATA = FILE OF INTEGER;
VAR
F: DATA;
2 4 8 6 4 -2 -5 25
7
100
3 18
(empty sequence]
F is a variable of type DATA. Therefore, the value of F is a sequence
of integers. For the sake of an example, let's assume the value of F is:
9 5 4 7 2
At any one time, we have access to only one of these values, the one
currently inmain memory, the one that can be seen through the file win-
dow. Associated with each file variable F is another variable, F | called ,
the buffer variable, whose value is the currently accessible value of the
We can think of F t as our window into the file, through which
file. we
can see exactly one value.
For example, we can indicate the position of the window into the file
as follows:
9 5 4 7 2
Ft
I :
= F|
WRITE(Ft )
stop. To position the file window over the first component of the file, we
use the built-in procedure RESET. After executing
RESET F (
9 5 4 7 2
F|
file window forward one position using the built-in procedure GET. After
executing
GET F (
9 5 4 7 2
Ft
9 5 4 7 2
Ft
In this situation, the value of F t is undefined, and the effect of any fur-
ther calls to GET is unpredictable.
The program must be won't attempt
able to detect this situation, so it
if it has not.
SUM = : ;
RESET F ( ) ;
GET(F)
END
REWRITE! F)
Ft
F| :
= 5
5
Ft
PUT(F)
5
Ft
The value 5 has been transferred to auxiliary memory and the window is
Ft : = 7;
PUT F (
5 7
Ft
and so on.
As an example of output to a sequential file, the following statements
store the integers from 1 through 100 in F:
REWRITE(F)
FOR I = 1 TO 100 DO
:
BEGIN
Ft := I;
PUT F (
END
528 Pascal Supplement
F: TEXT;
ABCD
EFG
HIJKL
Pascal does not allow the user's program access to the line-separator
character. The reason computer systems use different char-
is that different
acters to separate lines. A
program written to recognize the line-separator
character used by one system wouldn't work properly on another system
that uses a different line-separator character.
To prevent programs from depending on a particular line-separator
character, Pascal does two things:
1. When the file window is positioned over a line separator, the value of
the buffer variable is a blank space, not the line-separator character.
FALSE when it is not. The program uses EOLN to recognize the end of a
line.
READ(F, C)
)
is equivalent to
C := F| ;
GET F (
and
WRITE(F, C)
is equivalent to
F| :
= C;
PUT C (
READ(F, V)
WRITE(F, E)
converts the value of E into a string of characters and writes those charac-
ters to F. As we already know, field-width parameters can be supplied to
specify how the values will be written.
(In UCSD Pascal, values of type STRING
can be both read and written.
Values of type BOOLEAN
cannot be written.)
The READ and WRITE procedures can read and write more than one
value in a single call. The statement
and
The procedure READLN moves the file window to the character fol-
lowing the next line separator. Thus
) ) ; ; ;
READLN F (
is equivalent to:
WRITELN(F)
is equivalent to:
READLN(F)
and
is equivalent to:
The Files INPUT and OUTPUT. Pascal has two standard files, INPUT and
OUTPUT, to which the following rules apply:
1. The files INPUT and OUTPUT are already declared when the program
begins execution. Declarations for them must not be included in the pro-
gram.
RESET (INPUT)
REWRITE (OUTPUT)
READLN(V1, V2, . •
• , VN) READLN (INPUT, VI, V2, ..., VN)
EOF EOF (INPUT)
WRITE (El, E2, . . , EN) WRITE (OUTPUT, El, E2 ..., EN) ,
WRITELN(E1, E2, . .
.
, EN WRITELN( OUTPUT, El, E2 EN
Thus the input and output statements that we have been using all
along, such as
read from the standard file INPUT and write to the standard file OUTPUT.
C = Ft
: ;
GET F (
GET(F)
C = FT
:
2. Executing RESET for an interactive file does not get the first character
)
from the file. The first character is not obtained until GET or READ is exe-
cuted.
F: FILE OF INTEGER;
but do nothing else to establish any connection between F and some exist-
ing then F represents a local or internal file. A local file exists during
file,
RESET(F, 'TESTDATA'
;
REWRITE(F, 'RESULTS')
Better yet, we can obtain the necessary file names from the user, in-
stead of writing them into the program. If S is a string variable, then we
can obtain the name of an already existing file as follows:
RESET (F, S)
READLN S ( )
REWRITE(F, S)
In UCSD Pascal, any file to which output has been sent must be
closed after use. Closing a file assures that all data has been transferred
from main memory to the file and that all necessary information about the
file has been entered in the directory for the disk on which it is stored. In
UCSD Pascal,
CLOSE(F, LOCK)
CLOSE(F, PURGE)
transaction file and for listing (displaying the contents of) the master file
RECORD
KEY: INTEGER;
BALANCE: REAL
END
RECORD
KEY: INTEGER;
KIND: TRANSTYPE;
AMOUNT: REAL
END
:-.- -
,-.-:.' psatemaster
i
* create a master file
SENTINEL = 9999:
TYPE
MASTER - RECORD
KEY: INTEGER:
BALANCE: REAL
END;
VAR
MASTERFILE: FILE OF MASTER:
FILENAME: STRING;
BEGIN
WRITEI 'FILE NAME 9 '
)
READLNf FILENAME)
REWRITE (MASTERFILE. FILENAME)
WHILE NOT EOF (INPUT) DO
BEGIN
WRITEI 'KEY AND BALANCE 9 '
)
PUT (MASTERFILE
CLOSE (MASTERFILE. LOC
END.
; ;
'
? i. A . c
: TRANSACTION FILE *
sentinel = 5999
READLN FILENAME)
(
PROGRAM LISTMASTER;
(* PRINT LISTING OF MASTER FILE *)
CONST
SENTINEL = 9999;
TYPE
MASTER = RECORD
KEY: INTEGER;
BALANCE: REAL
END;
VAR
MASTERFILE: FILE OF MASTER;
FILENAME: STRING;
BEGIN
WRITE 'FILE NAME?
(
'
)
READLN( FILENAME)
RESET MASTERFILE FILENAME
( , )
WRITELN KEY 10 (
' BALANCE 10
' : . ' ' : )
GET (MASTERFILE)
END
END
SEEK(F, 5)
PROGRAM FILEUPDATE;
(* UPDATE MASTER FILE FROM TRANSACTION FILE *)
CONST
SENTINEL = 9999;
TYPE
TRANSTYPE = (ADD, UPDATE, DELETE);
MASTER = RECORD
KEY: INTEGER;
BALANCE; REAL;
END;
TRANSACTION = RECORD
KEY: INTEGER;
KIND: TRANSTYPE;
AMOUNT: REAL
END;
VAR
CURRENTKEY: INTEGER;
OLDFILE, NEWFILE: FILE OF MASTER;
TRANSFILE: FILE OF TRANSACTION;
INUSE: BOOLEAN;
PROCEDURE OPENFILES;
(* GET FILE NAMES, RESET OLDFILE AND TRANSFILE,
REWRITE NEWFILE. RESETTING OLDFILE AND NEWFILE
GETS THE FIRST RECORD OF EACH FILE *)
VAR
OLDMASTER. NEWMASTER, TRANS: STRING;
BEGIN
WRITE( 'OLD MASTER FILE? '
)
READLN( OLDMASTER)
WRITE) 'TRANSACTION FILE? '
) ;
READLNf TRANS) ;
FIGURE P-30. The program FILEUPDATE including the procedures OPENFILES, GET-
NEXTKEY, ADDRECORD, UPDATERECORD, DELETERECORD, and PROCESSTRANSAC-
TIONS.
Although SEEK positions the file window, it does not transfer any data
between the buffer variable F | and the file. SEEK must be followed by
GET to transfer a record from the file to the buffer variable or by PUT to
transfer a record from the buffer variable to the file.
Thus
SEEK(F, 5);
GET(F)
locates record 5 of file F and transfers that record to the buffer variable F f
On the other hand,
=
PROCEDURE GETNEXTKEY;
(* SET CURRENTKEY TO NEXT KEY TO BE PROCESSED. IF CURRENTKEY IS
THE KEY OF A RECORD IN THE MASTER FILE, THEN PLACE THAT
RECORD IN NEWFILE! SET INUSE TO TRUE, AND READ ANOTHER
,
NEWFILE t = OLDFILE | :
;
INUSE = TRUE;
:
GET (OLDFILE)
END
ELSE
BEGIN
CURRENTKEY := TRANSFILE t KEY .
;
INUSE = FALSE
:
END
END ; * GETNEXTKEY *
(
)
PROCEDURE ADDRECORD;
(* ADD ONE RECORD *)
BEGIN
IF INUSE THEN
BEGIN
WRITE! 'CANNOT ADD RECORD ', CURRENTKEY);
WRITELNf '—-RECORD ALREADY IN MASTER FILE")
END
ELSE
BEGIN
NEWFILE t KEY := TRANSFILE T KEY;
NEWFILE t BALANCE := TRANSFILE t .AMOUNT;
INUSE TRUE :
END
END; (* ADDRECORD *)
PROCEDURE UPDATERECORD;
(* UPDATE ONE RECORD •)
BEGIN
IF INUSE THEN
NEWFILEf .BALANCE := NEWFILE f BALANCE + TRANSFILE . | . AMOUNT
ELSE
BEGIN
WRITE! 'CANNOT UPDATE RECORD '. CURRENTKEY);
WRITELNf '
—
RECORD NOT IN MASTER FILE')
END
END; (* UPDATERECORD *)
SEEK(F, 25);
PUT(F)
P.27 Sets
Sets in Pascal do not correspond to anything in the algorithmic language.
For this reason, they have been saved until last and are covered fairly
briefly.
; ; ; j
PROCEDURE DELETERECORD;
(» DELETE ONE RECORD *)
BEGIN
IF INUSE THEN
INUSE = FALSE :
ELSE
beg:::
write 'cannot delete record ', currentkey
(
writelnf '
—
record not in master file
e:;g
END; (* DELETE RECORD *)
PROCEDURE PROCESSTRANSACTIONS;
(* PROCESS ALL TRANSACTIONS 7/HOSE KEYS ARE EQUAL TO
CURRENTKEY *)
BEGIN
WHILE TRANSFILE* .KEY = CURRENTKEY DO
BEGIN
CASE TRANSFILE * .KIND OF
ADD: ADDRECORD;
UPDATE: UPDATERECORD;
DELETE: DELETERECORD
END;
GET (TRANSFILE)
END
END; (* PROCESSTRANSACTIONS *)
contains the values 1, 3, 11, and [Link] that Pascal uses the square
brackets [ and ] in place of the braces and } used in mathematics.
{
We can describe sets that contain ranges of values. Thus the set
The set
[]
3 IN [1, 3, 9, 20]
is true, while
4 IN [1, 3, 9, 20]
is false.
Set Types. The following examples show how set types are defined:
The type following the work OF is called the base type. All of the
elements of a set of a given type must belong to the base type. If we declare
VAR
S: LETTERSET;
T: C0L0RSET;
P.27 Sets 541
then
BOOLEAN
CHAR
0..4079
Any enumeration type with 4080 or fewer values
Operations on Sets. Three operations that can be applied to sets and yield
sets as results are union, intersection, and difference.
The union of two sets contains those elements belonging to either of
the two sets or to both. In Pascal, union is represented by the + sign;
The difference of two sets contains those elements of the first set that
do not belong to the second. In Pascal, set difference is represented by a
- sign:
Sets can be compared for equality and for one set being a subset or a
superset of another.
Two sets are equal if they contain the same elements and are unequal
otherwise. As usual in Pascal, we represent the relational operator for
equality by = and for inequality by <>. Each of the following conditions
is true:
[1, 5, 8, 9] - [1, 5, 8, 9]
542 Pascal Supplement
[] = []
[1, 4, 5] <> [1, 4, 6]
[1, 4, 5] <> [1, 4, 5, 8]
If all of the elements of one set also belong to a second set, we say that
the first set is a subset of the second and the second set is a superset of the
first. In Pascal, the relational operator for subset is <= and for superset is
> = Each
. of the following conditions is true:
543
Index
design 191-202
of, one-dimensional, 144-163
Euclidean, 7-16 searching, 151-159
handwritten form of, 86 sorting, 159-164
printed form of, 85-86 two-dimensional, 163-167
testing of, 202-209 Arrays, parallel, 151-152
Algorithmic language, 10, 75-76 Array variable, 145
All-purpose machine, 5 and graphs, 357, 359
Artificial intelligence,
Alphabet ASCII code, 30
cipher, 233-234 Assembly language, 55-57
plaintext, 233 Assignment, 11-12, 92-97
545
546 Index
comparison 110of,
Data types, 76-79
concatenation of, 219-222 Decimal number system, 31
examples of processing, 226-230 Decision symbol, 15
Declarations, record, 261-262
fixed and variable length, 215-217
memory management 217-219for,
DECLARE (statement), 218
operations and functions on, 219-226 DELETE_ AFTER (procedure), 290-291
representation in memory, 215-219 DELETE (procedure), 297, 299
substrings, 222-225
DELETE_RECORD (procedure), 374
331 Design
Chip, silicon, 25 of algorithms, 191-202
Index 547
M
O
Machine design, graphs in, 356-357
Machine language, 54-55 Object program, 58
Magnetic disks, 26-27, 365-366, Octal notation, 37-39
385-387 ODD_INTEGER_SUM (algorithm), 136
Magnetic tape, 26-27, 365-366 One-dimensional arrays, 144-163
Main memory, 23-24 One-way selection, 110-112
of hypothetical computer, 43-44 Operating system, 59-62
Main storage (see Main memory) Operations, on binary values, 33-37
Maps, and graphs, 337, 355-356 Operator node, 324ff.
Mass storage, 23 Operator priorities
Master file, 367ff. for arithmetic operators, 82-84
MAX (function), 176-177 for logical operators, 124-125
Memory for relational operators, 124-125
auxiliary, 23-24, 26-27, 365-366 use in translating expressions, 242-249
main, 23-24, 43-44 Operators
Memory cells, 24 arithmetic, 80-84
Memory locations, 24, 90-91 assignment, 11-12
MERGE (algorithm), 376 character string, 219-222
Merge sort, 376-377 logical, 120-125
Merging, 371, 374ff. relational, 109-110
Microprocessor, 25 Optimizing compilers, 329-330
Microprocessor revolution, 25 Origin, of coordinate line, 430
Microprogramming, 63 OR (logical operator), 120-125
MID (function), 222-223, 226ff. OR-merge, 399-400
Minimax technique, 332-334 OR operation, on binary values, 35, 37
Mnemonic, 46 Output devices, 23-26
MOD (operator), 11-12, 393 OUTPUT (statement), 79-80, 97-98
Modularity, 191-192 for sequential file processing, 366-367
Module, 191-192 Overflow area, 389, 391-392, 394-395
550 Index
siblings, 303ff.
sister ofnode. 303
Table, array as, 144 son of node, 303
Tangent line. 434-436, 444 subtree, 303ff.
0-314-63243-3
mbbkhbii