(Latest Revision: 09/12/2000)
Hints to Help You Implement the Stack
CONSIDER DECIMAL DIGIT SELECTION:
Suppose you have a decimal display with a capacity of 8
digits. You can then display a number such as:
12938761
If you wish, you can think of this as a stack with 4 numbers on
it: 61, 87, 93, and 12.
You can start with an original value of
00000000
When you want push 12 onto the stack, you put the 12 into the
rightmost two digits:
00000012
When you want to push 93 onto the stack that already contains
12, you shift the 12 over to the left and put the 93 into the
rightmost two digits:
00001293
It's similar to push 87 and then 61
00129387
12938761
If the display is limited to 8 digits, then there is no more
room for more elements to be pushed onto the stack.
At first you may think that you can store any set of four
two-digit numbers this way. However what does 00000000 mean?
Is this an empty stack or is this a full stack that contains
four zeros?
One way to get around this ambiguity is to let 00000000
represent an empty stack, and to agree that we will place only
numbers in the range 01-99 on the stack.
How can we program instructions to place an element on the
stack? There is a really easy way to do it with arithmetic.
For example we can push 87 onto 00001293 by just multiplying by
100 and adding 87:
00001293*100+87 equals 00129387
It is also easy to pop something using the % and / operators.
For example,
00129387 % 100 equals 87 (the top element of the stack), and
00129387 / 100 equals 00001293 (the stack after the top has
been popped off-- assuming that C-style integer divsion has
"thrown away" the decimal part.)
How can you test to see if the stack is full? The biggest
number you can express with 8 digits is 99999999 (99,999,999).
Suppose you want to push 25 onto the stack. If stack*100+25 is
more than 99,999,999 then there is no room. Basically if you
don't have room to push 99, then the stack is full. So you
just need to check to see if stack*100+99 is more than
99,999,999.
MODIFY IT TO WORK ON CHARACTERS:
The idea above works well when you are interested in storing
numbers in the range 1-99. It can also work when you want to
store characters in the range 'a'-'z'. One could use exactly
the scheme described above, except just push numbers in the
range 1-26 and ignore the numbers from 27-99. However this
wastes space. This stack will probably have a
smaller-than-optimal capacity. (Remember: The program
specifications require that your implementation have room for
at least six characters when the program is compiled and
executed on the Sun Ultra's.)
You can conserve capacity better by using a smaller "modulus."
There is really nothing special about using modulus 100.
At first glance the stack operations are easier to understand
when the modulus is a power of 10. That is because we are
accustomed to representing numbers in base-10 notation.
However, it's easy to use the same idea with a different type
of modulus. For example, it will work to push by doing
data=data*27+code, where code is in the range 1-26.
Of course, in this case the stack top is data%27, and if you
pop the stack the new stack is data/27.
The actual number you will be working with (the class member
called data) is an unsigned long int. The maximum value it can
store is a constant called ULONG_MAX, which is defined in
"limits.h". The actual value of ULONG_MAX can vary from system
to system. Mainly the issue is how many bits are allocated to
representing an unsigned long int. The more bits, the larger
the number can be before it overflows.
Basically you can test for a full stack by seeing if data*27+26
> ULONG_MAX. However you have to make sure that in the course
of doing your test you don't overflow something that the
computer is storing as an unsigned long int. In other words,
don't directly tell the computer to compute data*27+26 because
this will sometimes cause an overflow. If an overflow occurs,
the result of the test will not be reliable. Instead, cast data
to a double first. After that it is safe to multiply by 27 and
add 26.