Next: Summary
Up: Algorithms
Previous: Desk-checking
Consider the following requirement specification:
A user has a list of numbers and wishes to find the minimum value and the maximum value in the list. A program is required which will allow the user to enter the numbers from the keyboard and which will calculate the minimum and maximum values that are input. The user is quite happy to enter a count of the numbers in the list before entering the numbers.
A first version at an algorithm for this might be:
initialise. get count of numbers. enter numbers and find maximum and minimum. output results.
The algorithm is now made completely general to allow for a list with no numbers in it, this may seem a bit stupid but it is not uncommon when writing a general-purpose function to allow for the possibility of null input. A user might change their mind after calling the program for example and it is sensible that the program should respond sensibly if the user enters zero for the count. Incorporating this into the algorithm above gives the next version:
initialise. get count of numbers. if count is zero then exit otherwise { enter numbers and find maximum and minimum. output results. }
Once the count of the numbers is known then a loop has to be executed that number of times, each time reading in a number and somehow using that number in finding the maximum and minimum of the numbers. In this loop the number of times the loop is executed is known, i.e. equal to the count of numbers. Thus another type of repetition command is introduced:
loop n times { body of loop. }
This operation of repeating some set of instructions, the
body of the loop, a set number of times occurs frequently in
algorithm design. Note that braces have been used to make the body of
the loop into a
compound statement. Each time the loop is executed it is the
instructions between the braces that are executed.
Hence the following version of the algorithm:
initialise. get count of numbers. if count is zero then exit otherwise { loop count times { enter a number. process the number. } output results. }
It has not yet been considered how to compute the maximum and minimum values so this has been indicated by using the phrase `process the number'. Given a large list of numbers written down on a sheet of paper how could the smallest number in the list be found in a methodical fashion? One way would be to start at the beginning of the list and work through the list systematically always remembering the smallest number seen so far, whenever a number is found smaller than the memorised number the memorised number is replaced by the smaller number. At the start of the list the smallest number yet seen is of course the first number, and when the end of the list is reached the memorised number is the smallest. Similarly for the largest number. Hence the following expansion:
get count of numbers. if count is zero then exit otherwise { get first number. set small to number. set large to number. loop count-1 times { enter a number. if number is less than small then set small to number. if number is greater than large then set large to number. } print small and large. }
In this algorithm no initialisation is required at the beginning, the only quantities that have to be initialised are small and large, and they are initialised to the first number entered by the user. Similarly count is entered by the user and requires no initialisation.
A brief reading of this should convince us that this algorithm is correct. If the user enters zero for the count then exit takes place immediately. If the user enters a non-zero count the first number is input, then the loop is executed count-1 times and one number is entered in each execution of the loop body. This means that 1 plus count-1 numbers are entered so all input numbers are considered. Large and small are initialised to the first number entered and each time round the loop are updated if the current number is larger or smaller than the memorised large or small. The boundary case where the count is zero has been considered but there is another boundary case here, namely count equal to one. If count is equal to 1 then large and small are set to the single number and the loop is executed zero times, hence when large and small are output they are set to the only number input, which is the correct result.
It is worth checking this algorithm by doing a simple desk check, say with the following data:
count = 5 numbers are 3 5 1 7 2The different values taken during the algorithm are as follows:
count number large small - - - - begin 5 - - - enter count 5 3 3 3 enter first number 5 5 5 3 first loop execution 5 1 5 1 second loop execution 5 7 7 1 third loop execution 5 2 7 1 final loop execution
The symbol `-
' has been used to indicate an unknown value.
At the end of execution of the algorithm large and small do hold the correct
maximum and minimum values