Algorithms Handout
Algorithms Handout
Algorithms Handout
Informally, think of algorithm as just a fancy word for recipe or rule of procedure. A recipe is
nothing but a sequence of steps that instruct a cook in preparation of a particular dish. The
following recipe for salmon furnishes an example of an algorithm:
1. Take a to pound salmon and allow it to swim in clear water for hours.
2. Scale and fillet the salmon.
3. Rub fillets with butter and season with salt and pepper.
4. Place on cedar board and bake in oven set at for minutes.
5. Throw away salmon and eat cedar board.
While a recipe describes the ingredients and the sequence of steps required to convert the
ingredients into a dish, an algorithm describes the input data and sequence of steps to generate
the required output from the given input. Just as there are many recipes to make a dish, a
problem or class of problems may have many different algorithms. And, for each such algorithm,
there can be many different implementations of computer programs.
Input. The algorithm receives zero or more inputs taken from a specified set of objects.
Output. The algorithm produces one or more output which have a relation to the inputs.
Precision. The steps are precisely and rigorously stated without cause for any ambiguity in
their actions.
Finiteness. The algorithm must terminate after a finite number of steps are executed.
Uniqueness: The intermediate results of each step of execution are uniquely defined and
depend only on the input to and results of the preceding steps.
Generality. To be interesting, the algorithm must solve the problem for a general set of
inputs.
Finally, a word about why the subject of algorithms is important and useful. One specific reason is
that algorithms are the basis of all computer programs and thus this subject underlines the entire
field of computing and computer science. A more general reason is that the discipline of
algorithmic thinking is valuable in carrying out any non-trivial project because it aids in the
planning of such tasks and, in particular, helps avoidance of errors by forcing a consideration of
all possibilities. This latter point is crucial when designing a large system such as a manned lunar
probe, where forgetting even the smallest detail will lead to catastrophic results.
1 / 12
Brief Introduction to Algorithms [Prasanna Ghali]
Input: Algorithms must have the means of acquiring data from external means. For example,
an algorithm that computes the roots of a quadratic equation must receive
the coefficients as input.
Sequence: Algorithms must be able to perform actions in order, one after the other. A
majority of these sequential actions consist of arithmetic computations [addition,
subtraction, multiplication, division, and so on], relational comparisons [greater than, less
than, and so on], and testing logical conditions [equal to, not equal to, and so on].
Selection: Algorithms must have some means of selecting (or choosing) among two possible
courses of actions based on initial data, input values, and/or computed values.
Iteration: Algorithms must be able to repeatedly execute a collection of instructions, for a
fixed number of times or until some logical condition holds.
Output: At their conclusion, algorithms must have the means to report the results obtained
by executing the algorithm.
Expressing algorithms
The term algorithm is derived from the name of a ninth-century Arabic textbook author, Musa al-
Khowarizimi (son of Moses, native of Khowarizm). It is a word familiar to - although perhaps
quickly forgotten by - generations of secondary school students many of whom have learned
Euclid's algorithm, a rule for computing the greatest common divisor of two integers.
Indeed, algorithms are something most people use every day even when they've never heard of
the word. When using a recipe in a cookbook, the algorithm is the specific sequence of
instructions which the cook follows. The route information published by mapping apps provides
another example of an algorithm. In this case, the route is the specific sequence of directions that
must be followed to travel from a source location to a destination location. Often algorithms are
used implicitly, that is, without explicit thought about a sequence of steps. You just don't know it
or think about it much. Almost every activity in your lives can be modeled as algorithm: figuring
out what to wear, alphabetizing books on a shelf, folding laundry retrieved from a dryer, how to
navigate the grocery store to purchase weekly supplies, determining how to prioritize your tasks
for the day, and so on.
Computers are used to solve problems. However, before a computer can solve a problem it must
be given instructions for how to solve the problem. And to determine what these instructions are,
an algorithm, apart from any specific computer and any specific programming language, must be
devised to solve the problem. Algorithms intended to be executed or run or performed on a
computer must avoid imprecision and ambiguities because computers do exactly what they're
told and nothing more. They are notoriously poor at resolving ambiguities since they lack the
ability to read between the lines and they lack the skill to determine what was meant rather than
what was said. An informal instruction "please get me a glass of water" in a non-computing
context can be understood and accomplished by you and most humans but not by a computer. In
contrast, an algorithm is a sequence of steps that describes how to solve a problem and/or
complete a task, which will always give the correct result. For the previous non-computing "please
get me a glass of water" instruction, the algorithm might be
1. Go to the kitchen.
2. Pick up a glass.
3. Turn on the tap.
4. Put the glass under the running water and remove it once it is almost full.
5. Turn off the tap.
6. Take the glass back to the person who gave the instruction.
2 / 12
Brief Introduction to Algorithms [Prasanna Ghali]
It is reasonable to assume that you and most other humans would be able to follow these steps
and fetch the glass of water. However, from a computational context, no computer could execute
these steps. These steps are too informal, too lacking in precision. For example, how would a
computer execute the step "Go to the kitchen." Assuming the person requesting the glass of
water is on the patio, how does the computer navigate its way to the kitchen? How does the
computer open the door separating the patio from the kitchen. How does it avoid obstacles?
What has been said about the lack of precision in the first step is true for the remaining steps.
Another example in a computational context might be to "display the list of high scores" for a
video game. Again, informal instructions like this aren't precise; there's no way that a computer
could follow that instruction exactly, but you would get the general idea of what is meant and
what you have to do, which would be "go through each score in a table of scores for various
players, keeping track of the largest score and the player's name." These sorts of informal
descriptions are only useful for giving another human the general idea of what you mean, and
even then there's a risk that they won't properly understand it. In a computational context, the
video game's authors will have to implement the algorithm in more detail with more precise steps
before a programmer could author a program that executes the algorithm.
This exercise underscores an important point - you must specify exactly what you want the
computer to do. The computer does not "know what you mean" when you write something
vague, nor can it figure out an "etc." Instead, you must be able to describe exactly what you want
to do in a step-by-step fashion. Precisely describing the exact steps to perform a specific task is
somewhat tricky, as you are used to people implicitly understanding details you omit. Irrespective
of the programming language used, no computer will do that for you.
Describing and writing algorithms requires a notation for expressing a sequence of steps to be
performed. The options available to us include natural languages such as English and
programming languages such as Java, Python, C, C++, and so on.
Humans communicate in their daily lives using natural languages such as English, Spanish,
Japanese, and so on. However, human communications are too rich, ambiguous, and depend on
context. They lack structure and therefore would be hard to follow when used for expressing
computer science algorithms.
A programming language is at the other end of the spectrum - it is too rigid for expressing
solutions. When solving problems, you want to think at an abstract level. However, programming
languages shift the emphasis from how to solve the problem to tedious details of grammar and
syntax.
Rather than using natural languages or programming languages, an algorithm is better expressed
using one of two tools: pseudocode or flowchart.
3 / 12
Brief Introduction to Algorithms [Prasanna Ghali]
Writing pseudocode
Pseudocode involves thinking at an abstract level about the problem and using an English-like
representation of the solution. Pseudo is a prefix that means false, and to code a problem means
to put it in a programming language; therefore pseudocode means false code, or sentences that
appear to have been written in a computer programming language but don't necessarily follow
syntax rules of any specific language.
Pseudocode is flexible and provides a good compromise between natural and programming
languages because it is a planning tool, and not the final product. It is simple, readable, and has
no rigid rules to adhere to.
Any pseudocode must be able to represent the five common elements of any algorithm: input,
sequence, selection, iteration, and output. Sometimes, pseudocode is prefaced with a beginning
statement like and ended with a terminating statement like . The statements between
and look like English and are indented slightly so that and stand out.
Input
Output
Sequence
A sequence structure consists of computational statements that are executed in order, one after
the other. Basic arithmetic operations are written as:
A bit of terminology first. Each computational line in the pseudocode and more generally every
line of the pseudocode is labeled a statement. Each statement consists one or more expressions.
Line containing the text is a statement. This statement consists of expressions (from
left to right): , , and . Every expression consists of one or more operands and zero or
more operators. Operators represent actions while operands represent the objects on which
these actions are applied. In expression , symbol represents the operator while symbol
and value represent operands. While will always intrinsically describe an integer value ,
symbol specifies a variable. Think of a variable as a named memory location that can store
values. Unlike constant , the contents of a variable change during the course of execution of
the program.
In terms of execution, every expression evaluates to a value and a type (more on types in
subsequent lectures).
At line , statement means "Copy value into ." More generally, the statement
4 / 12
Brief Introduction to Algorithms [Prasanna Ghali]
means "Copy value of into ," or, equivalently, "Replace the current value of
by the value of ." For example, when the statement on line
is executed, the value of is copied into and the value of is unchanged. The symbol is
interpreted as "is assigned." We call symbol the assignment operator.
The relational operators , , , , , and have the usual meanings from algebra:
equal to, not equal to, greater than, greater than or equal to, less than, and less than equal to,
respectively. The thing to remember though is that relational expressions evaluate to a or
value. By convention, zero value is considered while any non-zero value evaluates
.
Logical expressions are mostly used to control the sequencing of steps. They allow the
pseudocode to make a decision based on multiple conditions. Each operand is considered to be a
condition that can be evaluated or . Then the values of the conditions are combined to
determine the overall value of the groupings or
grouping.
Selection
Input, output, and sequence statements are sequentially executed, that is, the statements are
executed in order one after the other. In contrast, a selection statement alters the sequential flow
of control by allowing one of two courses of action to take place depending on whether the
answer to a condition is or . An action that might or might not be executed can be
written as:
5 / 12
Brief Introduction to Algorithms [Prasanna Ghali]
Notice that the steps performed by the and clauses are indented slightly so that
they can stand out and can be easily discerned. Such conditional situations arise often in our daily
lives. For example:
In certain situations, the clause doesn't appear. For example, when there is a high
probability that it might rain, you would like to carry an umbrella to stay dry during your
commute. If rain is not forecast, you go about your commute as usual:
Line in the pseudocode contains text delimited by symbols and representing a comment.
Comments are not an intrinsic part of an algorithm but are instead present when the algorithm's
author wishes to convey explanatory information to readers of the algorithm.
Iteration operations
The fifth element represents repeat operations where a block of basic operations are repeatedly
executed until a certain condition is met:
Notice that the steps repeatedly performed by the statement are indented slightly so that
they can stand out and can be easily discerned. How does this work? First, is
evaluated. If it is , then the loop terminates and the step on line immediately following the
loop is executed. Instead, if is , then the algorithm executes the
in order, one by one. Here's an example that prints a table of numbers
and their corresponding squares:
6 / 12
Brief Introduction to Algorithms [Prasanna Ghali]
Let's embody the thought process you might apply in deciding how to make your trip from station
to station into an algorithm expressed in pseudocode:
Algorithm should be understandable even if you've never seen an algorithm before. You
may have noticed ways that might be improved. For example, suppose you know a long
walk is required to change from one line to another at station compared to some other station
. How might that fact be used by the algorithm? You should always be on the lookout for ways
in which an individual algorithm may be improved.
You may have also noted some ambiguities in . What do you do if two pairs of lines require
the same number of stops? How about the case where two lines have more than one station in
common? What if certain lines are less busy than other lines at certain parts of the day and thus it
is highly likely that you'd be able to find a seat? And, what if the more comfortable journey takes
more time than the less comfortable journey? How should algorithm decide between the
two options? These are not serious problems with because it is an algorithm intended for
consumption by humans who are usually pretty good at "reading between the lines" and using
situational contexts to resolve ambiguities.
7 / 12
Brief Introduction to Algorithms [Prasanna Ghali]
The input is the terminating index , and the output is the sum of the first terms of the series. If
you aren't familiar with summation notation , it means that you take the quantity after the
and evaluate it for each value of implied by the limit below the and the limit
above the and then add the evaluated values together. Thus, for example,
The algorithm receives a positive natural number as input and produces as output, , the
sum of the first terms of the series.
The first task of the algorithm is to initialize variables to their appropriate values. Lines and
initialize variable (keeping track of the summation computed so far) to and counter
(keeping track of the numbers whose reciprocals are to be computed) to .
condition to compute for all values of in the interval . Lines and are repeatedly
To test algorithm , we should check it by hand for several values of . Simulating the
execution of an algorithm for a specific input is called a trace. Here the minimum value of is ;
has no maximum since can be equal to any positive integer.
8 / 12
Brief Introduction to Algorithms [Prasanna Ghali]
Next, we show how the algorithm executes if the input, , is equal to . At lines and , the
algorithm sets to and to . At line , it assigns the value , which is since is , to .
The effect is to add to . At line , it adds [i.e., to , so that now has value . At
line , the algorithm tests whether equals . Because equals and equals , the algorithm
repeats lines and .
At line , the algorithm updates to . It then adds [i.e., ] to . At this point, the value of
is . Since now equals and therefore is not equal to , the algorithm repeats lines
and .
At line , the algorithm updates to . It then adds [i.e., ] to . At this point, the value of
is . Since equals , is now equal to . Therefore, the algorithm terminates.
The value, stored in , is the sum of the first three terms of the series: .
Recall that an algorithm must have the following characteristics: input, output, precision,
finiteness, uniqueness, and generality. Let's evaluate algorithm for these characteristics:
Input. The algorithm receives exactly one input - the terminating index - which can have
any of the infinite values of a positive natural number.
Precision. The algorithm is decomposed into simple sequential steps from lines through
each of which performs a specific action without any ambiguity.
Finiteness. This is where most algorithms have errors - it is especially important to test
boundary values: the minimum and maximum values. First, the counter is initialized to on
line . If [that is, is equivalent to ], the algorithm stops after one repetition since
line increments to ensuring that the condition on line will evaluate . There is no
maximum value for this algorithm. However large the value of is, is always incremented
by each repetition meaning that after repetitions will have a value of at which
point the condition on line will evaluate .
Generality. The algorithm works for all positive natural numbers of which an infinite number
exist.
Checking algorithm for small values of doesn't prove that the algorithm is correct. It
proves only that the algorithm is correct for the values that were tested! However, checking the
algorithm for small values of does give you confidence that the algorithm is correct. To prove
that the algorithm is correct, a mathematical technique such as mathematical induction could be
used. Such correctness proofs are beyond the scope of this basic introduction.
Drawing flowcharts
A flowchart is a combination of graphical symbols that are used to represent the logical flow of
data through a solution to a problem. When you create a flowchart, you draw geometric shapes
that contain the individual statements and that are connected with arrows.
A parallelogram represents an input symbol indicating that it contains input operations. The input
statement in English is written inside the parallelogram. The same symbol is used to represent an
output operation. Since the parallelogram is used to represent both input and output, it is often
called the input/output symbol, or I/O symbol.
9 / 12
Brief Introduction to Algorithms [Prasanna Ghali]
To implement selection and iteration structures, a decision symbol, which is shaped like a
diamond is used. The diamond usually contains a question, the answer to which is one of two
mutually exclusive options: or .
To show the correct sequence of these statements, flowlines represented by arrows are used to
connect these graphical symbols.
To be complete, a flowchart should include the two terminal symbols at each end: start and stop
symbols. These symbols are graphically represented by the lozenge shape.
Flowcharts are difficult to draw for complex algorithms compared to writing pseudocode.
diagrams.net is a free online tool for rendering flowcharts.
10 / 12
Brief Introduction to Algorithms [Prasanna Ghali]
something as trivial as counting and writing an algorithm to perform that task would be a true
test of your understanding of the concept of counting. Assume that an integer can be represented
as a sequence of digits , so that, for example, the number is
represented by with having a value of . Likewise, the
number is represented by with having a value of .
Test the algorithm for general values such as the number , the number , and , for all of
which . Test boundary conditions such as where , or where , or with
and with .
The following figure illustrates the flowchart corresponding to algorithm that adds
to an integer .
11 / 12
Brief Introduction to Algorithms [Prasanna Ghali]
Do you prefer the pseudocode or the flowchart? If this is your first introduction to both these
techniques, then I'd hazard a guess that you prefer the flowchart because it contains easy-to-
follow symbols. This notation was popular in the early days of computing but is no longer used
because it is quite unwieldy for all but quite small algorithms. Once you get used to pseudocode
notation, you'll find it easier to read and understand than flowcharts.
Exercises
The following problems are meant for exercising your knowledge of writing pseudocode and
flowcharting algorithms. The practice gained from developing algorithms, pseudocode, and
flowcharting will help you write more robust and elegant code. For each problem, write the
pseudocode and draw a flowchart for the algorithm that solves the problem. Before attempting to
write any algorithm, you should think carefully about precisely what it is you want to do and how
you're going to go about doing it.
1. This is a classic problem introduced to every computer science student. Write an algorithm
to make a peanut butter and jelly sandwich.
2. In the same vein as the previous question, think about the process of calling your friend
using a telephone. Next, provide an algorithm that can be followed by an inanimate robot to
make a call using a telephone.
3. Compute the area of a trapezoid.
4. Compute the factorial of a positive integer :
.
5. Write an algorithm that computes the sum of the first terms of the series .
12 / 12